读卡器开发详解

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通信函数
    ```
    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;

}
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;

}





posted @ 2018-10-23 10:30  wangjunyao  阅读(1130)  评论(0编辑  收藏  举报