rfid与arduino

2017-02-10 14:31:00 weixin_34293911 阅读数 704

一、前几天在某宝上刚买了个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 }

 

 

 

2019-09-24 18:42:53 v86337286 阅读数 1370

RFID简介:射频识别即RFID(Radio Frequency IDentification)技术,又称无线射频识别,是一种通信技术,可通过无线电讯号识别特定目标并读写相关数据,而无需识别系统与特定目标之间建立机械或光学接触。常用的有低频(125k~134.2K)、高频(13.56Mhz)、超高频,微波等技术。RFID读写器也分移动式的和固定式的,目前RFID技术应用很广,如:图书馆,门禁系统,食品安全溯源等。

硬件准备

(基于Arduino的开发板、MFRC522读卡器模块)
Arduino Uno * 1
在这里插入图片描述
RFID-RC522 模块 * 1
在这里插入图片描述
IC卡 * 1-2
在这里插入图片描述
RFID技术现在都非常成熟和应用广泛,今天我们就来看看这个RFID如何实现读取里面的数据

接线

Arduino Uno <—> RFID-RC522
10 <—> SDA
13 <—> SCK
11 <—> MOSI
12 <—> MISO
null <—> IRQ
GND <—> GND
9 <—> RST
3.3V <—> 3.3V

需要用到RFID-RC522的库

法一、下载:https://github.com/miguelbalboa/rfid
下载解压到Arduino IDE的安装路径里的库文件夹libraries
https://download.csdn.net/download/v86337286/11813061

法二、点开管理库,在搜索栏里输入RC522,找到图中的库,
在这里插入图片描述
在这里插入图片描述
点击安装(我这图是已经安装过)
在这里插入图片描述

示例代码 .

Arduino + RFID 读取 IC 卡信息

读取 IC 卡信息后并通过串口将卡号及0扇区卡号数据打印出来,其他15个扇区不显示扇区内容
代码如下

/*
 * --------------------------------------------------------------------------------------------------------------------
 * Example sketch/program showing how to read data from a PICC to serial.
 * --------------------------------------------------------------------------------------------------------------------
 * This is a MFRC522 library example; for further details and other examples see: https://github.com/miguelbalboa/rfid
 * 
 * Example sketch/program showing how to read data from a PICC (that is: a RFID Tag or Card) using a MFRC522 based RFID
 * Reader on the Arduino SPI interface.
 * 
 * When the Arduino and the MFRC522 module are connected (see the pin layout below), load this sketch into Arduino IDE
 * then verify/compile and upload it. To see the output: use Tools, Serial Monitor of the IDE (hit Ctrl+Shft+M). When
 * you present a PICC (that is: a RFID Tag or Card) at reading distance of the MFRC522 Reader/PCD, the serial output
 * will show the ID/UID, type and any data blocks it can read. Note: you may see "Timeout in communication" messages
 * when removing the PICC from reading distance too early.
 * 
 * If your reader supports it, this sketch/program will read all the PICCs presented (that is: multiple tag reading).
 * So if you stack two or more PICCs on top of each other and present them to the reader, it will first output all
 * details of the first and then the next PICC. Note that this may take some time as all data blocks are dumped, so
 * keep the PICCs at reading distance until complete.
 * 
 * @license Released into the public domain.
 * 
 * Typical pin layout used:
 * -----------------------------------------------------------------------------------------
 *             MFRC522      Arduino       Arduino   Arduino    Arduino          Arduino
 *             Reader/PCD   Uno/101       Mega      Nano v3    Leonardo/Micro   Pro Micro
 * Signal      Pin          Pin           Pin       Pin        Pin              Pin
 * -----------------------------------------------------------------------------------------
 * RST/Reset   RST          9             5         D9         RESET/ICSP-5     RST
 * SPI SS      SDA(SS)      10            53        D10        10               10
 * SPI MOSI    MOSI         11 / ICSP-4   51        D11        ICSP-4           16
 * SPI MISO    MISO         12 / ICSP-1   50        D12        ICSP-1           14
 * SPI SCK     SCK          13 / ICSP-3   52        D13        ICSP-3           15
 */
 
#include <SPI.h>
#include <MFRC522.h>
 
