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 }

 

原文地址:https://www.cnblogs.com/hbtmwangjin/p/8534696.html