一、前幾天在某寶上剛買了個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 }