#define RST_PIN         9          // Configurable, see typical pin layout above
#define SS_PIN          10         // Configurable, see typical pin layout above
 
MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance
 
void setup() {
    Serial.begin(9600);     // Initialize serial communications with the PC
    while (!Serial);        // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
    SPI.begin();            // Init SPI bus
    mfrc522.PCD_Init();     // Init MFRC522
    mfrc522.PCD_DumpVersionToSerial();  // Show details of PCD - MFRC522 Card Reader details
    Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));
}
 
void loop() {
    // Look for new cards
    if ( ! mfrc522.PICC_IsNewCardPresent()) {
        return;
    }
 
    // Select one of the cards
    if ( ! mfrc522.PICC_ReadCardSerial()) {
        return;
    }
 
    // Dump debug info about the card; PICC_HaltA() is automatically called
    mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
}

运行此代码并将其中一张卡放入RFID卡时,很多信息显示在Arduino IDE的串行监视器上
在这里插入图片描述

看完了上面那如何在Arduino中获得RFID的UID?

Arduino uno中只获得RFID的UID 并通过串口转发

法一

创建了另一个函数: PICC_DumpDetailsToSerialUid(Uid *uid)


函数如下

//This is just for read UID!
void MFRC522::PICC_DumpDetailsToSerialUid(Uid *uid){
Serial.print(F(“Card JUST UID :”));
for (byte i = 0; i < uid->size; i++) {
if(uid->uidByte[i] < 0x10)
Serial.print(F(" 0"));
else
Serial.print(F(" "));
Serial.print(uid->uidByte[i], HEX);
}
Serial.println();
}

可以把它放在你需要的任何地方
示例:
在这里插入图片描述
添加该功能后,您需要进入第410行的 MFRC522.h 库并添加

void PICC_DumpDetailsToSerialUid(Uid *uid);

在该库中进行了这两次编辑后,您可以在任意位置调用该函数 .
示例:
在这里插入图片描述
用Arduino调用它: mfrc522.PICC_DumpDetailsToSerialUid(&(mfrc522.uid)); 只仅且只有一个函数用于uid读取
效果
在这里插入图片描述

法二

返回UID的函数 .

/**
 * mfrc522.PICC_IsNewCardPresent() should be checked before 
 * @return the card UID
 */
unsigned long getID(){
  if ( ! mfrc522.PICC_ReadCardSerial()) { //Since a PICC placed get Serial and continue
    return -1;
  }
  unsigned long hex_num;
  hex_num =  mfrc522.uid.uidByte[0] << 24;
  hex_num += mfrc522.uid.uidByte[1] << 16;
  hex_num += mfrc522.uid.uidByte[2] <<  8;
  hex_num += mfrc522.uid.uidByte[3];
  mfrc522.PICC_HaltA(); // Stop reading
  return hex_num;
}

例如这样使用:

if(mfrc522.PICC_IsNewCardPresent()) {
  unsigned long uid = getID();
  if(uid != -1){
    Serial.print("Card detected, UID: "); Serial.println(uid);
  }
}

在这里插入图片描述

2018-12-26 14:47:53 acktomas 阅读数 2301

参考资料

  1. RFID-RC522 模块
    https://blog.csdn.net/acktomas/article/details/88706364
  2. Arduino教程-17 RFID无线识别设备
    https://blog.csdn.net/acktomas/article/details/85262017

17.1 认识条码与RFID

17.1.1 条码

条码是根据特定规则排列而成的黑白粗细并行线条,方便机器识别物品,条码读取器会发射红外线或镭射光,由于黑色和白色的光线反射程度不同,读取器里的红外线传感器将依据反射光的强弱,判读0与1信号,进而得知条码所记录的厂商、商品名称和价格等信息。

17.1.2 条码的标准

不同信息产品都要支持ASCII字符编码,以便于互通信息;条码有简称EAN的国际标准(原意:European Article Number,欧洲商品编码,后改名为International Article Number,国际商品编码)

17.1.3 RFID系统简介

