RFID-RC522 与Arduino的连接

一、前几天在某宝上刚买了个RFID-RC522  ,目标是复制我的门禁卡(看样子没多大希望了)。
二、各种百度各种谷歌都没找到与Arduino的连接方式。

so,分享下我的连接方式,与大家共同进步。。。。

材料:
1、Arduino Uno R3
2、RFID-RC522
3、连接线7根

 

最下面一根红色为3.3v的电源。
最上面的为SDA,其它照图连接就可以了。

 

下面是测试代码:

  1 #include <SPI.h>
  2  
  3 #define uchar unsigned char
  4 #define uint unsigned int
  5  
  6 //数据数组的最大长度 
  7 #define MAX_LEN 16
  8  
  9 /////////////////////////////////////////////////////////////////////
 10 //set the pin设置引脚
 11 /////////////////////////////////////////////////////////////////////
 12 const int chipSelectPin = 10;    //SDA引脚片选引脚
 13 const int NRSTPD = 5;            //RST引脚
 14  
 15 //MF522 命令位
 16 #define PCD_IDLE 0x00             //取消当前命令不行动
 17 #define PCD_AUTHENT 0x0E         //验证密码的钥匙
 18 #define PCD_RECEIVE 0x08         //接收数据
 19 #define PCD_TRANSMIT 0x04        //发送数据
 20 #define PCD_TRANSCEIVE 0x0C        //发送和接收数据
 21 #define PCD_RESETPHASE 0x0F        //重置
 22 #define PCD_CALCCRC 0x03        //CRC校验和的计算
 23  
 24 //Mifare_One卡的命令位
 25 #define PICC_REQIDL 0x26        //在天线区域搜索不进入睡眠模式的卡 
 26 #define PICC_REQALL 0x52         //搜索天线区域中的所有卡 
 27 #define PICC_ANTICOLL 0x93        //防止冲突 
 28 #define PICC_SElECTTAG 0x93     //选择卡
 29 #define PICC_AUTHENT1A 0x60     //验证A密码密钥
 30 #define PICC_AUTHENT1B 0x61     //验证B密码密钥
 31 #define PICC_READ 0x30            //
 32 #define PICC_WRITE 0xA0            //
 33 #define PICC_DECREMENT 0xC0     //扣除值 
 34 #define PICC_INCREMENT 0xC1     //装载值
 35 #define PICC_RESTORE 0xC2         //还原数据到缓冲区
 36 #define PICC_TRANSFER 0xB0        //保存数据到缓冲区
 37 #define PICC_HALT 0x50             //睡眠模式
 38  
 39 
 40 //通信时MF522的返回值 
 41 #define MI_OK 0
 42 #define MI_NOTAGERR 1
 43 #define MI_ERR 2
 44  
 45 //------------------MFRC522 注册 ---------------
 46 //Page 0:命令和状态
 47 #define Reserved00 0x00             //保留将来之用
 48 #define CommandReg 0x01             //启动和停止命令的执行
 49 #define CommIEnReg 0x02             //中断请求传递的使能和禁能控制位。
 50 #define DivlEnReg 0x03                 //中断请求传递的使能和禁能控制位。
 51 #define CommIrqReg 0x04             //包含中断请求标志
 52 #define DivIrqReg 0x05                //包含中断请求标志
 53 #define ErrorReg 0x06                 //错误标志,指示执行行的上个命令的错误状态
 54 #define Status1Reg 0x07             //包含通信的状态标志
 55 #define Status2Reg 0x08             //包含接收器和发射器的状态标志
 56 #define FIFODataReg 0x09            //64字节FIFO缓冲器的输入输出
 57 #define FIFOLevelReg 0x0A            //指示FIFO中存储的字节数
 58 #define WaterLevelReg 0x0B            //定义FIFO下溢和上溢报警的FIFO深度。
 59 #define ControlReg 0x0C                //不同的控制寄存器
 60 #define BitFramingReg 0x0D            //面向位的帧调节
 61 #define CollReg 0x0E                //RF接口上检测到的第一个位冲突的位的位置
 62 #define Reserved01 0x0F                //保留将来之用
 63 //Page 1:控制 
 64 #define Reserved10 0x10                //保留将来之用
 65 #define ModeReg 0x11                //定义发射和接收的常用模式
 66 #define TxModeReg 0x12                //定义发射过程的数据传输速率
 67 #define RxModeReg 0x13                //定义接收过程中的数据传输速率
 68 #define TxControlReg 0x14            //控制天线驱动管脚TX1和TX2的逻辑特征
 69 #define TxAutoReg 0x15                //控制天线驱动的设置
 70 #define TxSelReg 0x16                //选择天线驱动器的内部源
 71 #define RxSelReg 0x17                //选着内部的接收器设置
 72 #define RxThresholdReg 0x18            //选择位译码器的阀值
 73 #define DemodReg 0x19                //定义解调器的设置
 74 #define Reserved11 0x1A                //保留将来之用
 75 #define Reserved12 0x1B                //保留将来之用
 76 #define MifareReg 0x1C                //控制ISO 14443/MIFARE 模式106kbit/s的通信
 77 #define Reserved13 0x1D                //保留将来之用
 78 #define Reserved14 0x1E                //保留将来之用
 79 #define SerialSpeedReg 0x1F            //选择串行UART接口的速率
 80 //Page 2:发生器
 81 #define Reserved20 0x20                //保留将来之用
 82 #define CRCResultRegM 0x21            //显示CRC计算的实际MSB和LSB值(MSB)
 83 #define CRCResultRegL 0x22            //显示CRC计算的实际MSB和LSB值(LSB)
 84 #define Reserved21 0x23                //保留将来之用
 85 #define ModWidthReg 0x24            //控制ModWidth的设置
 86 #define Reserved22 0x25                //保留将来之用
 87 #define RFCfgReg 0x26                //配置接受器增益
 88 #define GsNReg 0x27                    //选择天线驱动器管脚TX1和TX2的调制电导
 89 #define CWGsPReg 0x28                //选择天线驱动器管脚TX1和TX2的调制电导
 90 #define ModGsPReg 0x29                //选择天线驱动器管脚TX1和TX2的调制电导
 91 #define TModeReg 0x2A                //定义内部定时器的设置A
 92 #define TPrescalerReg 0x2B            //定义内部定时器的设置B
 93 #define TReloadRegH 0x2C            //描述16位长的定时器重装值(C)
 94 #define TReloadRegL 0x2D            //描述16位长的定时器重装值(D)
 95 #define TCounterValueRegH 0x2E        //显示16位长的实际定时器值(E)
 96 #define TCounterValueRegL 0x2F        //显示16位长的实际定时器值(F)
 97 //Page 3:记录 
 98 #define Reserved30 0x30                //保留将来之用
 99 #define TestSel1Reg 0x31            //常用测试信号的配置
