1356M读卡器开发详解二RC522驱动程序.docx
《1356M读卡器开发详解二RC522驱动程序.docx》由会员分享,可在线阅读,更多相关《1356M读卡器开发详解二RC522驱动程序.docx(21页珍藏版)》请在冰豆网上搜索。
1356M读卡器开发详解二RC522驱动程序
13.56M读卡器开发详解二
1. 硬件接口介绍
根据上一篇的介绍,小编使用了RC522的SPI口通信方式和51单片机进行通信。
硬件接口设计此处不再附图。
只是将接口配置列写如下:
sbit spi_cs=P1^6;
sbit spi_ck=P1^5;
sbit spi_mosi=P1^4;
sbit spi_miso=P1^3;
sbit spi_rst=P1^2;
#define SET_SPI_CS spi_cs=1
#define CLR_SPI_CS spi_cs=0
#define SET_SPI_CK spi_ck=1
#define CLR_SPI_CK spi_ck=0
#define SET_SPI_MOSI spi_mosi=1
#define CLR_SPI_MOSI spi_mosi=0
#define STU_SPI_MISO spi_miso
#define SET_RC522RST spi_rst=1
#define CLR_RC522RST spi_rst=0
2. 51单片机模拟SPI通信函数
void delay_ns(unsigned int data ns)
{
unsigned int xdata i;
for(i=0;i
{
nop();
nop();
nop();
}
}
unsigned char SPIReadByte(void)
{
unsigned char idata SPICount; // Counter used to clock out the data
unsigned char idata SPIData;
SPIData = 0;
for (SPICount = 0; SPICount < 8; SPICount++) // Prepare to clock in the data to be read
{
SPIData <<=1; // Rotate the data
CLR_SPI_CK; nop();nop(); // Raise the clock to clock the data out of the MAX7456
if(STU_SPI_MISO)
{
SPIData|=0x01;
}
SET_SPI_CK; nop();nop(); // Drop the clock ready for the next bit
} // and loop back
return (SPIData); // Finally return the read data
}
void SPIWriteByte(unsigned char data SPIData)
{
unsigned char idata SPICount; // Counter used to clock out the data
for (SPICount = 0; SPICount < 8; SPICount++)
{
if (SPIData & 0x80)
{
SET_SPI_MOSI;
}
else
{
CLR_SPI_MOSI;
} nop();nop();
CLR_SPI_CK;nop();nop();
SET_SPI_CK;nop();nop();
SPIData <<= 1;
}
}
3.RC522芯片的寄存器、命令字等定义
3.1命令字等定义
这些宏定义都是根据RC522数据手册编写的代码。
3.2. RC522寄存器地址定义
4. Rc522的14443协议代码驱动程序
4.1寻卡程序
char PcdRequest(unsigned char data req_code,unsigned char *pTagType)
{ char idata status;
unsigned int idata unLen;
unsigned char xdata ucComMF522Buf[MAXRLEN];
ClearBitMask(Status2Reg,0x08);
WriteRawRC(BitFramingReg,0x07);
SetBitMask(TxControlReg,0x03);
ucComMF522Buf[0] = req_code;
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
if ((status == MI_OK) && (unLen == 0x10))
{
*pTagType = ucComMF522Buf[0];
*(pTagType+1) = ucComMF522Buf[1];
}
else
{ status = MI_ERR; }
return status;
}
4.2防冲撞函数
char PcdAnticoll(unsigned char *pSnr)
{
char xdata status;
unsigned char xdata i,snr_check=0;
unsigned int xdata unLen;
unsigned char xdata ucComMF522Buf[MAXRLEN];
ClearBitMask(Status2Reg,0x08);
WriteRawRC(BitFramingReg,0x00);
ClearBitMask(CollReg,0x80);
ucComMF522Buf[0] = PICC_ANTICOLL1;
ucComMF522Buf[1] = 0x20;
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);
if (status == MI_OK)
{
for (i=0; i<4; i++)
{
*(pSnr+i) = ucComMF522Buf[i];
snr_check ^= ucComMF522Buf[i];
}
if (snr_check !
= ucComMF522Buf[i])
{ status = MI_ERR; }
}
SetBitMask(CollReg,0x80);
return status;
}
4.3选定卡片
char PcdSelect(unsigned char *pSnr)
{
char xdata status;
unsigned char xdata i;
unsigned int xdata unLen;
unsigned char xdata ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_ANTICOLL1;
ucComMF522Buf[1] = 0x70;
ucComMF522Buf[6] = 0;
for (i=0; i<4; i++)
{
ucComMF522Buf[i+2] = *(pSnr+i);
ucComMF522Buf[6] ^= *(pSnr+i);
}
CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);
ClearBitMask(Status2Reg,0x08);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
if ((status == MI_OK) && (unLen == 0x18))
{ status = MI_OK; }
else
{ status = MI_ERR; }
return status;
}
4.4验证卡片密码
char PcdAuthState(unsigned char data auth_mode,unsigned char data addr,unsigned char *pKey,unsigned char *pSnr)
{
char xdata status;
unsigned int xdata unLen;
unsigned char xdata i,ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = auth_mode;
ucComMF522Buf[1] = addr;
for (i=0; i<6; i++)
{ ucComMF522Buf[i+2] = *(pKey+i); }
for (i=0; i<6; i++)
{ ucComMF522Buf[i+8] = *(pSnr+i); }
// memcpy(&ucComMF522Buf[2], pKey, 6);
// memcpy(&ucComMF522Buf[8], pSnr, 4);
status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
if ((status !
= MI_OK) || (!
(ReadRawRC(Status2Reg) & 0x08)))
{ status = MI_ERR; }
return status;
}
4.5读取M1卡一块数据
char PcdRead(unsigned char data addr,unsigned char *pData)
{
char idata status;
unsigned int idata unLen;
unsigned char idata i,ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_READ;
ucComMF522Buf[1] = addr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
if ((status == MI_OK) && (unLen == 0x90))
// { memcpy(pData, ucComMF522Buf, 16); }
{
for (i=0; i<16; i++)
{ *(pData+i) = ucComMF522Buf[i]; }
}
else
{ status = MI_ERR; }
return status;
}
4.6写数据到M1卡一块
char PcdWrite(unsigned char data addr,unsigned char *pData)
{
char idata status;
unsigned int idata unLen;
unsigned char idata ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_WRITE;
ucComMF522Buf[1] = addr;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
if ((status !
= MI_OK) || (unLen !
= 4) || ((ucComMF522Buf[0] & 0x0F) !
= 0x0A))
{ status = MI_ERR; }
if (status == MI_OK)
{
memcpy(ucComMF522Buf, pData, 16);
// for (i=0; i<16; i++)
// {
// ucComMF522Buf[i] = *(pData+i);
// }
CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);
if ((status !
= MI_OK) || (unLen !
= 4) || ((ucComMF522Buf[0] & 0x0F) !
= 0x0A))
{ status = MI_ERR; } }
return status;
}
4.7命令卡进入休眠状态
char PcdHalt(void)
{
char idata status;
unsigned int idata unLen;
unsigned char idata ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = PICC_HALT;
ucComMF522Buf[1] = 0;
CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
return MI_OK;
}
4.8 RC522计算CRC16
void CalulateCRC(unsigned char *pIndata,unsigned char data len,unsigned char *pOutData)
{
unsigned char idata i,n;
ClearBitMask(DivIrqReg,0x04);
WriteRawRC(CommandReg,PCD_IDLE);
SetBitMask(FIFOLevelReg,0x80);
for (i=0; i
{ WriteRawRC(FIFODataReg, *(pIndata+i)); }
WriteRawRC(CommandReg, PCD_CALCCRC);
i = 0xFF;
do
{
n = ReadRawRC(DivIrqReg);
i--;
}
while ((i!
=0) && !
(n&0x04));
pOutData[0] = ReadRawRC(CRCResultRegL);
pOutData[1] = ReadRawRC(CRCResultRegM);
}
4.9 复位RC522
char PcdReset(void)
{
//PORTD|=(1<SET_RC522RST;
delay_ns(10);
//PORTD&=~(1<CLR_RC522RST;
delay_ns(10);
//PORTD|=(1<SET_RC522RST;
delay_ns(10);
WriteRawRC(CommandReg,PCD_RESETPHASE);
delay_ns(10);
WriteRawRC(ModeReg,0x3D); //ºÍMifare¿¨Í¨Ñ¶£¬CRC³õʼֵ0x6363
WriteRawRC(TReloadRegL,30);
WriteRawRC(TReloadRegH,0);
WriteRawRC(TModeReg,0x8D);
WriteRawRC(TPrescalerReg,0x3E);
WriteRawRC(TxAutoReg,0x40);//±ØÐëÒª
return MI_OK;
}
4.10 设置RC522工作方式
char M500PcdConfigISOType(unsigned char data type)
{
if (type == 'A') //ISO14443_A
{
ClearBitMask(Status2Reg,0x08);
WriteRawRC(ModeReg,0x3D);//3F
WriteRawRC(RxSelReg,0x86);//84
WriteRawRC(RFCfgReg,0x7F); //4F
WriteRawRC(TReloadRegL,30);//tmoLength);// TReloadVal = 'h6a =tmoLength(dec)
WriteRawRC(TReloadRegH,0);
WriteRawRC(TModeReg,0x8D);
WriteRawRC(TPrescalerReg,0x3E);
delay_ns(1000);
PcdAntennaOn();
}
else{ return -1; }
return MI_OK;
}
4.11 读RC522寄存器
unsigned char ReadRawRC(unsigned char data Address)
{
unsigned char xdata ucAddr;
unsigned char xdata ucResult=0;
CLR_SPI_CS;
ucAddr = ((Address<<1)&0x7E)|0x80;
SPIWriteByte(ucAddr);
ucResult=SPIReadByte();
SET_SPI_CS;
return ucResult;
}
4.12 写RC522寄存器
void WriteRawRC(unsigned char data Address, unsigned char data value)
{
unsigned char xdata ucAddr;
CLR_SPI_CS;
ucAddr = ((Address<<1)&0x7E);
SPIWriteByte(ucAddr);
SPIWriteByte(value);
SET_SPI_CS;
}
4.13 置和清RC522寄存器位
4.14 RC522与ISO14443卡通讯
char PcdComMF522(unsigned char data Command,
unsigned char *pInData,
unsigned char data InLenByte,
unsigned char *pOutData,
unsigned int *pOutLenBit)
{
char data status = MI_ERR;
unsigned char data irqEn = 0x00;
unsigned char data waitFor = 0x00;
unsigned char data lastBits;
unsigned char data n;
unsigned int data i;
switch (Command)
{
case PCD_AUTHENT:
irqEn = 0x12;
waitFor = 0x10;
break;
case PCD_TRANSCEIVE:
irqEn = 0x77;
waitFor = 0x30;
break;
default:
break;
}
WriteRawRC(ComIEnReg,irqEn|0x80);
ClearBitMask(ComIrqReg,0x80);
WriteRawRC(CommandReg,PCD_IDLE);
SetBitMask(FIFOLevelReg,0x80);
for (i=0; i
{ W