RFID是无线射频识别(radio frequency identification)。RFID是记载唯一编号或其他数据的芯片,并使用无线电传输数据的技术统称。
一套RFID系统由底下三大部分组成。

  • 读卡器(reader):发射无线电波,读取电子标签内的信息。
  • 电子标签(tag):也称为转发器(transponder),内建无线电波发射电路及控制IC,当电子标签感应到读卡器发射的电波时,标签内部电路会把电波能量转换成电源,并发射无线电波返回一系列数据。
  • 主控端(host):连接读卡器的Arduino,负责解析返回的数据。

17.1.4 认识NFC

NFC(Near Field Communication,进场通信或称为近距离无线通信),是RFID的一种延伸应用。

NFC和RFID的主要差异
  • RFID的通讯距离比较远,NFC的通信距离在10CM以内。
  • 因为通信距离短,NFC标签通常采用被动式、无源标签。
  • NFC的数据经过加密,适合有安全性及保密需求的场合,如:金融卡

17.2 RFID模块规格介绍与标签读取实验

选购RFID模块时,需要留意底下几项规格。

  • 输入电压:有些采用5V,有些则是3.3
  • 标签频率:通常是125kHZ或13.56MHZ。采用任何频率都行,但采购标签时,记得要买相同频率的款式。
  • 接口:读卡器模块和微电脑相连的接口,有串口(TTL电位格式,也称作UART界面)、I2C、SPI、USB和蓝牙无线等类型

动手做17-1 读取RFID标签

实验说明:

连接RFID模块与Arduino,读取两个不同的RFID标签,在“串口监视器”显示标签数据(内码)。

实验材料:

名称 数量
RFID读卡器(频率规格需要和RFID标签搭配) 1
RFID标签 1

实验程序:为了避免影响Arduino默认串口的运行,本单元代码同样采用“软件串口”扩展库来接收读卡器的数据

#include <SoftwareSerial.h>
SoftwareSerial RFID(3, 4);

byte data;

void setup() {
    Serial.begin(9600);
    RFID.begin(9600);
    Serial.println("RFID Ready!");
}

void loop(){
    if (RFID.available() > 0) {
        data = RFID.read();
        Serial.println(data);
    }
}

17.3 存储与对比RFID编码

典型的RFID应用,例如门禁卡,都是事先在微电脑中存储特定RFID卡片的编码值。当持卡人扫码门禁卡时,系统将读取并且对比存储值,如果相符,就开门让持卡人通过。
当前所用RFID标签每次都会返回14个数字,为了对比数据,每次扫描到的卡片编码,都要先暂存在内存中。我们可以用一个执行14次读取的循环,把读入的数字分别存入数组。

byte temp[14];
byte i =0;
……
while (RFID.availabel() && i < 14){
    //如果有数据,而且元素索引值小于14
    temp[i] = Serial.read();  //读取数据并存入数组
    i++;
}
i = 0;
……

另一种写法:由于传入串口的数据会暂存在微处理器内部的缓存区(buffer),因此程序可以等到所有数字都传入微处理器之后,再一起读取。
在这里插入图片描述
假如RFID读卡器模块采用9600bps联机,因此每一秒钟大约可传递1200字字符(9600÷8=1200),所以当程序收到第一个字符后,等待0.1秒,让读卡器传入14个数字,已经绰绰有余。

// 动手做18-1:储存与比对 RFID 编码
// 详细说明,请参阅第十八章,18-11页。

#include <SoftwareSerial.h>

SoftwareSerial RFID(3, 4); // 接收脚=3, 传送脚=4

const byte TAG_LEN = 14;   // 定义标签数据的长度
byte temp[TAG_LEN];        // 存放读入标签的 14 个数字
String rfidStr = "";

// 负责读入 RFID 编码值的自定义函数,传回值型别为「布林」
boolean readTag() {
  // 代表是否读入数据的变量,预设值为 0,代表没有
  boolean ok = 0;
  if (RFID.available()) { // 如果读卡机传入新的数据...
    delay(100);           // 等 0.1 秒,让其余数字都传进来

    // 执行 14 次循环,读取缓冲区里的数字
    for (byte i = 0; i < TAG_LEN; i++) {
      temp[i] = RFID.read();
    }
    RFID.flush();   // 清除缓冲区
    ok = 1;       // 读取完毕后,设定成 1,代表有读到新数据
  }
  return ok;       // 传回 0 或 1
}

