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