100 #define TestSel2Reg 0x32            //常用测试信号的配置和PRBS控制
101 #define TestPinEnReg 0x33            //D1—D7输出驱动器的使能管脚(注:仅用于串行接口)
102 #define TestPinValueReg 0x34        //定义D1-D7用做I/O总线的值
103 #define TestBusReg 0x35                //显示内部测试总线的状态
104 #define AutoTestReg 0x36            //控制数字自测试
105 #define VersionReg 0x37                //显示版本
106 #define AnalogTestReg 0x38            //控制管脚AUX1和AUX2
107 #define TestDAC1Reg 0x39             //定义 TestDAC1的测试值
108 #define TestDAC2Reg 0x3A             //定义 TestDAC2的测试值
109 #define TestADCReg 0x3B             //显示 ADC I和 Q通道的实际值
110 #define Reserved31 0x3C             //保留用于产品测试
111 #define Reserved32 0x3D             //保留用于产品测试
112 #define Reserved33 0x3E             //保留用于产品测试
113 #define Reserved34 0x3F                //保留用于产品测试
114 //-----------------------------------------------
115  
116 //4字节序列号卡,5字节字节是核准
117 uchar serNum[5];
118  
119 void setup() 
120 { 
121     Serial.begin(57600); 
122      
123     SPI.begin();
124      
125     pinMode(chipSelectPin,OUTPUT);        //设置数字引脚10作为输出连接到RFID/使能引脚
126     digitalWrite(chipSelectPin, LOW);    //激活RFID阅读器(片选)
127     pinMode(NRSTPD,OUTPUT);                //设置数字引脚5,不复位和断电(复位引脚)
128     
129     MFRC522_Init(); 
130 }
131  
132 void loop()
133 {
134  
135     uchar status;
136     uchar str[MAX_LEN];
137  
138      
139     //搜索卡,返回卡类型
140     status = MFRC522_Request(PICC_REQIDL, str); 
141     if (status != MI_OK)
142     {
143         return;
144     }
145     //查看卡的类型
146     ShowCardType(str);
147      
148     //防止冲突返回网卡的4字节序列号
149     status = MFRC522_Anticoll(str);
150      
151     // str[0..3]: 卡片序列号
152     // str[4]: XOR checksum of the SN.(SN的异或校验。)
153     if (status == MI_OK)
154     {
155         Serial.print("The card's number is: ");
156         memcpy(serNum, str, 5);
157         ShowCardID(serNum);
158      
159         //ID卡的相关身份验证
160         uchar* id = serNum;
161         if( id[0]==0x4B && id[1]==0xE6 && id[2]==0xD1 && id[3]==0x3B ) {
162             Serial.println("Hello Mary!");
163         } else if(id[0]==0x3B && id[1]==0xE6 && id[2]==0xD1 && id[3]==0x3B) {
164             Serial.println("Hello Greg!");
165         }else{
166             Serial.println("Hello unkown guy!");
167         }
168     }
169  
170     
171     MFRC522_Halt(); //命令卡进入休眠模式
172     delay(200);
173 }
174  
175 /*
176  * Function:ShowCardID
177  * Description:显示卡的ID 
178  * Input parameter:ID string
179  * Return:Null
180  */
181 void ShowCardID(uchar *id)
182 {
183     int IDlen=4;
184     for(int i=0; i<IDlen; i++){
185         Serial.print(0x0F & (id[i]>>4), HEX);
186         Serial.print(0x0F & id[i],HEX);
187     }
188     Serial.println("");
189 }
190  
191 /*
192  * Function:ShowCardType
193  * Description:显示卡类型
194  * Input parameter:Type string
195  * Return:Null
196  */
197 void ShowCardType(uchar* type)
198 {
199     Serial.print("Card type: ");
200     if(type[0]==0x04&&type[1]==0x00) 
201         Serial.println("MFOne-S50");
202     else if(type[0]==0x02&&type[1]==0x00)
203         Serial.println("MFOne-S70");
204     else if(type[0]==0x44&&type[1]==0x00)
205         Serial.println("MF-UltraLight");
206     else if(type[0]==0x08&&type[1]==0x00)
207         Serial.println("MF-Pro");
208     else if(type[0]==0x44&&type[1]==0x03)
209         Serial.println("MF Desire");
210     else
211         Serial.println("Unknown");
212 }
213  
214 /*
215  * Function:Write_MFRC5200
216  * Description:写一个字节的数据到一个登记的MR RC522
217  * Input parameter:addr--register address;val--the value that need to write in
218  * Return:Null
219  */
220 void Write_MFRC522(uchar addr, uchar val)
221 {
222     digitalWrite(chipSelectPin, LOW);
223  
224     //address format:0XXXXXX0
225     SPI.transfer((addr<<1)&0x7E); 
226     SPI.transfer(val);
227      
228     digitalWrite(chipSelectPin, HIGH);
229 }
230  
231  
232 /*
233  * Function:Read_MFRC522
234  * Description:读一个字节的数据到一个登记的MR RC522
235  * Input parameter:addr--register address
236  * Return:return the read value
237  */
238 uchar Read_MFRC522(uchar addr)
239 {
240     uchar val;
241  
242     digitalWrite(chipSelectPin, LOW);
243  
244     //地址形式:1XXXXXX0
245     SPI.transfer(((addr<<1)&0x7E) | 0x80); 
246     val =SPI.transfer(0x00);
247      
248     digitalWrite(chipSelectPin, HIGH);
249      
250     return val; 
251 }
252  
253 /*
254  * Function:SetBitMask
255  * Description:设置RC522寄存器位
256  * Input parameter:reg--register address;mask--value
257  * Return:null
258  */
259 void SetBitMask(uchar reg, uchar mask) 
260 {
261     uchar tmp;
262     tmp = Read_MFRC522(reg);
263     Write_MFRC522(reg, tmp | mask); //设置掩码位
264 }
265  
266  
267 /*
268  * Function:ClearBitMask
269  * Description:清除RC522寄存器位
270  * Input parameter:reg--register address;mask--value
271  * Return:null
272  */
273 void ClearBitMask(uchar reg, uchar mask) 
274 {
275     uchar tmp;
276     tmp = Read_MFRC522(reg);
277     Write_MFRC522(reg, tmp & (~mask)); //清除掩码
278 } 
279  
280 /*
281  * Function:AntennaOn
282  * Description:打开天线,每一次打开的天线所需要至少1ms
283  * Input parameter:null
284  * Return:null
285  */
286 void AntennaOn(void)
287 {
288     uchar temp;
289  
290     temp = Read_MFRC522(TxControlReg);
291     if (!(temp & 0x03))
292     {
293         SetBitMask(TxControlReg, 0x03);
294     }
295 }
296  
297  
298 /*
299  * Function:AntennaOff
300  * Description:关闭天线,每次关闭天线至少需要1ms
301  * Input parameter:null
302  * Return:null
303  */
304 void AntennaOff(void)
305 {
306     ClearBitMask(TxControlReg, 0x03);
307 }
308  
309 /*
310  * Function:ResetMFRC522
311  * Description:重置RC522
312  * Input parameter:null
313  * Return:null
314  */
315 void MFRC522_Reset(void)
316 {
317     Write_MFRC522(CommandReg, PCD_RESETPHASE);        //重置RC522
318 }
319  
320 /*
321  * Function:InitMFRC522
322  * Description:初始化RC522
323  * Input parameter:null
324  * Return:null
325  */
326 void MFRC522_Init(void)
327 {
328     digitalWrite(NRSTPD,HIGH);                //复位引脚
329  
330     MFRC522_Reset();                //重置RC522
331           
332     //定时器: TPrescaler*TreloadVal/6.78MHz = 24ms
333     Write_MFRC522(TModeReg, 0x8D);            //Tauto=1; f(Timer) = 6.78MHz/TPreScaler
334     Write_MFRC522(TPrescalerReg, 0x3E);        //TModeReg[3..0] + TPrescalerReg
335     Write_MFRC522(TReloadRegL, 30); 
336     Write_MFRC522(TReloadRegH, 0);
337      
338     Write_MFRC522(TxAutoReg, 0x40);            //100%ASK
339     Write_MFRC522(ModeReg, 0x3D);            //CRC效验值0x6363 ???
340  
341     //ClearBitMask(Status2Reg, 0x08); //MFCrypto1On=0
342     //Write_MFRC522(RxSelReg, 0x86); //RxWait = RxSelReg[5..0]
343     //Write_MFRC522(RFCfgReg, 0x7F); //RxGain = 48dB
344  
345     AntennaOn();                    //打开天线
346 }
347  
348 /*
349  * Function:MFRC522_Request
350  * Description:搜寻卡,读取卡的类型
351  * Input parameter:reqMode--搜寻方法,
352  *     TagType--返回卡的类型
353  *     0x4400 = Mifare_UltraLight
354  *     0x0400 = Mifare_One(S50)
355  *     0x0200 = Mifare_One(S70)
356  *     0x0800 = Mifare_Pro(X)
357  *     0x4403 = Mifare_DESFire
358  * return:return MI_OK if successed
359  */
360 uchar MFRC522_Request(uchar reqMode, uchar *TagType)
361 {
362     uchar status; 
363     uint backBits;                                //接收到的数据比特
364  
365     Write_MFRC522(BitFramingReg, 0x07);         //TxLastBists = BitFramingReg[2..0] ???
366      
367     TagType[0] = reqMode;
368     status = MFRC522_ToCard(PCD_TRANSCEIVE, TagType, 1, TagType, &backBits);
369  
370     if ((status != MI_OK) || (backBits != 0x10))
371     { 
372         status = MI_ERR;
373     }
374     
375     return status;
376 }
377  
378  
379 /*
380  * Function:MFRC522_ToCard
381  * Description:RC522和ISO14443之间通信
382  * Input parameter:command--MF522 command bits
383  * sendData--send data to card via rc522
384  * sendLen--send data length 
385  * backData--the return data from card
386  * backLen--the length of return data
387  * return:return MI_OK if successed
388  */
389 uchar MFRC522_ToCard(uchar command, uchar *sendData, uchar sendLen, uchar *backData, uint *backLen)
390 {
391     uchar status = MI_ERR;
392     uchar irqEn = 0x00;
393     uchar waitIRq = 0x00;
394     uchar lastBits;
395     uchar n;
396     uint i;
397  
398     switch (command)
399     {
400         case PCD_AUTHENT:            //密码验证
401         {
402             irqEn = 0x12;
403             waitIRq = 0x10;
404             break;
405         }
406         case PCD_TRANSCEIVE:         //在FIFO发送数据
407         {
408             irqEn = 0x77;
409             waitIRq = 0x30;
410             break;
411         }
412         default:
413             break;
414     }
415     
416     Write_MFRC522(CommIEnReg, irqEn|0x80);     //允许中断
417     ClearBitMask(CommIrqReg, 0x80);            //清除所有的中断标志位
418     SetBitMask(FIFOLevelReg, 0x80);         //FlushBuffer=1, FIFO 初始化大部分
419      
420     Write_MFRC522(CommandReg, PCD_IDLE); //没有行动;取消现在的命令
421  
422     //把数据持续写入FIFO
423     for (i=0; i<sendLen; i++)
424     { 
425         Write_MFRC522(FIFODataReg, sendData[i]); 
426     }
427  
428     //进行下面
429     Write_MFRC522(CommandReg, command);
430     if (command == PCD_TRANSCEIVE)
431     { 
432         SetBitMask(BitFramingReg, 0x80);     //StartSend=1,开始传送数据
433     } 
434      
435     //等待接收数据完成
436     i = 2000;         //i 应根据时钟调整,等待的时间最大应该是25毫秒
437     do
438     {
439         //CommIrqReg[7..0]
440         //Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq
441         n = Read_MFRC522(CommIrqReg);
442         i--;
443     }
444     while ((i!=0) && !(n&0x01) && !(n&waitIRq));
445  
446     ClearBitMask(BitFramingReg, 0x80); //StartSend=0
447      
448     if (i != 0)
449     { 
450         if(!(Read_MFRC522(ErrorReg) & 0x1B)) //BufferOvfl Collerr CRCErr ProtecolErr
451         {
452             status = MI_OK;
453             if (n & irqEn & 0x01)
454             { 
455                 status = MI_NOTAGERR; //?? 
456             }
457              
458             if (command == PCD_TRANSCEIVE)
459             {
460                 n = Read_MFRC522(FIFOLevelReg);
461                 lastBits = Read_MFRC522(ControlReg) & 0x07;
462                 if (lastBits)
463                 { 
464                     *backLen = (n-1)*8 + lastBits; 
465                 }
466                 else
467                 { 
468                     *backLen = n*8; 
469                 }
470                  
471                 if (n == 0)
472                 { 
473                     n = 1; 
474                 }
475                 if (n > MAX_LEN)
476                 { 
477                     n = MAX_LEN; 
478                 }
479                  
480                 //读取FIFO数据
481                 for (i=0; i<n; i++)
482                 { 
483                     backData[i] = Read_MFRC522(FIFODataReg); 
484                 }
485             }
486         }
487         else
488         { 
489             status = MI_ERR; 
490         }
491          
492     }
493      
494     //SetBitMask(ControlReg,0x80);            //关闭定时器
495     //Write_MFRC522(CommandReg, PCD_IDLE); 
496  
497     return status;
498 }
499  
500  
501 /*
502  * Function:MFRC522_Anticoll
503  * Description:防冲撞,读取卡的连续数据 
504  * Input parameter:serNum--return the 4 bytes card serial number, the 5th byte is recheck byte
505  * return:return MI_OK if successed
506  */
507 uchar MFRC522_Anticoll(uchar *serNum)
508 {
509     uchar status;
510     uchar i;
511     uchar serNumCheck=0;
512     uint unLen;
513      
514     //ClearBitMask(Status2Reg, 0x08);     //strSensclear
515     //ClearBitMask(CollReg,0x80);         //ValuesAfterColl
516     Write_MFRC522(BitFramingReg, 0x00); //TxLastBists = BitFramingReg[2..0]
517   
518     serNum[0] = PICC_ANTICOLL;
519     serNum[1] = 0x20;
520     status = MFRC522_ToCard(PCD_TRANSCEIVE, serNum, 2, serNum, &unLen);
521  
522     if (status == MI_OK)
523     {
524         //验证卡的连续数据
525         for (i=0; i<4; i++)
526         { 
527             serNumCheck ^= serNum[i];
528         }
529         if (serNumCheck != serNum[i])
530         { 
531             status = MI_ERR; 
532         }
533     }
534  
535     //SetBitMask(CollReg, 0x80);        //ValuesAfterColl=1
536  
537     return status;
538 } 
539  
540  
541 /*
542  * Function:CalulateCRC
543  * Description:使用mf522计算CRC
544  * Input parameter:pIndata--the CRC data need to be read,len--data length,pOutData-- the caculated result of CRC
545  * return:Null
546  */
547 void CalulateCRC(uchar *pIndata, uchar len, uchar *pOutData)
548 {
549     uchar i, n;
550  
551     ClearBitMask(DivIrqReg, 0x04);         //CRCIrq = 0
552     SetBitMask(FIFOLevelReg, 0x80);        //清除FIFO指针
553     //Write_MFRC522(CommandReg, PCD_IDLE);
554  
555     //Write data into FIFO 
556     for (i=0; i<len; i++)
557     { 
558         Write_MFRC522(FIFODataReg, *(pIndata+i)); 
559     }
560     Write_MFRC522(CommandReg, PCD_CALCCRC);
561  
562     //等待CRC计算完成
563     i = 0xFF;
564     do
565     {
566         n = Read_MFRC522(DivIrqReg);
567         i--;
568     }
569     while ((i!=0) && !(n&0x04)); //CRCIrq = 1
570  
571     //读出CRC校验结果
572     pOutData[0] = Read_MFRC522(CRCResultRegL);
573     pOutData[1] = Read_MFRC522(CRCResultRegM);
574 }
575  
576  
577  
578 /*
579  * Function:MFRC522_Write
580  * Description:写数据块
581  * Input parameters:blockAddr--block address;writeData--Write 16 bytes data into block
582  * return:return MI_OK if successed
583  */
584 uchar MFRC522_Write(uchar blockAddr, uchar *writeData)
585 {
586     uchar status;
587     uint recvBits;
588     uchar i;
589     uchar buff[18]; 
590      
591     buff[0] = PICC_WRITE;
592     buff[1] = blockAddr;
593     CalulateCRC(buff, 2, &buff[2]);
594     status = MFRC522_ToCard(PCD_TRANSCEIVE, buff, 4, buff, &recvBits);
595  
596     if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A))
597     { 
598         status = MI_ERR; 
599     }
600          
601     if (status == MI_OK)
602     {
603         for (i=0; i<16; i++) //16字节的数据写入到FIFO
604         { 
605             buff[i] = *(writeData+i); 
606         }
607         CalulateCRC(buff, 16, &buff[16]);
608         status = MFRC522_ToCard(PCD_TRANSCEIVE, buff, 18, buff, &recvBits);
609          
610         if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A))
611         { 
612             status = MI_ERR; 
613         }
614     }
615      
616     return status;
617 }
618  
619  
620 /*
621  * Function:MFRC522_Halt
622  * Description:命令卡进入睡眠模式
623  * Input parameters:null
624  * return:null
625  */
626 void MFRC522_Halt(void)
627 {
628     uchar status;
629     uint unLen;
630     uchar buff[4]; 
631  
632     buff[0] = PICC_HALT;
633     buff[1] = 0;
634     CalulateCRC(buff, 2, &buff[2]);
635   
636     status = MFRC522_ToCard(PCD_TRANSCEIVE, buff, 4, buff,&unLen);
637 }

 

 

原文地址:https://www.cnblogs.com/jikexianfeng/p/6386247.html