void setup() {
  Serial.begin(9600);
  RFID.begin(9600);
  Serial.println("RFID Ready!");
}

void loop() {
  // 呼叫自定义函数,如果读取到标签,此判断条件式将「成立」
  if (readTag()) {
    rfidStr = "";
    // 把读入的 14 个数字连结成字符串
    for (byte i = 0; i < TAG_LEN; i++) {
      rfidStr += temp[i];
    }
    Serial.println(rfidStr);  // 显示标签的编码字符串
  }
}

动手做17-2 使用RFID控制开关

实验说明: 采用两个RFID标签,一个当做“开”,另一个当做“关”,来控制第13脚的led。
程序

// 动手做18-2:使用 RFID 控制开关
// 详细说明,请参阅第十八章,18-14页。

#include <SoftwareSerial.h>

SoftwareSerial RFID(3, 4); // 接收脚=3, 传送脚=4

const byte TAG_LEN = 14;   // 定义标签数据的长度
byte temp[TAG_LEN];        // 存放读入标签的 14 个数字
String rfidStr = "";

const byte ledPin = 13;   // LED 位于 13 脚
// 请将底下的数字改成你的 RFID 标签数字
// 代表「开启」的 RFID 编码值
String tagON = "24850484853505649577052713" ;
// 代表「关闭」的 RFID 编码值
String tagOFF = "24854484855535452575356503" ;

// 负责读入 RFID 编码值的自定义函数,传回值型别为「布林」
boolean readTag() {
  // 代表是否读入数据的变量,预设值为 0,代表没有
  boolean ok = 0;
  if (RFID.available()) { // 如果读卡机传入新的数据...
    delay(100);           // 等 0.1 秒,让其余数字都传进来

    // 执行 14 次循环,读取缓冲区里的数字
    for (byte i = 0; i < TAG_LEN; i++) {
      temp[i] = RFID.read();
    }
    RFID.flush();   // 清除缓冲区
    ok = 1;       // 读取完毕后,设定成 1,代表有读到新数据
  }
  return ok;       // 传回 0 或 1
}

void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
  RFID.begin(9600);
  Serial.println("RFID Ready!");
}

void loop() {
  if (readTag()) {
    rfidStr = "";
    for (byte i = 0; i < TAG_LEN; i++) {
      rfidStr += temp[i];
    }
    Serial.println(rfidStr);

    if (rfidStr == tagON) { // 如果 RFID 码等于「开启」的编码值
      digitalWrite(ledPin, HIGH); // 点亮 LED
    } else if (rfidStr == tagOFF) {
      // 否则,若 RFID 码等于「关闭」编码
      digitalWrite(ledPin, LOW);  // 关闭 LED
    }
  }
}

将RFID标签数据存入“程序内存”区

上面的程序代码将RFID标签数据存储成字符串(String)类型,这样的程序写法比较简单,但由于这些数据将会占用有限的数据存储器空间,如果RFID标签有很多组,建议将它们存放在程序内存区。

// 动手做18-2:使用 RFID 控制开关,标签值储存在程序内存区。
// 详细的程式说明,请参阅第十八章,18-15页。

#include <avr/pgmspace.h>
#include <SoftwareSerial.h>

SoftwareSerial RFID(3, 4); // 接收脚=3, 传送脚=4

const byte TAG_LEN = 14;   // 定义标签数据的长度
const byte TAG_TOTAL = 2;   // 定义标签数据的组数
byte temp[TAG_LEN];        // 存放读入标签的 14 个数字
String rfidStr = "";
int tag = -1;  //用来存放RFID标签编号,-1代表找不到相同的标签码。
//PROGMEM 把数组存入程序内存区
/**
* tags数组存储了两组标签,假设要比对这两组的标签值是否相同,
* 可以使用比较两个内存区块(数组)值的memcmp()函数,
* 此指令用于比较位于主存储器(SRAM,或者说“数据存储器”)的数据,
* 若要比较位于程序内存区域(program memory)的数据,
* 请使用这个指令memcmp_P(数组1, 数组2, n)
**/
PROGMEM byte tags[TAG_TOTAL][TAG_LEN] = {
  // 第 0 组标签
  {2, 48, 50, 48, 48, 53, 50, 56, 49, 57, 70, 52, 71, 3},
  // 第 1 组标签
  {2, 48, 54, 48, 48, 55, 53, 54, 52, 57, 53, 56, 50, 3}
};

