• STM32 + RC522(SPI2 和 模拟SPI)


    STM32 + RC522(SPI2 和 模拟SPI)

    一. STM32 + RC522(SPI2 模式)

    1. 头文件: rc522.h

      1 #include "stm32f10x.h"
      2 /////////////////////////////////////////////////////////////////////
      3 //MF522命令字
      4 /////////////////////////////////////////////////////////////////////
      5 #define PCD_IDLE              0x00               //取消当前命令
      6 #define PCD_AUTHENT           0x0E               //验证密钥
      7 #define PCD_RECEIVE           0x08               //接收数据
      8 #define PCD_TRANSMIT          0x04               //发送数据
      9 #define PCD_TRANSCEIVE        0x0C               //发送并接收数据
     10 #define PCD_RESETPHASE        0x0F               //复位
     11 #define PCD_CALCCRC           0x03               //CRC计算
     12 
     13 /////////////////////////////////////////////////////////////////////
     14 //Mifare_One卡片命令字
     15 /////////////////////////////////////////////////////////////////////
     16 #define PICC_REQIDL           0x26               //寻天线区内未进入休眠状态
     17 #define PICC_REQALL           0x52               //寻天线区内全部卡
     18 #define PICC_ANTICOLL1        0x93               //防冲撞
     19 #define PICC_ANTICOLL2        0x95               //防冲撞
     20 #define PICC_AUTHENT1A        0x60               //验证A密钥
     21 #define PICC_AUTHENT1B        0x61               //验证B密钥
     22 #define PICC_READ             0x30               //读块
     23 #define PICC_WRITE            0xA0               //写块
     24 #define PICC_DECREMENT        0xC0               //扣款
     25 #define PICC_INCREMENT        0xC1               //充值
     26 #define PICC_RESTORE          0xC2               //调块数据到缓冲区
     27 #define PICC_TRANSFER         0xB0               //保存缓冲区中数据
     28 #define PICC_HALT             0x50               //休眠
     29 
     30 /////////////////////////////////////////////////////////////////////
     31 //MF522 FIFO长度定义
     32 /////////////////////////////////////////////////////////////////////
     33 #define DEF_FIFO_LENGTH       64                 //FIFO size=64byte
     34 #define MAXRLEN  18
     35 
     36 /////////////////////////////////////////////////////////////////////
     37 //MF522寄存器定义
     38 /////////////////////////////////////////////////////////////////////
     39 // PAGE 0
     40 #define     RFU00                 0x00    
     41 #define     CommandReg            0x01    
     42 #define     ComIEnReg             0x02    
     43 #define     DivlEnReg             0x03    
     44 #define     ComIrqReg             0x04    
     45 #define     DivIrqReg             0x05
     46 #define     ErrorReg              0x06    
     47 #define     Status1Reg            0x07    
     48 #define     Status2Reg            0x08    
     49 #define     FIFODataReg           0x09
     50 #define     FIFOLevelReg          0x0A
     51 #define     WaterLevelReg         0x0B
     52 #define     ControlReg            0x0C
     53 #define     BitFramingReg         0x0D
     54 #define     CollReg               0x0E
     55 #define     RFU0F                 0x0F
     56 // PAGE 1     
     57 #define     RFU10                 0x10
     58 #define     ModeReg               0x11
     59 #define     TxModeReg             0x12
     60 #define     RxModeReg             0x13
     61 #define     TxControlReg          0x14
     62 #define     TxAutoReg             0x15
     63 #define     TxSelReg              0x16
     64 #define     RxSelReg              0x17
     65 #define     RxThresholdReg        0x18
     66 #define     DemodReg              0x19
     67 #define     RFU1A                 0x1A
     68 #define     RFU1B                 0x1B
     69 #define     MifareReg             0x1C
     70 #define     RFU1D                 0x1D
     71 #define     RFU1E                 0x1E
     72 #define     SerialSpeedReg        0x1F
     73 // PAGE 2    
     74 #define     RFU20                 0x20  
     75 #define     CRCResultRegM         0x21
     76 #define     CRCResultRegL         0x22
     77 #define     RFU23                 0x23
     78 #define     ModWidthReg           0x24
     79 #define     RFU25                 0x25
     80 #define     RFCfgReg              0x26
     81 #define     GsNReg                0x27
     82 #define     CWGsCfgReg            0x28
     83 #define     ModGsCfgReg           0x29
     84 #define     TModeReg              0x2A
     85 #define     TPrescalerReg         0x2B
     86 #define     TReloadRegH           0x2C
     87 #define     TReloadRegL           0x2D
     88 #define     TCounterValueRegH     0x2E
     89 #define     TCounterValueRegL     0x2F
     90 // PAGE 3      
     91 #define     RFU30                 0x30
     92 #define     TestSel1Reg           0x31
     93 #define     TestSel2Reg           0x32
     94 #define     TestPinEnReg          0x33
     95 #define     TestPinValueReg       0x34
     96 #define     TestBusReg            0x35
     97 #define     AutoTestReg           0x36
     98 #define     VersionReg            0x37
     99 #define     AnalogTestReg         0x38
    100 #define     TestDAC1Reg           0x39  
    101 #define     TestDAC2Reg           0x3A   
    102 #define     TestADCReg            0x3B   
    103 #define     RFU3C                 0x3C   
    104 #define     RFU3D                 0x3D   
    105 #define     RFU3E                 0x3E   
    106 #define     RFU3F                    0x3F
    107 
    108 /////////////////////////////////////////////////////////////////////
    109 //和MF522通讯时返回的错误代码
    110 /////////////////////////////////////////////////////////////////////
    111 #define     MI_OK                 0
    112 #define     MI_NOTAGERR           (1)
    113 #define     MI_ERR                (2)
    114 
    115 #define    SHAQU1    0X01
    116 #define    KUAI4    0X04
    117 #define    KUAI7    0X07
    118 #define    REGCARD    0xa1
    119 #define    CONSUME    0xa2
    120 #define READCARD    0xa3
    121 #define ADDMONEY    0xa4
    122 
    123 //
    124 //#define  spi_cs 1;
    125 //sbit  spi_ck=P0^6;
    126 //sbit  spi_mosi=P0^7;
    127 //sbit  spi_miso=P4^1;
    128 //sbit  spi_rst=P2^7;
    129 #define SPIReadByte()    SPIWriteByte(0)
    130 u8 SPIWriteByte(u8 byte);
    131 void SPI2_Init(void);
    132 
    133 #define SET_SPI_CS  (GPIOF->BSRR=0X01)
    134 #define CLR_SPI_CS  (GPIOF->BRR=0X01)
    135 
    136 
    137 
    138 #define SET_RC522RST  GPIOF->BSRR=0X02
    139 #define CLR_RC522RST  GPIOF->BRR=0X02
    140 void InitRc522(void);
    141 void ClearBitMask(u8   reg,u8   mask);
    142 void WriteRawRC(u8   Address, u8   value);
    143 void SetBitMask(u8   reg,u8   mask);
    144 char PcdComMF522(u8   Command, 
    145                  u8 *pIn , 
    146                  u8   InLenByte,
    147                  u8 *pOut , 
    148                  u8  *pOutLenBit);
    149 void CalulateCRC(u8 *pIn ,u8   len,u8 *pOut );
    150 u8 ReadRawRC(u8   Address);
    151 void PcdAntennaOn(void);
    152 
    153 char PcdReset(void);
    154 char PcdRequest(unsigned char req_code,unsigned char *pTagType);
    155 void PcdAntennaOn(void);
    156 void PcdAntennaOff(void);
    157 char M500PcdConfigISOType(unsigned char type);
    158 char PcdAnticoll(unsigned char *pSnr);
    159 char PcdSelect(unsigned char *pSnr);
    160 char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr);
    161 char PcdWrite(unsigned char addr,unsigned char *pData);
    162 char PcdRead(unsigned char addr,unsigned char *pData);
    163 char PcdHalt(void);
    164 void Reset_RC522(void);
    165 char PcdValue(u8 dd_mode,u8 addr,u8 *pValue);
    166 char PcdBakValue(u8 sourceaddr, u8 goaladdr);

    2. C文件:rc522.c

     

      1 #include "sys.h"
      2 #include "rc522.h"
      3 #include "delay.h"
      4 
      5 void delay_ns(u32 ns)
      6 {
      7   u32 i;
      8   for(i=0;i<ns;i++)
      9   {
     10     __nop();
     11     __nop();
     12     __nop();
     13   }
     14 }
     15 
     16 u8 SPIWriteByte(u8 Byte)
     17 {
     18     while((SPI2->SR&0X02)==0);        //等待发送区空      
     19     SPI2->DR=Byte;                     //发送一个byte   
     20     while((SPI2->SR&0X01)==0);      //等待接收完一个byte  
     21     return SPI2->DR;                  //返回收到的数据            
     22 }
     23 
     24 //SPIx 读写一个字节
     25 //TxData:要写入的字节
     26 //返回值:读取到的字节
     27 u8 SPI2_ReadWriteByte(u8 TxData)
     28 {        
     29     u8 retry=0;                     
     30     while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
     31     {
     32         retry++;
     33         if(retry>200)return 0;
     34     }              
     35     SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个数据
     36     retry=0;
     37 
     38     while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位
     39     {
     40         retry++;
     41         if(retry>200)return 0;
     42     }                                  
     43     return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据                        
     44 }
     45 
     46 
     47 //SPI 速度设置函数
     48 //SpeedSet:
     49 //SPI_BaudRatePrescaler_2   2分频   
     50 //SPI_BaudRatePrescaler_8   8分频   
     51 //SPI_BaudRatePrescaler_16  16分频  
     52 //SPI_BaudRatePrescaler_256 256分频 
     53   
     54 void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler)
     55 {
     56       assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
     57     SPI2->CR1&=0XFFC7;
     58     SPI2->CR1|=SPI_BaudRatePrescaler;    //设置SPI2速度 
     59     SPI_Cmd(SPI2,ENABLE); 
     60 
     61 } 
     62 
     63 
     64 
     65 
     66 void SPI2_Init(void)    
     67 {
     68     GPIO_InitTypeDef GPIO_InitStructure;
     69       SPI_InitTypeDef  SPI_InitStructure;
     70      RCC_APB2PeriphClockCmd(    RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOF, ENABLE );//PORTB时钟使能 
     71     RCC_APB1PeriphClockCmd(    RCC_APB1Periph_SPI2,  ENABLE );//SPI2时钟使能
     72 
     73     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;     //IO-->PF0、PF1 端口配置
     74     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;          //推挽输出
     75     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         //IO口速度为50MHz
     76     GPIO_Init(GPIOF, &GPIO_InitStructure);                     //根据设定参数初始化PF0、PF1
     77     GPIO_ResetBits(GPIOF,GPIO_Pin_1);                         //PF1输出低
     78     //GPIO_SetBits(GPIOF,GPIO_Pin_0);
     79 
     80     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
     81     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //PB13/14/15复用推挽输出 
     82     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     83     GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB
     84 
     85      GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);  //PB13/14/15上拉
     86 
     87     SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
     88     SPI_InitStructure.SPI_Mode = SPI_Mode_Master;        //设置SPI工作模式:设置为主SPI
     89     SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;        //设置SPI的数据大小:SPI发送接收8位帧结构
     90     SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;        //串行同步时钟的空闲状态为低电平
     91     SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;    //串行同步时钟的第一个跳变沿(上升或下降)数据被采样
     92     SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;        //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
     93     SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;        //定义波特率预分频的值:波特率预分频值为256
     94     SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;    //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
     95     SPI_InitStructure.SPI_CRCPolynomial = 7;    //CRC值计算的多项式
     96     SPI_Init(SPI2, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
     97  
     98     SPI_Cmd(SPI2, ENABLE); //使能SPI外设
     99     
    100     //SPI2_ReadWriteByte(0xff);//启动传输    
    101 }
    102 
    103 void InitRc522(void)
    104 {
    105   SPI2_Init();
    106   PcdReset();
    107   PcdAntennaOff();
    108   delay_ms(2);  
    109   PcdAntennaOn();
    110   M500PcdConfigISOType( 'A' );
    111 }
    112 void Reset_RC522(void)
    113 {
    114   PcdReset();
    115   PcdAntennaOff();
    116   delay_ms(2);  
    117   PcdAntennaOn();
    118 }                         
    119 /////////////////////////////////////////////////////////////////////
    120 //功    能:寻卡
    121 //参数说明: req_code[IN]:寻卡方式
    122 //                0x52 = 寻感应区内所有符合14443A标准的卡
    123 //                0x26 = 寻未进入休眠状态的卡
    124 //          pTagType[OUT]:卡片类型代码
    125 //                0x4400 = Mifare_UltraLight
    126 //                0x0400 = Mifare_One(S50)
    127 //                0x0200 = Mifare_One(S70)
    128 //                0x0800 = Mifare_Pro(X)
    129 //                0x4403 = Mifare_DESFire
    130 //返    回: 成功返回MI_OK
    131 /////////////////////////////////////////////////////////////////////
    132 char PcdRequest(u8 req_code,u8 *pTagType)
    133 {
    134     char status;  
    135     u8   unLen;
    136     u8   ucComMF522Buf[MAXRLEN]; 
    137 
    138     ClearBitMask(Status2Reg,0x08);
    139     WriteRawRC(BitFramingReg,0x07);
    140     SetBitMask(TxControlReg,0x03);
    141  
    142     ucComMF522Buf[0] = req_code;
    143 
    144     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
    145 
    146     if ((status == MI_OK) && (unLen == 0x10))
    147     {    
    148         *pTagType     = ucComMF522Buf[0];
    149         *(pTagType+1) = ucComMF522Buf[1];
    150     }
    151     else
    152     {   status = MI_ERR;   }
    153    
    154     return status;
    155 }
    156 
    157 /////////////////////////////////////////////////////////////////////
    158 //功    能:防冲撞
    159 //参数说明: pSnr[OUT]:卡片序列号,4字节
    160 //返    回: 成功返回MI_OK
    161 /////////////////////////////////////////////////////////////////////  
    162 char PcdAnticoll(u8 *pSnr)
    163 {
    164     char   status;
    165     u8   i,snr_check=0;
    166     u8   unLen;
    167     u8   ucComMF522Buf[MAXRLEN]; 
    168     
    169 
    170     ClearBitMask(Status2Reg,0x08);
    171     WriteRawRC(BitFramingReg,0x00);
    172     ClearBitMask(CollReg,0x80);
    173  
    174     ucComMF522Buf[0] = PICC_ANTICOLL1;
    175     ucComMF522Buf[1] = 0x20;
    176 
    177     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);
    178 
    179     if (status == MI_OK)
    180     {
    181          for (i=0; i<4; i++)
    182          {   
    183              *(pSnr+i)  = ucComMF522Buf[i];
    184              snr_check ^= ucComMF522Buf[i];
    185          }
    186          if (snr_check != ucComMF522Buf[i])
    187          {   status = MI_ERR;    }
    188     }
    189     
    190     SetBitMask(CollReg,0x80);
    191     return status;
    192 }
    193 
    194 /////////////////////////////////////////////////////////////////////
    195 //功    能:选定卡片
    196 //参数说明: pSnr[IN]:卡片序列号,4字节
    197 //返    回: 成功返回MI_OK
    198 /////////////////////////////////////////////////////////////////////
    199 char PcdSelect(u8 *pSnr)
    200 {
    201     char   status;
    202     u8   i;
    203     u8   unLen;
    204     u8   ucComMF522Buf[MAXRLEN]; 
    205     
    206     ucComMF522Buf[0] = PICC_ANTICOLL1;
    207     ucComMF522Buf[1] = 0x70;
    208     ucComMF522Buf[6] = 0;
    209     for (i=0; i<4; i++)
    210     {
    211         ucComMF522Buf[i+2] = *(pSnr+i);
    212         ucComMF522Buf[6]  ^= *(pSnr+i);
    213     }
    214     CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);
    215   
    216     ClearBitMask(Status2Reg,0x08);
    217 
    218     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
    219     
    220     if ((status == MI_OK) && (unLen == 0x18))
    221     {   status = MI_OK;  }
    222     else
    223     {   status = MI_ERR;    }
    224 
    225     return status;
    226 }
    227 
    228 /////////////////////////////////////////////////////////////////////
    229 //功    能:验证卡片密码
    230 //参数说明: auth_mode[IN]: 密码验证模式
    231 //                 0x60 = 验证A密钥
    232 //                 0x61 = 验证B密钥 
    233 //          addr[IN]:块地址
    234 //          pKey[IN]:密码
    235 //          pSnr[IN]:卡片序列号,4字节
    236 //返    回: 成功返回MI_OK
    237 /////////////////////////////////////////////////////////////////////               
    238 char PcdAuthState(u8   auth_mode,u8   addr,u8 *pKey,u8 *pSnr)
    239 {
    240     char   status;
    241     u8   unLen;
    242     u8   i,ucComMF522Buf[MAXRLEN]; 
    243 
    244     ucComMF522Buf[0] = auth_mode;
    245     ucComMF522Buf[1] = addr;
    246 //    for (i=0; i<6; i++)
    247 //    {    ucComMF522Buf[i+2] = *(pKey+i);   }
    248 //    for (i=0; i<6; i++)
    249 //    {    ucComMF522Buf[i+8] = *(pSnr+i);   }
    250     memcpy(&ucComMF522Buf[2], pKey, 6); 
    251     memcpy(&ucComMF522Buf[8], pSnr, 4); 
    252     
    253     status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
    254     if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
    255     {   status = MI_ERR;   }
    256     
    257     return status;
    258 }
    259 
    260 /////////////////////////////////////////////////////////////////////
    261 //功    能:读取M1卡一块数据
    262 //参数说明: addr[IN]:块地址
    263 //          p [OUT]:读出的数据,16字节
    264 //返    回: 成功返回MI_OK
    265 ///////////////////////////////////////////////////////////////////// 
    266 char PcdRead(u8   addr,u8 *p )
    267 {
    268     char   status;
    269     u8   unLen;
    270     u8   i,ucComMF522Buf[MAXRLEN]; 
    271 
    272     ucComMF522Buf[0] = PICC_READ;
    273     ucComMF522Buf[1] = addr;
    274     CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
    275    
    276     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
    277     if ((status == MI_OK) && (unLen == 0x90))
    278  //   {   memcpy(p , ucComMF522Buf, 16);   }
    279     {
    280         for (i=0; i<16; i++)
    281         {    *(p +i) = ucComMF522Buf[i];   }
    282     }
    283     else
    284     {   status = MI_ERR;   }
    285     
    286     return status;
    287 }
    288 
    289 /////////////////////////////////////////////////////////////////////
    290 //功    能:写数据到M1卡一块
    291 //参数说明: addr[IN]:块地址
    292 //          p [IN]:写入的数据,16字节
    293 //返    回: 成功返回MI_OK
    294 /////////////////////////////////////////////////////////////////////                  
    295 char PcdWrite(u8   addr,u8 *p )
    296 {
    297     char   status;
    298     u8   unLen;
    299     u8   i,ucComMF522Buf[MAXRLEN]; 
    300     
    301     ucComMF522Buf[0] = PICC_WRITE;
    302     ucComMF522Buf[1] = addr;
    303     CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
    304  
    305     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
    306 
    307     if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
    308     {   status = MI_ERR;   }
    309         
    310     if (status == MI_OK)
    311     {
    312         //memcpy(ucComMF522Buf, p , 16);
    313         for (i=0; i<16; i++)
    314         {    
    315             ucComMF522Buf[i] = *(p +i);   
    316         }
    317         CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);
    318 
    319         status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);
    320         if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
    321         {   status = MI_ERR;   }
    322     }
    323     
    324     return status;
    325 }
    326 
    327 /////////////////////////////////////////////////////////////////////
    328 //功    能:命令卡片进入休眠状态
    329 //返    回: 成功返回MI_OK
    330 /////////////////////////////////////////////////////////////////////
    331 char PcdHalt(void)
    332 {
    333     u8   status;
    334     u8   unLen;
    335     u8   ucComMF522Buf[MAXRLEN]; 
    336 
    337     ucComMF522Buf[0] = PICC_HALT;
    338     ucComMF522Buf[1] = 0;
    339     CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
    340  
    341     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
    342 
    343     return MI_OK;
    344 }
    345 
    346 /////////////////////////////////////////////////////////////////////
    347 //用MF522计算CRC16函数
    348 /////////////////////////////////////////////////////////////////////
    349 void CalulateCRC(u8 *pIn ,u8   len,u8 *pOut )
    350 {
    351     u8   i,n;
    352     ClearBitMask(DivIrqReg,0x04);
    353     WriteRawRC(CommandReg,PCD_IDLE);
    354     SetBitMask(FIFOLevelReg,0x80);
    355     for (i=0; i<len; i++)
    356     {   WriteRawRC(FIFODataReg, *(pIn +i));   }
    357     WriteRawRC(CommandReg, PCD_CALCCRC);
    358     i = 0xFF;
    359     do 
    360     {
    361         n = ReadRawRC(DivIrqReg);
    362         i--;
    363     }
    364     while ((i!=0) && !(n&0x04));
    365     pOut [0] = ReadRawRC(CRCResultRegL);
    366     pOut [1] = ReadRawRC(CRCResultRegM);
    367 }
    368 
    369 /////////////////////////////////////////////////////////////////////
    370 //功    能:复位RC522
    371 //返    回: 成功返回MI_OK
    372 /////////////////////////////////////////////////////////////////////
    373 char PcdReset(void)
    374 {
    375     //PORTD|=(1<<RC522RST);
    376     SET_RC522RST;
    377     delay_ns(10);
    378     //PORTD&=~(1<<RC522RST);
    379     CLR_RC522RST;
    380     delay_ns(10);
    381     //PORTD|=(1<<RC522RST);
    382     SET_RC522RST;
    383     delay_ns(10);
    384     WriteRawRC(CommandReg,PCD_RESETPHASE);
    385     WriteRawRC(CommandReg,PCD_RESETPHASE);
    386     delay_ns(10);
    387     
    388     WriteRawRC(ModeReg,0x3D);            //和Mifare卡通讯,CRC初始值0x6363
    389     WriteRawRC(TReloadRegL,30);           
    390     WriteRawRC(TReloadRegH,0);
    391     WriteRawRC(TModeReg,0x8D);
    392     WriteRawRC(TPrescalerReg,0x3E);
    393     
    394     WriteRawRC(TxAutoReg,0x40);//必须要
    395    
    396     return MI_OK;
    397 }
    398 //////////////////////////////////////////////////////////////////////
    399 //设置RC632的工作方式 
    400 //////////////////////////////////////////////////////////////////////
    401 char M500PcdConfigISOType(u8   type)
    402 {
    403    if (type == 'A')                     //ISO14443_A
    404    { 
    405        ClearBitMask(Status2Reg,0x08);
    406        WriteRawRC(ModeReg,0x3D);//3F
    407        WriteRawRC(RxSelReg,0x86);//84
    408        WriteRawRC(RFCfgReg,0x7F);   //4F
    409           WriteRawRC(TReloadRegL,30);//tmoLength);// TReloadVal = 'h6a =tmoLength(dec) 
    410        WriteRawRC(TReloadRegH,0);
    411        WriteRawRC(TModeReg,0x8D);
    412        WriteRawRC(TPrescalerReg,0x3E);
    413        delay_ns(1000);
    414        PcdAntennaOn();
    415    }
    416    else{ return 1; }
    417    
    418    return MI_OK;
    419 }
    420 /////////////////////////////////////////////////////////////////////
    421 //功    能:读RC632寄存器
    422 //参数说明:Address[IN]:寄存器地址
    423 //返    回:读出的值
    424 /////////////////////////////////////////////////////////////////////
    425 u8 ReadRawRC(u8   Address)
    426 {
    427     u8   ucAddr;
    428     u8   ucResult=0;
    429     CLR_SPI_CS;
    430     ucAddr = ((Address<<1)&0x7E)|0x80;
    431     
    432     SPIWriteByte(ucAddr);
    433     ucResult=SPIReadByte();
    434     SET_SPI_CS;
    435    return ucResult;
    436 }
    437 
    438 /////////////////////////////////////////////////////////////////////
    439 //功    能:写RC632寄存器
    440 //参数说明:Address[IN]:寄存器地址
    441 //          value[IN]:写入的值
    442 /////////////////////////////////////////////////////////////////////
    443 void WriteRawRC(u8   Address, u8   value)
    444 {  
    445     u8   ucAddr;
    446 //    u8 tmp;
    447 
    448     CLR_SPI_CS;
    449     ucAddr = ((Address<<1)&0x7E);
    450 
    451     SPIWriteByte(ucAddr);
    452     SPIWriteByte(value);
    453     SET_SPI_CS;
    454 
    455 //    tmp=ReadRawRC(Address);
    456 //
    457 //    if(value!=tmp)
    458 //        printf("wrong
    ");
    459 }
    460 /////////////////////////////////////////////////////////////////////
    461 //功    能:置RC522寄存器位
    462 //参数说明:reg[IN]:寄存器地址
    463 //          mask[IN]:置位值
    464 /////////////////////////////////////////////////////////////////////
    465 void SetBitMask(u8   reg,u8   mask)  
    466 {
    467     char   tmp = 0x0;
    468     tmp = ReadRawRC(reg);
    469     WriteRawRC(reg,tmp | mask);  // set bit mask
    470 }
    471 
    472 /////////////////////////////////////////////////////////////////////
    473 //功    能:清RC522寄存器位
    474 //参数说明:reg[IN]:寄存器地址
    475 //          mask[IN]:清位值
    476 /////////////////////////////////////////////////////////////////////
    477 void ClearBitMask(u8   reg,u8   mask)  
    478 {
    479     char   tmp = 0x0;
    480     tmp = ReadRawRC(reg);
    481     WriteRawRC(reg, tmp & ~mask);  // clear bit mask
    482 } 
    483 
    484 /////////////////////////////////////////////////////////////////////
    485 //功    能:通过RC522和ISO14443卡通讯
    486 //参数说明:Command[IN]:RC522命令字
    487 //          pIn [IN]:通过RC522发送到卡片的数据
    488 //          InLenByte[IN]:发送数据的字节长度
    489 //          pOut [OUT]:接收到的卡片返回数据
    490 //          *pOutLenBit[OUT]:返回数据的位长度
    491 /////////////////////////////////////////////////////////////////////
    492 char PcdComMF522(u8   Command, 
    493                  u8 *pIn , 
    494                  u8   InLenByte,
    495                  u8 *pOut , 
    496                  u8 *pOutLenBit)
    497 {
    498     char   status = MI_ERR;
    499     u8   irqEn   = 0x00;
    500     u8   waitFor = 0x00;
    501     u8   lastBits;
    502     u8   n;
    503     u16   i;
    504     switch (Command)
    505     {
    506         case PCD_AUTHENT:
    507             irqEn   = 0x12;
    508             waitFor = 0x10;
    509             break;
    510         case PCD_TRANSCEIVE:
    511             irqEn   = 0x77;
    512             waitFor = 0x30;
    513             break;
    514         default:
    515             break;
    516     }
    517    
    518     WriteRawRC(ComIEnReg,irqEn|0x80);
    519     ClearBitMask(ComIrqReg,0x80);    //清所有中断位
    520     WriteRawRC(CommandReg,PCD_IDLE);
    521     SetBitMask(FIFOLevelReg,0x80);         //清FIFO缓存
    522     
    523     for (i=0; i<InLenByte; i++)
    524     {   WriteRawRC(FIFODataReg, pIn [i]);    }
    525     WriteRawRC(CommandReg, Command);      
    526 //        n = ReadRawRC(CommandReg);
    527     
    528     if (Command == PCD_TRANSCEIVE)
    529     {    SetBitMask(BitFramingReg,0x80);  }     //开始传送
    530                                              
    531     //i = 600;//根据时钟频率调整,操作M1卡最大等待时间25ms
    532     i = 2000;
    533     do 
    534     {
    535         n = ReadRawRC(ComIrqReg);
    536         i--;
    537     }
    538     while ((i!=0) && !(n&0x01) && !(n&waitFor));
    539     ClearBitMask(BitFramingReg,0x80);
    540 
    541     if (i!=0)
    542     {    
    543         if(!(ReadRawRC(ErrorReg)&0x1B))
    544         {
    545             status = MI_OK;
    546             if (n & irqEn & 0x01)
    547             {   status = MI_NOTAGERR;   }
    548             if (Command == PCD_TRANSCEIVE)
    549             {
    550                    n = ReadRawRC(FIFOLevelReg);
    551                   lastBits = ReadRawRC(ControlReg) & 0x07;
    552                 if (lastBits)
    553                 {   *pOutLenBit = (n-1)*8 + lastBits;   }
    554                 else
    555                 {   *pOutLenBit = n*8;   }
    556                 if (n == 0)
    557                 {   n = 1;    }
    558                 if (n > MAXRLEN)
    559                 {   n = MAXRLEN;   }
    560                 for (i=0; i<n; i++)
    561                 {   pOut [i] = ReadRawRC(FIFODataReg);    }
    562             }
    563         }
    564         else
    565         {   status = MI_ERR;   }
    566         
    567     }
    568    
    569 
    570     SetBitMask(ControlReg,0x80);           // stop timer now
    571     WriteRawRC(CommandReg,PCD_IDLE); 
    572     return status;
    573 }
    574 
    575 /////////////////////////////////////////////////////////////////////
    576 //开启天线  
    577 //每次启动或关闭天险发射之间应至少有1ms的间隔
    578 /////////////////////////////////////////////////////////////////////
    579 void PcdAntennaOn(void)
    580 {
    581     u8   i;
    582     i = ReadRawRC(TxControlReg);
    583     if (!(i & 0x03))
    584     {
    585         SetBitMask(TxControlReg, 0x03);
    586     }
    587 }
    588 
    589 
    590 /////////////////////////////////////////////////////////////////////
    591 //关闭天线
    592 /////////////////////////////////////////////////////////////////////
    593 void PcdAntennaOff(void)
    594 {
    595     ClearBitMask(TxControlReg, 0x03);
    596 }
    597 
    598 /////////////////////////////////////////////////////////////////////
    599 //功    能:扣款和充值
    600 //参数说明: dd_mode[IN]:命令字
    601 //               0xC0 = 扣款
    602 //               0xC1 = 充值
    603 //          addr[IN]:钱包地址
    604 //          pValue[IN]:4字节增(减)值,低位在前
    605 //返    回: 成功返回MI_OK
    606 /////////////////////////////////////////////////////////////////////                 
    607 char PcdValue(u8 dd_mode,u8 addr,u8 *pValue)
    608 {
    609     char status;
    610     u8  unLen;
    611     u8 ucComMF522Buf[MAXRLEN]; 
    612     //u8 i;
    613     
    614     ucComMF522Buf[0] = dd_mode;
    615     ucComMF522Buf[1] = addr;
    616     CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
    617  
    618     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
    619 
    620     if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
    621     {   status = MI_ERR;   }
    622         
    623     if (status == MI_OK)
    624     {
    625         memcpy(ucComMF522Buf, pValue, 4);
    626         //for (i=0; i<16; i++)
    627         //{    ucComMF522Buf[i] = *(pValue+i);   }
    628         CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);
    629         unLen = 0;
    630         status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);
    631         if (status != MI_ERR)
    632         {    status = MI_OK;    }
    633     }
    634     
    635     if (status == MI_OK)
    636     {
    637         ucComMF522Buf[0] = PICC_TRANSFER;
    638         ucComMF522Buf[1] = addr;
    639         CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); 
    640    
    641         status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
    642 
    643         if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
    644         {   status = MI_ERR;   }
    645     }
    646     return status;
    647 }
    648 
    649 /////////////////////////////////////////////////////////////////////
    650 //功    能:备份钱包
    651 //参数说明: sourceaddr[IN]:源地址
    652 //          goaladdr[IN]:目标地址
    653 //返    回: 成功返回MI_OK
    654 /////////////////////////////////////////////////////////////////////
    655 char PcdBakValue(u8 sourceaddr, u8 goaladdr)
    656 {
    657     char status;
    658     u8  unLen;
    659     u8 ucComMF522Buf[MAXRLEN]; 
    660 
    661     ucComMF522Buf[0] = PICC_RESTORE;
    662     ucComMF522Buf[1] = sourceaddr;
    663     CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
    664  
    665     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
    666 
    667     if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
    668     {   status = MI_ERR;   }
    669     
    670     if (status == MI_OK)
    671     {
    672         ucComMF522Buf[0] = 0;
    673         ucComMF522Buf[1] = 0;
    674         ucComMF522Buf[2] = 0;
    675         ucComMF522Buf[3] = 0;
    676         CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);
    677  
    678         status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);
    679         if (status != MI_ERR)
    680         {    status = MI_OK;    }
    681     }
    682     
    683     if (status != MI_OK)
    684     {    return MI_ERR;   }
    685     
    686     ucComMF522Buf[0] = PICC_TRANSFER;
    687     ucComMF522Buf[1] = goaladdr;
    688 
    689     CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
    690  
    691     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
    692 
    693     if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
    694     {   status = MI_ERR;   }
    695 
    696     return status;
    697 }

    一. STM32 + RC522(模拟SPI 模式)

    1. 头文件: rc522.h

     

      1 #ifndef _RC522_H
      2 #define _RC522_H
      3 #include "sys.h"
      4 #include "delay.h"
      5 
      6 
      7 /////////////////////////////////////////////////////////////////////
      8 //MF522命令字
      9 /////////////////////////////////////////////////////////////////////
     10 #define PCD_IDLE              0x00               //取消当前命令
     11 #define PCD_AUTHENT           0x0E               //验证密钥
     12 #define PCD_RECEIVE           0x08               //接收数据
     13 #define PCD_TRANSMIT          0x04               //发送数据
     14 #define PCD_TRANSCEIVE        0x0C               //发送并接收数据
     15 #define PCD_RESETPHASE        0x0F               //复位
     16 #define PCD_CALCCRC           0x03               //CRC计算
     17 
     18 /////////////////////////////////////////////////////////////////////
     19 //Mifare_One卡片命令字
     20 /////////////////////////////////////////////////////////////////////
     21 #define PICC_REQIDL           0x26               //寻天线区内未进入休眠状态
     22 #define PICC_REQALL           0x52               //寻天线区内全部卡
     23 #define PICC_ANTICOLL1        0x93               //防冲撞
     24 #define PICC_ANTICOLL2        0x95               //防冲撞
     25 #define PICC_AUTHENT1A        0x60               //验证A密钥
     26 #define PICC_AUTHENT1B        0x61               //验证B密钥
     27 #define PICC_READ             0x30               //读块
     28 #define PICC_WRITE            0xA0               //写块
     29 #define PICC_DECREMENT        0xC0               //扣款
     30 #define PICC_INCREMENT        0xC1               //充值
     31 #define PICC_RESTORE          0xC2               //调块数据到缓冲区
     32 #define PICC_TRANSFER         0xB0               //保存缓冲区中数据
     33 #define PICC_HALT             0x50               //休眠
     34 
     35 /////////////////////////////////////////////////////////////////////
     36 //MF522 FIFO长度定义
     37 /////////////////////////////////////////////////////////////////////
     38 #define DEF_FIFO_LENGTH       64                 //FIFO size=64byte
     39 
     40 /////////////////////////////////////////////////////////////////////
     41 //MF522寄存器定义
     42 /////////////////////////////////////////////////////////////////////
     43 // PAGE 0
     44 #define     RFU00                 0x00    
     45 #define     CommandReg            0x01    
     46 #define     ComIEnReg             0x02    
     47 #define     DivlEnReg             0x03    
     48 #define     ComIrqReg             0x04    
     49 #define     DivIrqReg             0x05
     50 #define     ErrorReg              0x06    
     51 #define     Status1Reg            0x07    
     52 #define     Status2Reg            0x08    
     53 #define     FIFODataReg           0x09
     54 #define     FIFOLevelReg          0x0A
     55 #define     WaterLevelReg         0x0B
     56 #define     ControlReg            0x0C
     57 #define     BitFramingReg         0x0D
     58 #define     CollReg               0x0E
     59 #define     RFU0F                 0x0F
     60 // PAGE 1     
     61 #define     RFU10                 0x10
     62 #define     ModeReg               0x11
     63 #define     TxModeReg             0x12
     64 #define     RxModeReg             0x13
     65 #define     TxControlReg          0x14
     66 #define     TxAutoReg             0x15
     67 #define     TxSelReg              0x16
     68 #define     RxSelReg              0x17
     69 #define     RxThresholdReg        0x18
     70 #define     DemodReg              0x19
     71 #define     RFU1A                 0x1A
     72 #define     RFU1B                 0x1B
     73 #define     MifareReg             0x1C
     74 #define     RFU1D                 0x1D
     75 #define     RFU1E                 0x1E
     76 #define     SerialSpeedReg        0x1F
     77 // PAGE 2    
     78 #define     RFU20                 0x20  
     79 #define     CRCResultRegM         0x21
     80 #define     CRCResultRegL         0x22
     81 #define     RFU23                 0x23
     82 #define     ModWidthReg           0x24
     83 #define     RFU25                 0x25
     84 #define     RFCfgReg              0x26
     85 #define     GsNReg                0x27
     86 #define     CWGsCfgReg            0x28
     87 #define     ModGsCfgReg           0x29
     88 #define     TModeReg              0x2A
     89 #define     TPrescalerReg         0x2B
     90 #define     TReloadRegH           0x2C
     91 #define     TReloadRegL           0x2D
     92 #define     TCounterValueRegH     0x2E
     93 #define     TCounterValueRegL     0x2F
     94 // PAGE 3      
     95 #define     RFU30                 0x30
     96 #define     TestSel1Reg           0x31
     97 #define     TestSel2Reg           0x32
     98 #define     TestPinEnReg          0x33
     99 #define     TestPinValueReg       0x34
    100 #define     TestBusReg            0x35
    101 #define     AutoTestReg           0x36
    102 #define     VersionReg            0x37
    103 #define     AnalogTestReg         0x38
    104 #define     TestDAC1Reg           0x39  
    105 #define     TestDAC2Reg           0x3A   
    106 #define     TestADCReg            0x3B   
    107 #define     RFU3C                 0x3C   
    108 #define     RFU3D                 0x3D   
    109 #define     RFU3E                 0x3E   
    110 #define     RFU3F          0x3F
    111 
    112 /////////////////////////////////////////////////////////////////////
    113 //和MF522通讯时返回的错误代码
    114 /////////////////////////////////////////////////////////////////////
    115 #define MI_OK                          0
    116 #define MI_NOTAGERR                    (-1)
    117 #define MI_ERR                         (-2)
    118 
    119 
    120 #define MF522_NSS PFout(0)    //PF0     SDA
    121 #define MF522_SCK PFout(1)    //PF1
    122 #define MF522_SI PFout(2)    //PF2
    123 #define MF522_SO PFin(3)    //PF3
    124 #define MF522_RST PFout(4)    //PF4
    125 
    126 
    127 /////////////////////////////////////////////////////////////////////
    128 //函数原型
    129 /////////////////////////////////////////////////////////////////////
    130 char PcdReset(void);
    131 void PcdAntennaOn(void);
    132 void PcdAntennaOff(void);
    133 char PcdRequest(unsigned char req_code,unsigned char *pTagType);   
    134 char PcdAnticoll(unsigned char *pSnr);
    135 char PcdSelect(unsigned char *pSnr);         
    136 char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr);     
    137 char PcdRead(unsigned char addr,unsigned char *pData);     
    138 char PcdWrite(unsigned char addr,unsigned char *pData);    
    139 char PcdValue(unsigned char dd_mode,unsigned char addr,unsigned char *pValue);   
    140 char PcdBakValue(unsigned char sourceaddr, unsigned char goaladdr);                                 
    141 char PcdHalt(void);
    142 char PcdComMF522(unsigned char Command, 
    143                  unsigned char *pInData, 
    144                  unsigned char InLenByte,
    145                  unsigned char *pOutData, 
    146                  unsigned int  *pOutLenBit);
    147 void CalulateCRC(unsigned char *pIndata,unsigned char len,unsigned char *pOutData);
    148 void WriteRawRC(unsigned char Address,unsigned char value);
    149 unsigned char ReadRawRC(unsigned char Address); 
    150 void SetBitMask(unsigned char reg,unsigned char mask); 
    151 void ClearBitMask(unsigned char reg,unsigned char mask); 
    152 void RC522_Init(void);
    153 #endif 


    2. C文件:rc522.c

      1 #include "RC522.h"
      2 
      3 #define MAXRLEN 18
      4 
      5 void RC522_Init(void)
      6 {
      7     GPIO_InitTypeDef  GPIO_InitStructure;     
      8     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);        //使能PF端口时钟
      9     
     10     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_4;               
     11     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //推挽输出
     12     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //IO口速度为50MHz
     13     GPIO_Init(GPIOF, &GPIO_InitStructure);                 
     14     GPIO_SetBits(GPIOF,GPIO_Pin_1|GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_4);  //拉高
     15 
     16     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
     17     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;      //上拉输入               
     18     GPIO_Init(GPIOF, &GPIO_InitStructure);                 
     19 }
     20 
     21 
     22 
     23 /////////////////////////////////////////////////////////////////////
     24 //功    能:寻卡
     25 //参数说明: req_code[IN]:寻卡方式
     26 //                0x52 = 寻感应区内所有符合14443A标准的卡
     27 //                0x26 = 寻未进入休眠状态的卡
     28 //          pTagType[OUT]:卡片类型代码
     29 //                0x4400 = Mifare_UltraLight
     30 //                0x0400 = Mifare_One(S50)
     31 //                0x0200 = Mifare_One(S70)
     32 //                0x0800 = Mifare_Pro(X)
     33 //                0x4403 = Mifare_DESFire
     34 //返    回: 成功返回MI_OK
     35 /////////////////////////////////////////////////////////////////////
     36 char PcdRequest(unsigned char req_code,unsigned char *pTagType)
     37 {
     38    char status;  
     39    unsigned int  unLen;
     40    unsigned char ucComMF522Buf[MAXRLEN]; 
     41 
     42    ClearBitMask(Status2Reg,0x08);
     43    WriteRawRC(BitFramingReg,0x07);
     44    SetBitMask(TxControlReg,0x03);
     45  
     46    ucComMF522Buf[0] = req_code;
     47 
     48    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);
     49    
     50    if ((status == MI_OK) && (unLen == 0x10))
     51    {    
     52        *pTagType     = ucComMF522Buf[0];
     53        *(pTagType+1) = ucComMF522Buf[1];
     54    }
     55    else
     56    {   status = MI_ERR;  
     57     }
     58    
     59    return status;
     60 }
     61 
     62 /////////////////////////////////////////////////////////////////////
     63 //功    能:防冲撞
     64 //参数说明: pSnr[OUT]:卡片序列号,4字节
     65 //返    回: 成功返回MI_OK
     66 /////////////////////////////////////////////////////////////////////  
     67 char PcdAnticoll(unsigned char *pSnr)
     68 {
     69     char status;
     70     unsigned char i,snr_check=0;
     71     unsigned int  unLen;
     72     unsigned char ucComMF522Buf[MAXRLEN]; 
     73     
     74 
     75     ClearBitMask(Status2Reg,0x08);
     76     WriteRawRC(BitFramingReg,0x00);
     77     ClearBitMask(CollReg,0x80);
     78  
     79     ucComMF522Buf[0] = PICC_ANTICOLL1;
     80     ucComMF522Buf[1] = 0x20;
     81 
     82     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);
     83 
     84     if (status == MI_OK)
     85     {
     86          for (i=0; i<4; i++)
     87          {   
     88              *(pSnr+i)  = ucComMF522Buf[i];
     89              snr_check ^= ucComMF522Buf[i];
     90 
     91          }
     92          if (snr_check != ucComMF522Buf[i])
     93          {   status = MI_ERR;    }
     94     }
     95     
     96     SetBitMask(CollReg,0x80);
     97     return status;
     98 }
     99 
    100 /////////////////////////////////////////////////////////////////////
    101 //功    能:选定卡片
    102 //参数说明: pSnr[IN]:卡片序列号,4字节
    103 //返    回: 成功返回MI_OK
    104 /////////////////////////////////////////////////////////////////////
    105 char PcdSelect(unsigned char *pSnr)
    106 {
    107     char status;
    108     unsigned char i;
    109     unsigned int  unLen;
    110     unsigned char ucComMF522Buf[MAXRLEN]; 
    111     
    112     ucComMF522Buf[0] = PICC_ANTICOLL1;
    113     ucComMF522Buf[1] = 0x70;
    114     ucComMF522Buf[6] = 0;
    115     for (i=0; i<4; i++)
    116     {
    117         ucComMF522Buf[i+2] = *(pSnr+i);
    118         ucComMF522Buf[6]  ^= *(pSnr+i);
    119     }
    120     CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);
    121   
    122     ClearBitMask(Status2Reg,0x08);
    123 
    124     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);
    125     
    126     if ((status == MI_OK) && (unLen == 0x18))
    127     {   status = MI_OK;  }
    128     else
    129     {   status = MI_ERR;    }
    130 
    131     return status;
    132 }
    133 
    134 /////////////////////////////////////////////////////////////////////
    135 //功    能:验证卡片密码
    136 //参数说明: auth_mode[IN]: 密码验证模式
    137 //                 0x60 = 验证A密钥
    138 //                 0x61 = 验证B密钥 
    139 //          addr[IN]:块地址
    140 //          pKey[IN]:密码
    141 //          pSnr[IN]:卡片序列号,4字节
    142 //返    回: 成功返回MI_OK
    143 /////////////////////////////////////////////////////////////////////               
    144 char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr)
    145 {
    146     char status;
    147     unsigned int  unLen;
    148     unsigned char i,ucComMF522Buf[MAXRLEN]; 
    149 
    150     ucComMF522Buf[0] = auth_mode;
    151     ucComMF522Buf[1] = addr;
    152     for (i=0; i<6; i++)
    153     {    ucComMF522Buf[i+2] = *(pKey+i);   }
    154     for (i=0; i<6; i++)
    155     {    ucComMF522Buf[i+8] = *(pSnr+i);   }
    156  //   memcpy(&ucComMF522Buf[2], pKey, 6); 
    157  //   memcpy(&ucComMF522Buf[8], pSnr, 4); 
    158     
    159     status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);
    160     if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))
    161     {   status = MI_ERR;   }
    162     
    163     return status;
    164 }
    165 
    166 /////////////////////////////////////////////////////////////////////
    167 //功    能:读取M1卡一块数据
    168 //参数说明: addr[IN]:块地址
    169 //          pData[OUT]:读出的数据,16字节
    170 //返    回: 成功返回MI_OK
    171 ///////////////////////////////////////////////////////////////////// 
    172 char PcdRead(unsigned char addr,unsigned char *pData)
    173 {
    174     char status;
    175     unsigned int  unLen;
    176     unsigned char i,ucComMF522Buf[MAXRLEN]; 
    177 
    178     ucComMF522Buf[0] = PICC_READ;
    179     ucComMF522Buf[1] = addr;
    180     CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
    181    
    182     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
    183     if ((status == MI_OK) && (unLen == 0x90))
    184  //   {   memcpy(pData, ucComMF522Buf, 16);   }
    185     {
    186         for (i=0; i<16; i++)
    187         {    *(pData+i) = ucComMF522Buf[i];   }
    188     }
    189     else
    190     {   status = MI_ERR;   }
    191     
    192     return status;
    193 }
    194 
    195 /////////////////////////////////////////////////////////////////////
    196 //功    能:写数据到M1卡一块
    197 //参数说明: addr[IN]:块地址
    198 //          pData[IN]:写入的数据,16字节
    199 //返    回: 成功返回MI_OK
    200 /////////////////////////////////////////////////////////////////////                  
    201 char PcdWrite(unsigned char addr,unsigned char *pData)
    202 {
    203     char status;
    204     unsigned int  unLen;
    205     unsigned char i,ucComMF522Buf[MAXRLEN]; 
    206     
    207     ucComMF522Buf[0] = PICC_WRITE;
    208     ucComMF522Buf[1] = addr;
    209     CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
    210  
    211     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
    212 
    213     if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
    214     {   status = MI_ERR;   }
    215         
    216     if (status == MI_OK)
    217     {
    218         //memcpy(ucComMF522Buf, pData, 16);
    219         for (i=0; i<16; i++)
    220         {    ucComMF522Buf[i] = *(pData+i);   }
    221         CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);
    222 
    223         status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);
    224         if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
    225         {   status = MI_ERR;   }
    226     }
    227     
    228     return status;
    229 }
    230 
    231 /////////////////////////////////////////////////////////////////////
    232 //功    能:扣款和充值
    233 //参数说明: dd_mode[IN]:命令字
    234 //               0xC0 = 扣款
    235 //               0xC1 = 充值
    236 //          addr[IN]:钱包地址
    237 //          pValue[IN]:4字节增(减)值,低位在前
    238 //返    回: 成功返回MI_OK
    239 /////////////////////////////////////////////////////////////////////                 
    240 char PcdValue(unsigned char dd_mode,unsigned char addr,unsigned char *pValue)
    241 {
    242     char status;
    243     unsigned int  unLen;
    244     unsigned char i,ucComMF522Buf[MAXRLEN]; 
    245     
    246     ucComMF522Buf[0] = dd_mode;
    247     ucComMF522Buf[1] = addr;
    248     CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
    249  
    250     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
    251 
    252     if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
    253     {   status = MI_ERR;   }
    254         
    255     if (status == MI_OK)
    256     {
    257        // memcpy(ucComMF522Buf, pValue, 4);
    258         for (i=0; i<16; i++)
    259         {    ucComMF522Buf[i] = *(pValue+i);   }
    260         CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);
    261         unLen = 0;
    262         status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);
    263         if (status != MI_ERR)
    264         {    status = MI_OK;    }
    265     }
    266     
    267     if (status == MI_OK)
    268     {
    269         ucComMF522Buf[0] = PICC_TRANSFER;
    270         ucComMF522Buf[1] = addr;
    271         CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); 
    272    
    273         status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
    274 
    275         if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
    276         {   status = MI_ERR;   }
    277     }
    278     return status;
    279 }
    280 
    281 /////////////////////////////////////////////////////////////////////
    282 //功    能:备份钱包
    283 //参数说明: sourceaddr[IN]:源地址
    284 //          goaladdr[IN]:目标地址
    285 //返    回: 成功返回MI_OK
    286 /////////////////////////////////////////////////////////////////////
    287 char PcdBakValue(unsigned char sourceaddr, unsigned char goaladdr)
    288 {
    289     char status;
    290     unsigned int  unLen;
    291     unsigned char ucComMF522Buf[MAXRLEN]; 
    292 
    293     ucComMF522Buf[0] = PICC_RESTORE;
    294     ucComMF522Buf[1] = sourceaddr;
    295     CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
    296  
    297     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
    298 
    299     if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
    300     {   status = MI_ERR;   }
    301     
    302     if (status == MI_OK)
    303     {
    304         ucComMF522Buf[0] = 0;
    305         ucComMF522Buf[1] = 0;
    306         ucComMF522Buf[2] = 0;
    307         ucComMF522Buf[3] = 0;
    308         CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);
    309  
    310         status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);
    311         if (status != MI_ERR)
    312         {    status = MI_OK;    }
    313     }
    314     
    315     if (status != MI_OK)
    316     {    return MI_ERR;   }
    317     
    318     ucComMF522Buf[0] = PICC_TRANSFER;
    319     ucComMF522Buf[1] = goaladdr;
    320 
    321     CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
    322  
    323     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
    324 
    325     if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))
    326     {   status = MI_ERR;   }
    327 
    328     return status;
    329 }
    330 
    331 
    332 /////////////////////////////////////////////////////////////////////
    333 //功    能:命令卡片进入休眠状态
    334 //返    回: 成功返回MI_OK
    335 /////////////////////////////////////////////////////////////////////
    336 char PcdHalt(void)
    337 {
    338     char status;
    339     unsigned int  unLen;
    340     unsigned char ucComMF522Buf[MAXRLEN]; 
    341 
    342     ucComMF522Buf[0] = PICC_HALT;
    343     ucComMF522Buf[1] = 0;
    344     CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);
    345  
    346     status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);
    347 
    348     return MI_OK;
    349 }
    350 
    351 /////////////////////////////////////////////////////////////////////
    352 //用MF522计算CRC16函数
    353 /////////////////////////////////////////////////////////////////////
    354 void CalulateCRC(unsigned char *pIndata,unsigned char len,unsigned char *pOutData)
    355 {
    356     unsigned char i,n;
    357     ClearBitMask(DivIrqReg,0x04);
    358     WriteRawRC(CommandReg,PCD_IDLE);
    359     SetBitMask(FIFOLevelReg,0x80);
    360     for (i=0; i<len; i++)
    361     {   WriteRawRC(FIFODataReg, *(pIndata+i));   }
    362     WriteRawRC(CommandReg, PCD_CALCCRC);
    363     i = 0xFF;
    364     do 
    365     {
    366         n = ReadRawRC(DivIrqReg);
    367         i--;
    368     }
    369     while ((i!=0) && !(n&0x04));
    370     pOutData[0] = ReadRawRC(CRCResultRegL);
    371     pOutData[1] = ReadRawRC(CRCResultRegM);
    372 }
    373 
    374 /////////////////////////////////////////////////////////////////////
    375 //功    能:复位RC522
    376 //返    回: 成功返回MI_OK
    377 /////////////////////////////////////////////////////////////////////
    378 char PcdReset(void)
    379 {
    380     //unsigned char i;
    381     MF522_RST=1;
    382 
    383         delay_us(10);                  
    384 
    385     MF522_RST=0;
    386 
    387         delay_us(10);                   
    388 
    389     MF522_RST=1;
    390 
    391         delay_us(10);                 
    392     
    393     WriteRawRC(CommandReg,PCD_RESETPHASE);
    394 
    395         delay_us(10);                  
    396     
    397     
    398     WriteRawRC(ModeReg,0x3D);            //和Mifare卡通讯,CRC初始值0x6363
    399     WriteRawRC(TReloadRegL,30);           
    400     WriteRawRC(TReloadRegH,0);
    401     WriteRawRC(TModeReg,0x8D);
    402     WriteRawRC(TPrescalerReg,0x3E);
    403    WriteRawRC(TxAutoReg,0x40);
    404     return MI_OK;
    405 }
    406 
    407 /////////////////////////////////////////////////////////////////////
    408 //功    能:读RC632寄存器
    409 //参数说明:Address[IN]:寄存器地址
    410 //返    回:读出的值
    411 /////////////////////////////////////////////////////////////////////
    412 unsigned char ReadRawRC(unsigned char Address)
    413 {
    414      unsigned char i, ucAddr;
    415      unsigned char ucResult=0;
    416 
    417      MF522_SCK = 0;
    418      MF522_NSS = 0;
    419      ucAddr = ((Address<<1)&0x7E)|0x80;
    420 
    421      for(i=8;i>0;i--)
    422      {
    423          MF522_SI = ((ucAddr&0x80)==0x80);
    424          MF522_SCK = 1;
    425          ucAddr <<= 1;
    426          MF522_SCK = 0;
    427          delay_us(10);       //STM32需要多加的延时时间。51的不需要加
    428      }
    429 
    430      for(i=8;i>0;i--)
    431      {
    432          MF522_SCK = 1;
    433          ucResult <<= 1;
    434          ucResult|=MF522_SO;
    435          MF522_SCK = 0;
    436          delay_us(10);      //STM32需要多加的延时时间。51的不需要加
    437      }
    438 
    439      MF522_NSS = 1;
    440      MF522_SCK = 1;
    441      return ucResult;
    442 }
    443 
    444 /////////////////////////////////////////////////////////////////////
    445 //功    能:写RC632寄存器
    446 //参数说明:Address[IN]:寄存器地址
    447 //          value[IN]:写入的值
    448 /////////////////////////////////////////////////////////////////////
    449 void WriteRawRC(unsigned char Address, unsigned char value)
    450 {  
    451     unsigned char i, ucAddr;
    452 
    453     MF522_SCK = 0;
    454     MF522_NSS = 0;
    455     ucAddr = ((Address<<1)&0x7E);
    456 
    457     for(i=8;i>0;i--)
    458     {
    459         MF522_SI = ((ucAddr&0x80)==0x80);
    460         MF522_SCK = 1;
    461         ucAddr <<= 1;
    462         MF522_SCK = 0;
    463         delay_us(10);       //STM32需要多加的延时时间。51的不需要加
    464     }
    465 
    466     for(i=8;i>0;i--)
    467     {
    468         MF522_SI = ((value&0x80)==0x80);
    469         MF522_SCK = 1;
    470         value <<= 1;
    471         MF522_SCK = 0;
    472         delay_us(10);     //STM32需要多加的延时时间。51的不需要加
    473     }
    474     MF522_NSS = 1;
    475     MF522_SCK = 1;
    476 }
    477 
    478 /////////////////////////////////////////////////////////////////////
    479 //功    能:置RC522寄存器位
    480 //参数说明:reg[IN]:寄存器地址
    481 //          mask[IN]:置位值
    482 /////////////////////////////////////////////////////////////////////
    483 void SetBitMask(unsigned char reg,unsigned char mask)  
    484 {
    485     char tmp = 0x0;
    486     tmp = ReadRawRC(reg);
    487     WriteRawRC(reg,tmp | mask);  // set bit mask
    488 }
    489 
    490 /////////////////////////////////////////////////////////////////////
    491 //功    能:清RC522寄存器位
    492 //参数说明:reg[IN]:寄存器地址
    493 //          mask[IN]:清位值
    494 /////////////////////////////////////////////////////////////////////
    495 void ClearBitMask(unsigned char reg,unsigned char mask)  
    496 {
    497     char tmp = 0x0;
    498     tmp = ReadRawRC(reg);
    499     WriteRawRC(reg, tmp & ~mask);  // clear bit mask
    500 } 
    501 
    502 /////////////////////////////////////////////////////////////////////
    503 //功    能:通过RC522和ISO14443卡通讯
    504 //参数说明:Command[IN]:RC522命令字
    505 //          pInData[IN]:通过RC522发送到卡片的数据
    506 //          InLenByte[IN]:发送数据的字节长度
    507 //          pOutData[OUT]:接收到的卡片返回数据
    508 //          *pOutLenBit[OUT]:返回数据的位长度
    509 /////////////////////////////////////////////////////////////////////
    510 char PcdComMF522(unsigned char Command, 
    511                  unsigned char *pInData, 
    512                  unsigned char InLenByte,
    513                  unsigned char *pOutData, 
    514                  unsigned int  *pOutLenBit)
    515 {
    516     char status = MI_ERR;
    517     unsigned char irqEn   = 0x00;
    518     unsigned char waitFor = 0x00;
    519     unsigned char lastBits;
    520     unsigned char n;
    521     unsigned int i;
    522     switch (Command)
    523     {
    524        case PCD_AUTHENT:
    525           irqEn   = 0x12;
    526           waitFor = 0x10;
    527           break;
    528        case PCD_TRANSCEIVE:
    529           irqEn   = 0x77;
    530           waitFor = 0x30;
    531           break;
    532        default:
    533          break;
    534     }
    535    
    536     WriteRawRC(ComIEnReg,irqEn|0x80);
    537     ClearBitMask(ComIrqReg,0x80);
    538     WriteRawRC(CommandReg,PCD_IDLE);
    539     SetBitMask(FIFOLevelReg,0x80);
    540     
    541     for (i=0; i<InLenByte; i++)
    542     {   WriteRawRC(FIFODataReg, pInData[i]);    }
    543     WriteRawRC(CommandReg, Command);
    544    
    545     
    546     if (Command == PCD_TRANSCEIVE)
    547     {    SetBitMask(BitFramingReg,0x80);  }
    548     
    549     i = 600;//根据时钟频率调整,操作M1卡最大等待时间25ms
    550     do 
    551     {
    552          n = ReadRawRC(ComIrqReg);
    553          i--;
    554     }
    555     while ((i!=0) && !(n&0x01) && !(n&waitFor));
    556     ClearBitMask(BitFramingReg,0x80);
    557           
    558     if (i!=0)
    559     {    
    560          if(!(ReadRawRC(ErrorReg)&0x1B))
    561          {
    562              status = MI_OK;
    563              if (n & irqEn & 0x01)
    564              {   status = MI_NOTAGERR;   }
    565              if (Command == PCD_TRANSCEIVE)
    566              {
    567                    n = ReadRawRC(FIFOLevelReg);
    568                   lastBits = ReadRawRC(ControlReg) & 0x07;
    569                 if (lastBits)
    570                 {   *pOutLenBit = (n-1)*8 + lastBits;   }
    571                 else
    572                 {   *pOutLenBit = n*8;   }
    573                 if (n == 0)
    574                 {   n = 1;    }
    575                 if (n > MAXRLEN)
    576                 {   n = MAXRLEN;   }
    577                 for (i=0; i<n; i++)
    578                 {   pOutData[i] = ReadRawRC(FIFODataReg);    }
    579             }
    580          }
    581          else
    582          {   status = MI_ERR;   }
    583         
    584    }
    585    
    586 
    587    SetBitMask(ControlReg,0x80);           // stop timer now
    588    WriteRawRC(CommandReg,PCD_IDLE); 
    589    return status;
    590 }
    591 
    592 
    593 /////////////////////////////////////////////////////////////////////
    594 //开启天线  
    595 //每次启动或关闭天险发射之间应至少有1ms的间隔
    596 /////////////////////////////////////////////////////////////////////
    597 void PcdAntennaOn()
    598 {
    599     unsigned char i;
    600     i = ReadRawRC(TxControlReg);
    601     if (!(i & 0x03))
    602     {
    603         SetBitMask(TxControlReg, 0x03);
    604     }
    605 }
    606 
    607 
    608 /////////////////////////////////////////////////////////////////////
    609 //关闭天线
    610 /////////////////////////////////////////////////////////////////////
    611 void PcdAntennaOff()
    612 {
    613     ClearBitMask(TxControlReg, 0x03);
    614 }

     

  • 相关阅读:
    极客时间趣谈网络协议第一模块 通信协议综述 总结
    acl
    go context 梳理
    go sync 包梳理
    SQL优化
    .NET 6 支持的Windows 版本
    SQL Group By 和 Having 的区别
    SQLServer select语句执行流程
    NSwag, Swagger 调试 404
    转载: 数据库相关知识,理论及优化
  • 原文地址:https://www.cnblogs.com/hbtmwangjin/p/8534696.html
Copyright © 2020-2023  润新知