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\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 模式)
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 }
本文章為轉載內容,我們尊重原作者對文章享有的著作權。如有內容錯誤或侵權問題,歡迎原作者聯繫我們進行內容更正或刪除文章。