const byte ledPin = 13;   // LED 位于 13 脚

// 负责读入 RFID 编码值的自定义函数,传回值型别为「布林」
boolean readTag() {
  // 代表是否读入数据的变量,预设值为 0,代表没有
  boolean ok = 0;
  if (RFID.available()) { // 如果读卡机传入新的数据...
    delay(100);           // 等 0.1 秒,让其余数字都传进来

    // 执行 14 次循环,读取缓冲区里的数字
    for (byte i = 0; i < TAG_LEN; i++) {
      temp[i] = RFID.read();
    }
    RFID.flush();   // 清除缓冲区
    ok = 1;       // 读取完毕后,设定成 1,代表有读到新数据
  }
  return ok;       // 传回 0 或 1
}

void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
  RFID.begin(9600);
  Serial.println("RFID Ready!");
}

void loop() {
  if (readTag()) {
    for (byte i = 0; i < TAG_TOTAL; i++) {
      if (memcmp_P(temp, tags[i], TAG_LEN) == 0 ) {
        Serial.println(i);
        tag = i;   // 记录标签编号
        break;     // 若找到相符的标签,就跳出循环,不用再找了。
      } else {
        tag = -1;  // tag值为-1,代表没有找到相同的标签编码。
      }
    }

    switch (tag) {
      case 0:      // 如果是编号0的标签,就点亮LED。
        digitalWrite(ledPin, HIGH);
        break;
      case 1:      // 若是编号1的标签,关闭LED。
        digitalWrite(ledPin, LOW);
        break;
    }
  }
}
2016-11-12 17:29:00 weixin_34416754 阅读数 811

http://www.it165.net/embed/html/201512/3287.html

2015年12月04日(周五) 上午  博士的智能卡实验——RFID识别实验,基于51单片机;

我们的实验用的读写器是 RFID-RC522 模块,刚好和我买的 Arduino RFID 套件里的是同一款;

实验时候并没有完成,因为在烧写程序的时候一直烧不进去,好吧,下午在办公室的时候我们博士说有一块单片机是有问题的,破碎的心 TMD有那么巧吗 咬牙切齿咬牙切齿

中午开始我就开始阅读 Arduino 套件配套的 RFID 实验资料,打算把这个实验做完,只是我把上位机换成 Arduino 而已。

实验目的


1.了解 RFID 的基本概念和射频卡的工作原理;

2.熟悉 Arduino 和 RC522RFID 模块的使用;

3.测试 RC522 模块对卡的识别。

实验材料


1.计算机一台;

2.Arduino 一块;

3.USB-串口线一根;

4.RFID-RC522 模块一个;

5.标准S50空白卡一张;

6.S50异形卡一个(钥匙扣形状);

7.直排、弯排插针各一条;

8.杜邦线一排。

买来的射频 IC卡感应模块就像下面这样,包邮也就14块左右:

MFRC-522 RC522 RFID射频 IC卡感应模块

买来的时候排插并没有焊上,所以必须自己焊,虽然我没有焊接的工具,不过借着这次实验我还是焊上了。下面是我第二次焊接的成果:

image

Miafre 1 s50 感应式IC卡
◇ 芯    片:  Philips Mifare 1 S50
◇ 存储容量:  8Kbit ,16个分区,每分区两组密码
◇ 工作频率:  13.56MHZ
◇ 通讯速度:  106Kboud
◇ 读写距离:  2.5—10CM
◇ 读写时间:  1-2MS
◇ 工作温度:  -20℃-85℃
◇ 擦写次数:  >100000次
◇ 数据保存:  >10年
◇ 规  格:  0.87×85.5×54/ 非标卡
◇ 封装材料:  PVC、PET、0.13铜钱
◇ 封装工艺:  超声波自动植线/自动碰焊
◇ 制作标准:  ISO 14443, ISO 10536
◇ 应用范围:  企业/校园一卡通、公交储值卡、高速公路收费、停车场、小区管理等

实验原理


