13.56M读卡器开发详解二

1. 硬件接口介绍

根据上一篇的介绍,小编使用了RC522的SPI口通信方式和51单片机进行通信。硬件接口设计此处不再附图。只是将接口配置列写如下:

12345
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
  1. 51单片机模拟SPI通信函数
1. ``` 

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<<RC522RST); 

SET_RC522RST; 

    delay_ns(10); 

//PORTD&=~(1<<RC522RST); 

CLR_RC522RST; 

    delay_ns(10); 

//PORTD|=(1<<RC522RST); 

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
{   WriteRawRC(FIFODataReg, pInData[i]);    }
WriteRawRC(CommandReg, Command);


if (Command == PCD_TRANSCEIVE)
{    SetBitMask(BitFramingReg,0x80);  }

//i = 600;//¸ù¾ÝʱÖÓƵÂʵ÷Õû£¬²Ù×÷M1¿¨×î´óµÈ´ýʱ¼ä25ms
i = 2000; 

    do 

    { 

        n = ReadRawRC(ComIrqReg); 

        i--; 

    } 

    while ((i!=0) && !(n&0x01) && !(n&waitFor)); 

    ClearBitMask(BitFramingReg,0x80);if (i!=0)
{   
    if(!(ReadRawRC(ErrorReg)&0x1B))
    {
        status = MI_OK;
        if (n & irqEn & 0x01)
        {   status = MI_NOTAGERR;   }
        if (Command == PCD_TRANSCEIVE)
        {
            n = ReadRawRC(FIFOLevelReg);
           lastBits = ReadRawRC(ControlReg) & 0x07;
            if (lastBits)
            {   *pOutLenBit = (n-1)*8 + lastBits;   }
            else
            {   *pOutLenBit = n*8;   }
            if (n == 0)
            {   n = 1;    }
            if (n > MAXRLEN)
            {   n = MAXRLEN;   }
            for (i=0; i
            {   pOutData[i] = ReadRawRC(FIFODataReg);    }
        }
    }
    else
    {   status = MI_ERR;   }

}

SetBitMask(ControlReg,0x80);           // stop timer now
WriteRawRC(CommandReg,PCD_IDLE);
return status;
i = 2000; 

    do 

    { 

        n = ReadRawRC(ComIrqReg); 

        i--; 

    } 

    while ((i!=0) && !(n&0x01) && !(n&waitFor)); 

    ClearBitMask(BitFramingReg,0x80);if (i!=0)
{   
    if(!(ReadRawRC(ErrorReg)&0x1B))
    {
        status = MI_OK;
        if (n & irqEn & 0x01)
        {   status = MI_NOTAGERR;   }
        if (Command == PCD_TRANSCEIVE)
        {
            n = ReadRawRC(FIFOLevelReg);
           lastBits = ReadRawRC(ControlReg) & 0x07;
            if (lastBits)
            {   *pOutLenBit = (n-1)*8 + lastBits;   }
            else
            {   *pOutLenBit = n*8;   }
            if (n == 0)
            {   n = 1;    }
            if (n > MAXRLEN)
            {   n = MAXRLEN;   }
            for (i=0; i
            {   pOutData[i] = ReadRawRC(FIFODataReg);    }
        }
    }
    else
    {   status = MI_ERR;   }

}

SetBitMask(ControlReg,0x80);           // stop timer now
WriteRawRC(CommandReg,PCD_IDLE);
return status;
if (i!=0)
{   
    if(!(ReadRawRC(ErrorReg)&0x1B))
    {
        status = MI_OK;
        if (n & irqEn & 0x01)
        {   status = MI_NOTAGERR;   }
        if (Command == PCD_TRANSCEIVE)
        {
            n = ReadRawRC(FIFOLevelReg);
           lastBits = ReadRawRC(ControlReg) & 0x07;
            if (lastBits)
            {   *pOutLenBit = (n-1)*8 + lastBits;   }
            else
            {   *pOutLenBit = n*8;   }
            if (n == 0)
            {   n = 1;    }
            if (n > MAXRLEN)
            {   n = MAXRLEN;   }
            for (i=0; i
            {   pOutData[i] = ReadRawRC(FIFODataReg);    }
        }
    }
    else
    {   status = MI_ERR;   }

}

SetBitMask(ControlReg,0x80);           // stop timer now
WriteRawRC(CommandReg,PCD_IDLE);
return status;

4.15 天线开启和关闭

4.16 扣款和充值

char PcdValue(unsigned char data dd_mode,unsigned char data addr,unsigned char  *pValue) 

{ 

    char data status; 

    unsigned int data  unLen; 

    unsigned char idata  ucComMF522Buf[MAXRLEN];
ucComMF522Buf[0] = dd_mode;
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, pValue, 4);
   //  for (i=0; i<16; i++)
    // {    ucComMF522Buf[i] = *(pValue+i);   }
    CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);
    unLen = 0;
    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);
    if (status != MI_ERR)
    {    status = MI_OK;    }
}

if (status == MI_OK)
{
    ucComMF522Buf[0] = PICC_TRANSFER;
    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;   }
}
return status;