STM32 + RC522(SPI2 和 模擬SPI)

STM32 + RC522(SPI2 和 模擬SPI)緩存

一. STM32 + RC522(SPI2 模式)函數

1. 頭文件: rc522.hspa

 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.ccode

 

 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\n");
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 模式)blog

1. 頭文件: rc522.hip

 

 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 }
相關文章
相關標籤/搜索