(一)RFID系统组成

RFID 技术利用无线射频方式在阅读器和射频卡之间进行非接触双向数据传输,以达到目标识别和数据交换的目的。最基本的 RFID 系统由三部分组成:

1. 标签(Tag,即射频卡):由耦合元件及芯片组成,标签含有内置天线,用于和射频天线间进行通信。

2. 阅读器:读取(在读写卡中还可以写入)标签信息的设备。

3. 天线:在标签和读取器间传递射频信号。

(二)工作原理

MCU通过对读卡器芯片内寄存器的读写来控制读卡器芯片,读卡器芯片收到MCU发来的命令后,按照非接触式射频卡协议格式,通过天线及其匹配电路向附近发出一组固定频率的调制信号(13.56 MHz)进行寻卡,若此范围内有卡片存在,卡片内部的LC谐振电路(谐振频率与读卡器发送的电磁波频率相同)在电磁波的激励下,产生共振,在卡片内部电压泵的作用下不断为其另一端的电容充电,获得能量,当该电容电压达到2 V时,即可作为电源为卡片的其他电路提供工作电压。 当有卡片处在读卡器的有效工作范围内时,MCU向卡片发出寻卡命令,卡片将回复卡片类型,建立卡片与读卡器的第一步联系,若同时有多张卡片在天线的工作范围内,读卡器通过启动防冲撞机制,根据卡片序列号来选定一张卡片,被选中的卡片再与读卡器进行密码校验,确保读卡器对卡片有操作权限以及卡片的合法性,而未被选中的则仍然处在闲置状态,等待下一次寻卡命令。密码验证通过之后,就可以对卡片进行读写等应用操作。

(三)RC522模块

模块的射频读写芯片应该是飞利浦的 MF RC522,在上一篇文章我应该已经附上了英文和中文的手册。

MF RC522提供了3种接口模式:高达10 Mb/s的SPI、I2C总线模式(快速模式下能达400 kb/s,而高速模式下能达3.4 Mb/s)、最高达1228.8 kb/s的UART模式。买来的模块采用了第一种模式——四线制SPI,通信中的时钟信号由 Arduino 产生,MF RC522芯片设置为从机模式,接收来自 Arduino 的数据以设置寄存器,并负责射频接口通信中相关数据的收发。

数据的传输路径为:Arduino 通过 MOSI 线将数据发到 MF RC522,MF RC522 通过 MISO 线发回至 Arduino。

实验设计


RC522模块各引脚功能

  SDA -- 串行数据线(IIC接口时的I/O线);在SPI接口中为NSS(从机标志管脚);

  SCK -- 连接MCU的SCK信号;

MOSI -- MCU输出,RC522接收(即主设备输出,从设备输入);

MISO -- RC522输出,MCU接收(即从设备输出,主设备输入);

  IRQ -- 中断请求输出;

 GND -- 接地;

  RST -- 复位;

 3.3V -- VSS,工作电压,若使用的事5V的MCU,注意分压。

管脚对应关系:

RFID模块 Arduino UNO
VCC 3.3V
RST 5V
GND GND
MISO 12
MOSI 11
SCK 13
NSS 10
IRQ (不接)

 

电路图

d

实物连接图

WP_20151206_002WP_20151206_003

代码的设计,我会放到下一篇文章中讲。

实验内容


1、实现利用IC卡控制LED灯闪烁。

2、实现利用七段数码管显示IC卡的类型,并记录。

3、实现在七段数码管上以十六进制显示IC卡的序列号,并记录。

4、从串口打印IC卡的类型和序列号。

5、测试最大的识别距离。

思考题


1、完成对IC卡的数据读写,需要哪几个步骤?

答:四个步骤:寻卡 —> 防冲突 —> 选卡 —>  三次互相确认 —>  读写

2、请分别写出实验材料中标准S50卡、S50钥匙卡的类型和序列号。

答:S50标准卡:Type 0400 和 SN FDC2E3D5

      S50异形卡:Type 0400 和 SN D8163100

3、当多张卡在一起时,能否正确识别其卡号?并请说明其原因。

