二、说说RC522读卡器
我从淘宝里买来的读卡器模块如下:
读卡器与M1卡之间的通讯,首先要寻卡(Answer To Request),验证卡片类型
—-》防冲突检查(Anticollision Loop)选择一张卡片,返回该卡序列号;
—–》选择卡片(Select Tag),选择被选中的卡的序列号,返回卡的容量代码;
—–》三次互相确认(3 Pass Authentication)通过密码校验之后,三次互相认 证 之后可以通讯。
M1卡指令:
读(Read):读一个块;
写(Write):写一个块;
加值(Increment):对数值块进行加值;
减值(Decrement):对数值块进行减值;
存储(Restore):将块中数据保存到数据寄存器中;
传输(Transfer):将数据寄存器中内容写入到块中;
终止(Halt):将卡置于暂停工作状体。
三、RC522读卡器的使用–硬件部分
我使用了stm8s103来驱动RC522读卡器,硬件连接如下:
stm8s103引脚 RC522接口
3.3v ———- 3.3v
GND ——— GND
PC4 ——— SDA(NSS)
PC5(SPI_SCK) ——— SCK
PC6(SPI_MISO) ——— MISO
PC7(SPI_MOSI) ——— MOSI
至少接这6针。
使用stm8s芯片的spi接口来和rc522通讯,通过相应的寄存器可控制SPI接口的数据传输率、数据时钟相位等通信参数。
这里使用spi通讯,1/4分频,空闲低电平,第一个时钟周期开始采样,第一个时钟边缘开始数据采样。
注意:片选信号必须保证在写入数据流期间为低电平,而在无数据流写入时为高电平,不得为了省事而一直将NSS置为低电平。
四、单片机stm8s与读卡器RC522通讯—-软件部分
单片机与读卡器的接口
RC522读卡器提供三种接口,分别是UART,I2C,SPI这三种接口。我们这里选择了spi接口。关于stm8s为主机,rc522读卡器为从机。spi使用4个管脚与从设备相连,MISO,MOSI,SCK,NSS.
这里有一点需要注意:MOSI管脚相互连接,MISO脚相互连接。这样,数据在主和从之间串行地传输(MSB位在前)。通信总是由主设备发起。主设备通过MOSI脚把数据发送给从设备,从设备通过MISO引脚回传数据。这意味全双工通信的数据输出和数据输入是用同一个时钟信号同步的:时钟信号由主设备通过SCK脚提供。
(1)SPI初始化如下:
void init_SPI_Master(void)
{
SPI_CR1 = 0x04; //fMaster/2, 配置为主设备,空闲低电平,第一个时钟周期开始采样
SPI_CR2 = 0x03; //内部指定主模式,NSS上电平决定该位值
SPI_CRCPR = 0x07;
SPI_ICR = 0x00; //中断禁止
SPI_CR1 |= 0x40; //开启SPI
}
(2)UART初始化,这里为了调试方便,我们使用uart接口来观察执行情况。
void init_UART(void)
{
UART1_CR2=0x00;//使发送禁用TEN=0;
UART1_CR1=0x00;//设置M字长,8位数据位
UART1_CR3=0x00;//1位停止位
UART1_BRR2=0X00; //波特率9600,分频系数=2000000/9600=208
UART1_BRR1=0X0D; //208=0X0D;
UART1_CR2=0X2C; //b3=1,允许发送 b2=1,允许接收 b5=1,允许产生接收中断
}
(3)UART发送数据函数
void UARTSend(uchar aa)
{
UART1_CR2=0x00;
UART1_DR=aa;
UART1_CR2=0x08;
while((UART1_SR & 0x40) ==0);
UART1_CR2=0x2c;//0x2c;//0x08; 2位 rev使能 3位 发送使能 5–rien
}
(4)UART接收中断处理函数
@far @interrupt void UART1_RX_IRQHandler(void) //UART1_Receiver(void)
{
unsigned char i;
_asm(“sim”); //关总中断
a=UART1_DR; //将接收的字符放到a中
_asm(“rim”); //开总中断
return;
}
(5)SPI接收发送字节
//spi接口在写的时候要先发送,发送不一定要传送内容,只是为了
//给从机提供时钟,因为sck是主机来发出的,所以写函数里面要有发送指令,目的是提供从机写时钟
uchar SPIWriteByte(uchar spiData)
{
uchar retry=0;
while((SPI_SR & 0X02)==0) //等待发送区空
{
retry++;
if(retry>200) return 0; //防止死机
}
SPI_DR=spiData; //发送一个byte
retry=0;
while((SPI_SR|0X80)==0X80); //等待通信结束
while((SPI_SR & 0X01)==0); //等待接收缓冲区空
{
retry++;
if(retry>200) return 0;
}
return SPI_DR; //返回受到的数
}
(6)main.c主程序函数
void main()
{
uchar i;
uchar Card_Type1[2];
uchar Card_ID[4];
uchar Card_KEY[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
uchar Card_Data[16];
uchar status;
//fmaster=fcpu=2MHz
CLK_ECKR=0x00;
CLK_ICKR=0x01;
CLK_CMSR=0xe1;
CLK_SWR=0xe1;
CLK_CKDIVR=0x18;
init_IO();
init_UART();
init_SPI_Master();
_asm(“rim”); //开总中断,便于产生串口接收中断
status=PcdReset();
PcdAntennaOff();
delay(20);
PcdAntennaOn();
M500PcdConfigISOType( ‘A’ );
a=0x63;
nblock=4;//kuan 0
t=0;
while(1)
{
// PcdAntennaOff();
//测试一下接口是否正确
status = CheckMCURC522interface();
if(status != MI_OK)
{
UARTSend(0x04);
continue;
}
status = PcdRequest(PICC_REQALL, g_ucTempbuf);
if (status != MI_OK)
{
continue;
}
// UARTSend(a);//0x11);
// for(i=0;i<8;i++)
// UARTSend(g_ucTempbuf[i]);//0400 e52b 0000000000
delay(20);//
status = PcdAnticoll(g_ucTempbuf);
if (status != MI_OK)
{ continue; }
// UARTSend(0x12);
delay(20);//delay_ms(2);
status = PcdSelect(g_ucTempbuf);
if (status != MI_OK)
{ continue; }
// UARTSend(0x13);
delay(20);//
// UARTSend(nblock);
//认证卡
status = PcdAuthState(PICC_AUTHENT1A, nblock, DefaultKey, g_ucTempbuf);
if (status != MI_OK)
{ continue; }
// UARTSend(0x14);
delay(20);//
if(a==b) continue;
else b=a;
UARTSend(a); //发送执行的命令代码
switch(a)
{
case 0x91://写电子钱包数据到块nblock
status = PcdWrite(nblock, data1);
if(status==MI_OK)
{
UARTSend(0x88);
}
else UARTSend(0x44);
break;
case 0x92://写普通数据到块nblock
status = PcdWrite(nblock, data3);
if(status==MI_OK)
{
UARTSend(0x88);
}
else UARTSend(0x44);
break;
case 0x93://从块n中读取数据
status = PcdRead(nblock, g_ucTempbuf);//PcdRead(2, g_ucTempbuf);
if (status == MI_OK)
{
UARTSend(0x88);
for(i=0;i<16;i++)
UARTSend(g_ucTempbuf[i]);//把写进去的数
}
else UARTSend(0x44);
break;
case 0x94://从块n中读取数据
status = PcdRead(nblock, g_ucTempbuf);//PcdRead(2, g_ucTempbuf);
if (status == MI_OK)
{
UARTSend(0x88);
for(i=0;i<16;i++)
UARTSend(g_ucTempbuf[i]);//把写进去的数
}
else UARTSend(0x44);
break;
case 0x95://操作电子钱包
status = PcdValue(PICC_DECREMENT,nblock,data2);
if (status == MI_OK)
{
UARTSend(0x88);
for(i=0;i<4;i++)
UARTSend(data2[i]);//
}
else UARTSend(0x44);
break;
case 0x96: //备份电子钱包
status = PcdBakValue(nblock, nblock+1);
if (status == MI_OK)
{
UARTSend(0x88);
}
else UARTSend(0x44);
break;
default:break;
}
// PcdHalt();
// PcdAntennaOff();
}
}
(7)RC522的库函数和网上都基本一样,就不写了。
以上程序本人已经测试过了。
(8)本人在学习rc522的过程中参考了很多文章,在此表示感谢!
M1卡介绍 http://wenku.baidu.com/view/62cccb122e3f5727a4e9625c.html
M1卡激活成功教程密码控制位及控制规则http://www.docin.com/p-624326551.html
Mifare1技术说明(M1卡说明文档) http://www.docin.com/p-379085837.html
基于非接触式ic卡的读卡器的设计与开发http://www.docin.com/p-906980594.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/hz/88115.html