答:在这个实验中不行。在这个实验系统中,阅读器会先执行寻卡操作并返回卡的类型,之后才执行防冲突操作。因为有多张卡处在阅读器的可读范围,防冲突函数返回值为 MI_ERR,也就不能继续执行选卡和读写的操作,也就获取不到卡的序列号。

实验中的观察:

当我将两张卡同时慢慢靠近阅读器的过程中,阅读器首先识别出了卡的类型和其中的某一种卡,并在串口上打印了卡的类型和序列号。接着串口只会一直打印卡的类型而不会打印的卡的序列号。有时也会只打印卡类型而没有序列号。

分析:

在慢慢靠近的过程中,阅读器得到的是不确定的信号,偶尔碰巧识别出了其中一张卡。但是之后,两张卡相互干扰,以至都不能工作。

那么在多张卡的情况下,RFID阅读器能否同时处理多个标签呢?

答案是肯定的,TI 的 13.56MHz 系统每秒钟能处理大约50张标签。回顾一下上一篇文章讲到的MF卡的逻辑结构,其中有一个模块叫防冲突模块:

如果有多张Mifare 1卡片处在读写器的天线的工作范围之内时,防冲突模块的防冲突功能将被启动工作:根据卡片的序列号来选定一张卡片。被选中的卡片将直接与读写器进行数据交换,未被选择的卡片处于等待状态,准备与读写器进行通信。

既然有防冲突模块,那么为什么我们用的同样是 MF1 S50 的卡,还是无法识别呢?

原因就在 RFID 阅读器的防冲撞机制上。如果我们的读卡设备使用了防冲撞机制,那么在冲撞产生后,RFID系统会根据冲撞算法,将不同的卡片分时响应,并且已经响应的卡片将暂时被休眠(SLEEP),未被选择的卡片处于等待状态。这点在上一篇文章中我仅仅是提到算法的名字。

防冲撞机制使得同时处于读写区内的多张卡的正确操作成为可能,只用算法编程,读头即可自动选取其中一张卡进行读写操作。这样既方便了操作,也提高了操作的速度。

如果在同一时间段内有多于一个的 VICC 或 PICC 同时响应,则说明发生冲撞。RFID的核心是防冲撞技术,这也是和接触式 IC 卡的主要区别。ISO 14443-3 规定了 TYPE A 和 TYPE B 的防冲撞机制。二者防冲撞机制的原理不同:前者是基于位冲撞检测协议,而 TYPE B 通过系列命令序列完成防冲撞;ISO 15693 采用轮寻机制、分时查询的方式完成防冲撞机制,在标准的第三部分有详细规定。

4、请测试 RC522 模块是否能够识别羊城通、校园一卡通等非接触式IC卡?若能识别,请写出其类型及序列号?

答:RC522 模块还能识别羊城通、校园一卡通和银行卡,发现类型都是 0400,属于 MFOne-S50 卡。第二代身份证并不能识别出来,但是我见过识别的机器。估计是因为工作频率不同,待考。

某校园一卡通
Card type: MFOne-S50
The card's number is: F68F8EAB

某羊城通
Card type: MFOne-S50
The card's number is: 95AF4B27

某银行卡
Card type: MFOne-S50
The card's number is: EF660184

实验结果


led 闪烁

下次附图。。。

数码管显示

下次附图。。。

串口打印

g

识别距离

我粗略测量,发现白卡的识别需要在 4 cm 内,在 7 cm 的位置还是读不到卡片的。至于加大工作电流,还是不能增加通信距离。用我的校园卡和白卡一起测试,几乎都是只能识别校园卡。所以我以为校园卡的线圈比较好,但是单独识别,距离依然是 4 cm。钥匙扣的识别距离为2.5 cm 左右。

WP_20151207_009

注意 识别的时候要先释放手上的静电,阅读器的周围不要有其他电流干扰。

2017-04-30 21:58:20 ling3ye 阅读数 29503

欢迎关注「凌顺实验室」微信公众号

 

 

 

 

 

 

RFID技术现在都非常成熟和应用广泛

 

今天我们就来看看这个RFID如何实现读取里面的数据

 

看看RFID模块是什么模样的

 

实验效果

在串口监控器里面,我们把IC卡放在模块上,能读出储存在里面的数据,

程序就是这样来核对与我们数据库是否匹配,如果对得上,就开门,对不上肯定打死都不开

 

BOM表

Arduino Uno * 1

RFID-RC522 模块  * 1

IC卡 * 1-2

跳线若干

 

接线

Arduino Uno     <------>   RFID-RC522

           10            <------>                SDA

           13            <------>                SCK

           11           <------>                MOSI

           12            <------>                MISO

           --null--     <------>                IRQ

           GND       <------>                GND

           9              <------>                RST

           3.3V        <------>                3.3V

 

程序

我们需要用到RFID-RC522的库

下载:https://github.com/miguelbalboa/rfid

具体如何操作,再次说一下,下载解压到Arduino IDE的安装路径里的库文件夹libraries    

 

当然我们还有第二种更新库的方法,不过这得用最新版的Arduino IDE ,

在菜单栏找到如下:

 

点开管理库,在搜索栏里输入RC522,找到图中的库,点击安装(我这图是已经安装过啦)

 

安装好库我们就可以直接使用例子里的程序

 

这里贴出程序:

 

/*
 * --------------------------------------------------------------------------------------------------------------------
 * Example sketch/program showing how to read data from a PICC to serial.
 * --------------------------------------------------------------------------------------------------------------------
 * This is a MFRC522 library example; for further details and other examples see: https://github.com/miguelbalboa/rfid
 * 
 * Example sketch/program showing how to read data from a PICC (that is: a RFID Tag or Card) using a MFRC522 based RFID
 * Reader on the Arduino SPI interface.
 * 
 * When the Arduino and the MFRC522 module are connected (see the pin layout below), load this sketch into Arduino IDE
 * then verify/compile and upload it. To see the output: use Tools, Serial Monitor of the IDE (hit Ctrl+Shft+M). When
 * you present a PICC (that is: a RFID Tag or Card) at reading distance of the MFRC522 Reader/PCD, the serial output
 * will show the ID/UID, type and any data blocks it can read. Note: you may see "Timeout in communication" messages
 * when removing the PICC from reading distance too early.
 * 
 * If your reader supports it, this sketch/program will read all the PICCs presented (that is: multiple tag reading).
 * So if you stack two or more PICCs on top of each other and present them to the reader, it will first output all
 * details of the first and then the next PICC. Note that this may take some time as all data blocks are dumped, so
 * keep the PICCs at reading distance until complete.
 * 
 * @license Released into the public domain.
 * 
 * Typical pin layout used:
 * -----------------------------------------------------------------------------------------
 *             MFRC522      Arduino       Arduino   Arduino    Arduino          Arduino
 *             Reader/PCD   Uno/101       Mega      Nano v3    Leonardo/Micro   Pro Micro
 * Signal      Pin          Pin           Pin       Pin        Pin              Pin
 * -----------------------------------------------------------------------------------------
 * RST/Reset   RST          9             5         D9         RESET/ICSP-5     RST
 * SPI SS      SDA(SS)      10            53        D10        10               10
 * SPI MOSI    MOSI         11 / ICSP-4   51        D11        ICSP-4           16
 * SPI MISO    MISO         12 / ICSP-1   50        D12        ICSP-1           14
 * SPI SCK     SCK          13 / ICSP-3   52        D13        ICSP-3           15
 */

#include <SPI.h>
#include <MFRC522.h>

#define RST_PIN         9          // Configurable, see typical pin layout above
#define SS_PIN          10         // Configurable, see typical pin layout above

MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance

void setup() {
	Serial.begin(9600);		// Initialize serial communications with the PC
	while (!Serial);		// Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
	SPI.begin();			// Init SPI bus
	mfrc522.PCD_Init();		// Init MFRC522
	mfrc522.PCD_DumpVersionToSerial();	// Show details of PCD - MFRC522 Card Reader details
	Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));
}

void loop() {
	// Look for new cards
	if ( ! mfrc522.PICC_IsNewCardPresent()) {
		return;
	}

	// Select one of the cards
	if ( ! mfrc522.PICC_ReadCardSerial()) {
		return;
	}

	// Dump debug info about the card; PICC_HaltA() is automatically called
	mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
}

 

 

 

 

 

 

 

arduino于RFID

阅读数 161