├── documentation └── MFRC522.pdf ├── examples ├── check_firmware │ └── check_firmware.ino └── auth_read_write │ └── auth_read_write.ino ├── README.md ├── keywords.txt ├── MFRC522.h └── MFRC522.cpp /documentation/MFRC522.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ljos/MFRC522/HEAD/documentation/MFRC522.pdf -------------------------------------------------------------------------------- /examples/check_firmware/check_firmware.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define SAD 10 5 | #define RST 5 6 | 7 | MFRC522 nfc(SAD, RST); 8 | 9 | void setup() { 10 | SPI.begin(); 11 | Serial.begin(115200); 12 | 13 | Serial.println("Looking for MFRC522."); 14 | nfc.begin(); 15 | 16 | uint8_t version = nfc.getFirmwareVersion(); 17 | if (! version) { 18 | Serial.print("Didn't find MFRC522 board."); 19 | while(1); //halt 20 | } 21 | 22 | Serial.print("Found chip MFRC522 "); 23 | Serial.print("Firmware ver. 0x"); 24 | Serial.print(version, HEX); 25 | Serial.println("."); 26 | 27 | if (nfc.digitalSelfTestPass()) { 28 | Serial.print("Digital self test by MFRC522 passed."); 29 | } else { 30 | Serial.print("Digital self test by MFRC522 failed."); 31 | } 32 | } 33 | 34 | void loop() { 35 | 36 | } 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Arduino RFID Library for MFRC522 (13.56 Mhz) 2 | -------------------------------------------- 3 | 4 | Pin order, starting from the bottom left hand pin (in case your 5 | MFRC522 doesn't have pin markings like the B2CQSHOP one): 6 | 7 | | Pins | SPI | UNO | Mega2560 | Leonardo/Due | 8 | | ---- |:--------:|:----:|:--------:|:------------:| 9 | | 1 | SDA (SS) | 10 | 53 | 10 | 10 | | 2 | SCK | 13 | 52 | SCK`1` | 11 | | 3 | MOSI | 11 | 51 | MOSI`1` | 12 | | 4 | MISO | 12 | 50 | MISO`1` | 13 | | 5 | IRQ | `*` | `*` | `*` | 14 | | 6 | GND | GND | GND | GND | 15 | | 7 | RST | 5 | ? | Reset | 16 | | 8 | +3.3V | 3V3 | 3V3 | 3.3V | 17 | `*` Not needed 18 | `1` on ICPS header 19 | 20 | Using MFRC522 with other SPI components 21 | --------------------------------------- 22 | 23 | If you are planning to use other SPI components you just have to make 24 | sure each have an exclusive SS (Slave Select) line. MISO, MOSI and 25 | SCK lines may be shared. More reference regarding SPI may be found 26 | [here](http://arduino.cc/en/Reference/SPI). 27 | -------------------------------------------------------------------------------- /examples/auth_read_write/auth_read_write.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define SAD 10 5 | #define RST 5 6 | 7 | MFRC522 nfc(SAD, RST); 8 | 9 | void setup() { 10 | SPI.begin(); 11 | // Read a fast as possible. There is a limit for how long we are 12 | // allowed to read from the tags. 13 | Serial.begin(115200); 14 | 15 | Serial.println("Looking for MFRC522."); 16 | nfc.begin(); 17 | 18 | // Get the firmware version of the RFID chip 19 | byte version = nfc.getFirmwareVersion(); 20 | if (! version) { 21 | Serial.print("Didn't find MFRC522 board."); 22 | while(1); //halt 23 | } 24 | 25 | Serial.print("Found chip MFRC522 "); 26 | Serial.print("Firmware ver. 0x"); 27 | Serial.print(version, HEX); 28 | Serial.println("."); 29 | } 30 | 31 | byte keyA[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; 32 | byte keyB[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; 33 | 34 | void loop() { 35 | byte status; 36 | byte data[MAX_LEN]; 37 | byte serial[5]; 38 | int i, j, pos; 39 | 40 | // Send a general request out into the aether. If there is a tag in 41 | // the area it will respond and the status will be MI_OK. 42 | status = nfc.requestTag(MF1_REQIDL, data); 43 | 44 | if (status == MI_OK) { 45 | Serial.println("Tag detected."); 46 | Serial.print("Type: "); 47 | Serial.print(data[0], HEX); 48 | Serial.print(", "); 49 | Serial.println(data[1], HEX); 50 | 51 | // calculate the anti-collision value for the currently detected 52 | // tag and write the serial into the data array. 53 | status = nfc.antiCollision(data); 54 | memcpy(serial, data, 5); 55 | 56 | Serial.println("The serial nb of the tag is:"); 57 | for (i = 0; i < 3; i++) { 58 | Serial.print(serial[i], HEX); 59 | Serial.print(", "); 60 | } 61 | Serial.println(serial[3], HEX); 62 | 63 | // Select the tag that we want to talk to. If we don't do this the 64 | // chip does not know which tag it should talk if there should be 65 | // any other tags in the area.. 66 | nfc.selectTag(serial); 67 | 68 | // Assuming that there are only 64 blocks of memory in this chip. 69 | for (i = 0; i < 64; i++) { 70 | // Try to authenticate each block first with the A key. 71 | status = nfc.authenticate(MF1_AUTHENT1A, i, keyA, serial); 72 | if (status == MI_OK) { 73 | Serial.print("Authenticated block nb. 0x"); 74 | Serial.print(i, HEX); 75 | Serial.println(" with key A."); 76 | // Reading block i from the tag into data. 77 | status = nfc.readFromTag(i, data); 78 | if (status == MI_OK) { 79 | // If there was no error when reading; print all the hex 80 | // values in the data. 81 | for (j = 0; j < 15; j++) { 82 | Serial.print(data[j], HEX); 83 | Serial.print(", "); 84 | } 85 | Serial.println(data[15], HEX); 86 | } else { 87 | Serial.println("Read failed."); 88 | } 89 | } else { 90 | // If we could not authenticate with the A key, we will try 91 | // the B key. 92 | status = nfc.authenticate(MF1_AUTHENT1B, i, keyB, serial); 93 | if (status == MI_OK) { 94 | Serial.print("Authenticated block nb. 0x"); 95 | Serial.print(i, HEX); 96 | Serial.println(" with key B."); 97 | status = nfc.readFromTag(i, data); 98 | if (status == MI_OK) { 99 | for (j = 0; j < 15; j++) { 100 | Serial.print(data[j], HEX); 101 | Serial.print(", "); 102 | } 103 | Serial.println(data[15], HEX); 104 | } else { 105 | Serial.println("Read failed."); 106 | } 107 | } else { 108 | Serial.print("Access denied at block nb. 0x"); 109 | Serial.println(i, HEX); 110 | } 111 | } 112 | } 113 | 114 | // Stop the tag and get ready for reading a new tag. 115 | nfc.haltTag(); 116 | } 117 | delay(2000); 118 | } 119 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map MFRC522 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | MFRC522 KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | anticollision KEYWORD2 15 | authenticate KEYWORD2 16 | begin KEYWORD2 17 | calculateCRC KEYWORD2 18 | clearBitMask KEYWORD2 19 | commandTag KEYWORD2 20 | digitalSelfTestPass KEYWORD2 21 | getFirmwareVersion KEYWORD2 22 | haltTag KEYWORD2 23 | readFromRegister KEYWORD2 24 | readFromTag KEYWORD2 25 | requestTag KEYWORD2 26 | reset KEYWORD2 27 | selectTag KEYWORD2 28 | setBitMask KEYWORD2 29 | writeToRegister KEYWORD2 30 | writeToTag KEYWORD2 31 | 32 | ####################################### 33 | # Constants (LITERAL1) 34 | ####################################### 35 | MAX_LEN LITERAL1 36 | MI_ERR LITERAL1 37 | MI_NOTAGERR LITERAL1 38 | MI_OK LITERAL1 39 | MFRC522_AUTHENT LITERAL1 40 | MFRC522_CALCCRC LITERAL1 41 | MFRC522_GENID LITERAL1 42 | MFRC522_IDLE LITERAL1 43 | MFRC522_MEM LITERAL1 44 | MFRC522_NOCMDCH LITERAL1 45 | MFRC522_RECEIVE LITERAL1 46 | MFRC522_SOFTRESET LITERAL1 47 | MFRC522_TRANSCEIVE LITERAL1 48 | MFRC522_TRANSMIT LITERAL1 49 | MF1_ANTICOLL LITERAL1 50 | MF1_AUTHENT1A LITERAL1 51 | MF1_AUTHENT1B LITERAL1 52 | MF1_DECREMENT LITERAL1 53 | MF1_HALT LITERAL1 54 | MF1_INCREMENT LITERAL1 55 | MF1_READ LITERAL1 56 | MF1_REQALL LITERAL1 57 | MF1_REQIDL LITERAL1 58 | MF1_RESTORE LITERAL1 59 | MF1_SELECTTAG LITERAL1 60 | MF1_TRANSFER LITERAL1 61 | MF1_WRITE LITERAL1 62 | AnalogTestReg LITERAL1 63 | AutoTestReg LITERAL1 64 | BitFramingReg LITERAL1 65 | CRCResultRegL LITERAL1 66 | CRCResultRegM LITERAL1 67 | CWGsPReg LITERAL1 68 | CollReg LITERAL1 69 | CommIEnReg LITERAL1 70 | CommIrqReg LITERAL1 71 | CommandReg LITERAL1 72 | ControlReg LITERAL1 73 | DemodReg LITERAL1 74 | DivIrqReg LITERAL1 75 | DivlEnReg LITERAL1 76 | ErrorReg LITERAL1 77 | FIFODataReg LITERAL1 78 | FIFOLevelReg LITERAL1 79 | GsNReg LITERAL1 80 | MifareReg LITERAL1 81 | ModGsPReg LITERAL1 82 | ModWidthReg LITERAL1 83 | ModeReg LITERAL1 84 | RFCfgReg LITERAL1 85 | Reserved00 LITERAL1 86 | Reserved01 LITERAL1 87 | Reserved10 LITERAL1 88 | Reserved11 LITERAL1 89 | Reserved12 LITERAL1 90 | Reserved13 LITERAL1 91 | Reserved14 LITERAL1 92 | Reserved20 LITERAL1 93 | Reserved21 LITERAL1 94 | Reserved22 LITERAL1 95 | Reserved30 LITERAL1 96 | Reserved31 LITERAL1 97 | Reserved32 LITERAL1 98 | Reserved33 LITERAL1 99 | Reserved34 LITERAL1 100 | RxModeReg LITERAL1 101 | RxSelReg LITERAL1 102 | RxThresholdReg LITERAL1 103 | SerialSpeedReg LITERAL1 104 | Status1Reg LITERAL1 105 | Status2Reg LITERAL1 106 | TCounterValueRegH LITERAL1 107 | TCounterValueRegL LITERAL1 108 | TModeReg LITERAL1 109 | TPrescalerReg LITERAL1 110 | TReloadRegH LITERAL1 111 | TReloadRegL LITERAL1 112 | TestADCReg LITERAL1 113 | TestBusReg LITERAL1 114 | TestDAC1Reg LITERAL1 115 | TestDAC2Reg LITERAL1 116 | TestPinEnReg LITERAL1 117 | TestPinValueReg LITERAL1 118 | TestSel1Reg LITERAL1 119 | TestSel2Reg LITERAL1 120 | TxAutoReg LITERAL1 121 | TxControlReg LITERAL1 122 | TxModeReg LITERAL1 123 | TxSelReg LITERAL1 124 | VersionReg LITERAL1 125 | WaterLevelReg LITERAL1 126 | -------------------------------------------------------------------------------- /MFRC522.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************/ 2 | /*! 3 | @file MFRC522.h 4 | @author Bjarte Johansen 5 | @licence ljos.mit-license.org 6 | 7 | SPI Driver for MFRC522 NFC/13.56 RFID Transceiver. 8 | 9 | Based on code by Dr.Leong ( WWW.B2CQSHOP.COM ) and 10 | Miguel Balboa (https://github.com/miguelbalboa/rfid). 11 | */ 12 | /******************************************************************************/ 13 | 14 | #include 15 | #include 16 | 17 | #define MAX_LEN 16 // Maximum length of an array. 18 | 19 | // MF522 MFRC522 error codes. 20 | #define MI_OK 0 // Everything A-OK. 21 | #define MI_NOTAGERR 1 // No tag error 22 | #define MI_ERR 2 // General error 23 | 24 | // MF522 Command word 25 | #define MFRC522_IDLE 0x00 // NO action; Cancel the current command 26 | #define MFRC522_MEM 0x01 // Store 25 byte into the internal buffer. 27 | #define MFRC522_GENID 0x02 // Generates a 10 byte random ID number. 28 | #define MFRC522_CALCCRC 0x03 // CRC Calculate or selftest. 29 | #define MFRC522_TRANSMIT 0x04 // Transmit data 30 | #define MFRC522_NOCMDCH 0x07 // No command change. 31 | #define MFRC522_RECEIVE 0x08 // Receive Data 32 | #define MFRC522_TRANSCEIVE 0x0C // Transmit and receive data, 33 | #define MFRC522_AUTHENT 0x0E // Authentication Key 34 | #define MFRC522_SOFTRESET 0x0F // Reset 35 | 36 | // Mifare_One tag command word 37 | #define MF1_REQIDL 0x26 // find the antenna area does not enter hibernation 38 | #define MF1_REQALL 0x52 // find all the tags antenna area 39 | #define MF1_ANTICOLL 0x93 // anti-collision 40 | #define MF1_SELECTTAG 0x93 // election tag 41 | #define MF1_AUTHENT1A 0x60 // authentication key A 42 | #define MF1_AUTHENT1B 0x61 // authentication key B 43 | #define MF1_READ 0x30 // Read Block 44 | #define MF1_WRITE 0xA0 // write block 45 | #define MF1_DECREMENT 0xC0 // debit 46 | #define MF1_INCREMENT 0xC1 // recharge 47 | #define MF1_RESTORE 0xC2 // transfer block data to the buffer 48 | #define MF1_TRANSFER 0xB0 // save the data in the buffer 49 | #define MF1_HALT 0x50 // Sleep 50 | 51 | 52 | //------------------ MFRC522 registers--------------- 53 | //Page 0:Command and Status 54 | #define Reserved00 0x00 55 | #define CommandReg 0x01 56 | #define CommIEnReg 0x02 57 | #define DivIEnReg 0x03 58 | #define CommIrqReg 0x04 59 | #define DivIrqReg 0x05 60 | #define ErrorReg 0x06 61 | #define Status1Reg 0x07 62 | #define Status2Reg 0x08 63 | #define FIFODataReg 0x09 64 | #define FIFOLevelReg 0x0A 65 | #define WaterLevelReg 0x0B 66 | #define ControlReg 0x0C 67 | #define BitFramingReg 0x0D 68 | #define CollReg 0x0E 69 | #define Reserved01 0x0F 70 | //Page 1:Command 71 | #define Reserved10 0x10 72 | #define ModeReg 0x11 73 | #define TxModeReg 0x12 74 | #define RxModeReg 0x13 75 | #define TxControlReg 0x14 76 | #define TxAutoReg 0x15 77 | #define TxSelReg 0x16 78 | #define RxSelReg 0x17 79 | #define RxThresholdReg 0x18 80 | #define DemodReg 0x19 81 | #define Reserved11 0x1A 82 | #define Reserved12 0x1B 83 | #define MifareReg 0x1C 84 | #define Reserved13 0x1D 85 | #define Reserved14 0x1E 86 | #define SerialSpeedReg 0x1F 87 | //Page 2:CFG 88 | #define Reserved20 0x20 89 | #define CRCResultRegM 0x21 90 | #define CRCResultRegL 0x22 91 | #define Reserved21 0x23 92 | #define ModWidthReg 0x24 93 | #define Reserved22 0x25 94 | #define RFCfgReg 0x26 95 | #define GsNReg 0x27 96 | #define CWGsPReg 0x28 97 | #define ModGsPReg 0x29 98 | #define TModeReg 0x2A 99 | #define TPrescalerReg 0x2B 100 | #define TReloadRegH 0x2C 101 | #define TReloadRegL 0x2D 102 | #define TCounterValueRegH 0x2E 103 | #define TCounterValueRegL 0x2F 104 | //Page 3:TestRegister 105 | #define Reserved30 0x30 106 | #define TestSel1Reg 0x31 107 | #define TestSel2Reg 0x32 108 | #define TestPinEnReg 0x33 109 | #define TestPinValueReg 0x34 110 | #define TestBusReg 0x35 111 | #define AutoTestReg 0x36 112 | #define VersionReg 0x37 113 | #define AnalogTestReg 0x38 114 | #define TestDAC1Reg 0x39 115 | #define TestDAC2Reg 0x3A 116 | #define TestADCReg 0x3B 117 | #define Reserved31 0x3C 118 | #define Reserved32 0x3D 119 | #define Reserved33 0x3E 120 | #define Reserved34 0x3F 121 | //----------------------------------------------- 122 | 123 | class MFRC522 { 124 | public: 125 | MFRC522(int sad, int reset); 126 | void writeToRegister(byte addr, byte val); 127 | byte readFromRegister(byte addr); 128 | void setBitMask(byte addr, byte mask); 129 | void clearBitMask(byte addr, byte mask); 130 | void begin(); 131 | void reset(); 132 | byte getFirmwareVersion(); 133 | boolean digitalSelfTestPass(); 134 | int commandTag(byte command, byte *data, int dlen, byte *result, int *rlen); 135 | int requestTag(byte mode, byte *type); 136 | int antiCollision(byte *serial); 137 | void calculateCRC(byte *data, int len, byte *result); 138 | byte selectTag(byte *serial); 139 | int authenticate(byte mode, byte block, byte *key, byte *serial); 140 | int readFromTag(byte blockAddr, byte *recvData); 141 | int writeToTag(byte blockAddr, byte *writeData); 142 | int haltTag(); 143 | 144 | private: 145 | int _sad, _reset; 146 | }; 147 | -------------------------------------------------------------------------------- /MFRC522.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | 4 | @file MFRC522.cpp 5 | @author Bjarte Johansen 6 | @licence ljos.mit-license.org 7 | 8 | SPI Driver for MFRC522 NFC/13.56 RFID Transceiver. 9 | 10 | Based on code by Dr.Leong ( WWW.B2CQSHOP.COM ) and 11 | Miguel Balboa (https://github.com/miguelbalboa/rfid). 12 | 13 | */ 14 | /**************************************************************************/ 15 | 16 | #include 17 | #include 18 | 19 | /**************************************************************************/ 20 | /*! 21 | 22 | @brief Instantiates a new MFRC522 class. 23 | 24 | @param sad SPI chip select pin (CS/SS/SSEL) 25 | @param reset Not reset and power-down pin. 26 | 27 | */ 28 | /**************************************************************************/ 29 | MFRC522::MFRC522(int sad, int reset) { 30 | _sad = sad; 31 | pinMode(_sad, OUTPUT); // Set digital as OUTPUT to connect it to the RFID /ENABLE pin 32 | digitalWrite(_sad, HIGH); 33 | 34 | _reset = reset; 35 | pinMode(_reset, OUTPUT); // Set digital pin, Not Reset and Power-Down 36 | digitalWrite(_reset, HIGH); 37 | 38 | } 39 | 40 | /**************************************************************************/ 41 | /*! 42 | 43 | @brief Writes value to a register. 44 | 45 | @param addr The address a register. 46 | @param val The value to write to a register. 47 | 48 | */ 49 | /**************************************************************************/ 50 | void MFRC522::writeToRegister(byte addr, byte val) { 51 | digitalWrite(_sad, LOW); 52 | 53 | //Address format: 0XXXXXX0 54 | SPI.transfer((addr<<1)&0x7E); 55 | SPI.transfer(val); 56 | 57 | digitalWrite(_sad, HIGH); 58 | } 59 | 60 | /**************************************************************************/ 61 | /*! 62 | 63 | @brief Reads the value at a register. 64 | 65 | @param addr The address a register. 66 | 67 | @returns The byte at the register. 68 | 69 | */ 70 | /**************************************************************************/ 71 | byte MFRC522::readFromRegister(byte addr) { 72 | byte val; 73 | digitalWrite(_sad, LOW); 74 | SPI.transfer(((addr<<1)&0x7E) | 0x80); 75 | val =SPI.transfer(0x00); 76 | digitalWrite(_sad, HIGH); 77 | return val; 78 | } 79 | 80 | /**************************************************************************/ 81 | /*! 82 | 83 | @brief Adds a bitmask to a register. 84 | 85 | @param addr The address a register. 86 | @param mask The mask to update the register with. 87 | 88 | */ 89 | /**************************************************************************/ 90 | void MFRC522::setBitMask(byte addr, byte mask) { 91 | byte current; 92 | current = readFromRegister(addr); 93 | writeToRegister(addr, current | mask); 94 | } 95 | 96 | /**************************************************************************/ 97 | /*! 98 | 99 | @brief Removes a bitmask from the register. 100 | 101 | @param reg The address a register. 102 | @param mask The mask to update the register with. 103 | 104 | */ 105 | /**************************************************************************/ 106 | void MFRC522::clearBitMask(byte addr, byte mask) { 107 | byte current; 108 | current = readFromRegister(addr); 109 | writeToRegister(addr, current & (~mask)); 110 | } 111 | 112 | /**************************************************************************/ 113 | /*! 114 | 115 | @brief Does the setup for the MFRC522. 116 | 117 | */ 118 | /**************************************************************************/ 119 | void MFRC522::begin() { 120 | digitalWrite(_sad, HIGH); 121 | 122 | reset(); 123 | 124 | //Timer: TPrescaler*TreloadVal/6.78MHz = 24ms 125 | writeToRegister(TModeReg, 0x8D); // Tauto=1; f(Timer) = 6.78MHz/TPreScaler 126 | writeToRegister(TPrescalerReg, 0x3E); // TModeReg[3..0] + TPrescalerReg 127 | writeToRegister(TReloadRegL, 30); 128 | writeToRegister(TReloadRegH, 0); 129 | 130 | writeToRegister(TxAutoReg, 0x40); // 100%ASK 131 | writeToRegister(ModeReg, 0x3D); // CRC initial value 0x6363 132 | 133 | setBitMask(TxControlReg, 0x03); // Turn antenna on. 134 | } 135 | 136 | /**************************************************************************/ 137 | /*! 138 | 139 | @brief Sends a SOFTRESET command to the MFRC522 chip. 140 | 141 | */ 142 | /**************************************************************************/ 143 | void MFRC522::reset() { 144 | writeToRegister(CommandReg, MFRC522_SOFTRESET); 145 | } 146 | 147 | /**************************************************************************/ 148 | /*! 149 | 150 | @brief Checks the firmware version of the chip. 151 | 152 | @returns The firmware version of the MFRC522 chip. 153 | 154 | */ 155 | /**************************************************************************/ 156 | byte MFRC522::getFirmwareVersion() { 157 | byte response; 158 | response = readFromRegister(VersionReg); 159 | return response; 160 | } 161 | 162 | /**************************************************************************/ 163 | /*! 164 | 165 | @brief Runs the digital self test. 166 | 167 | @returns True if the self test passes, false otherwise. 168 | 169 | */ 170 | /**************************************************************************/ 171 | boolean MFRC522::digitalSelfTestPass() { 172 | int i; 173 | byte n; 174 | 175 | byte selfTestResultV1[] = {0x00, 0xC6, 0x37, 0xD5, 0x32, 0xB7, 0x57, 0x5C, 176 | 0xC2, 0xD8, 0x7C, 0x4D, 0xD9, 0x70, 0xC7, 0x73, 177 | 0x10, 0xE6, 0xD2, 0xAA, 0x5E, 0xA1, 0x3E, 0x5A, 178 | 0x14, 0xAF, 0x30, 0x61, 0xC9, 0x70, 0xDB, 0x2E, 179 | 0x64, 0x22, 0x72, 0xB5, 0xBD, 0x65, 0xF4, 0xEC, 180 | 0x22, 0xBC, 0xD3, 0x72, 0x35, 0xCD, 0xAA, 0x41, 181 | 0x1F, 0xA7, 0xF3, 0x53, 0x14, 0xDE, 0x7E, 0x02, 182 | 0xD9, 0x0F, 0xB5, 0x5E, 0x25, 0x1D, 0x29, 0x79}; 183 | byte selfTestResultV2[] = {0x00, 0xEB, 0x66, 0xBA, 0x57, 0xBF, 0x23, 0x95, 184 | 0xD0, 0xE3, 0x0D, 0x3D, 0x27, 0x89, 0x5C, 0xDE, 185 | 0x9D, 0x3B, 0xA7, 0x00, 0x21, 0x5B, 0x89, 0x82, 186 | 0x51, 0x3A, 0xEB, 0x02, 0x0C, 0xA5, 0x00, 0x49, 187 | 0x7C, 0x84, 0x4D, 0xB3, 0xCC, 0xD2, 0x1B, 0x81, 188 | 0x5D, 0x48, 0x76, 0xD5, 0x71, 0x61, 0x21, 0xA9, 189 | 0x86, 0x96, 0x83, 0x38, 0xCF, 0x9D, 0x5B, 0x6D, 190 | 0xDC, 0x15, 0xBA, 0x3E, 0x7D, 0x95, 0x3B, 0x2F}; 191 | byte *selfTestResult; 192 | switch(getFirmwareVersion()) { 193 | case 0x91 : 194 | selfTestResult = selfTestResultV1; 195 | break; 196 | case 0x92 : 197 | selfTestResult = selfTestResultV2; 198 | break; 199 | default: 200 | return false; 201 | } 202 | 203 | reset(); 204 | writeToRegister(FIFODataReg, 0x00); 205 | writeToRegister(CommandReg, MFRC522_MEM); 206 | writeToRegister(AutoTestReg, 0x09); 207 | writeToRegister(FIFODataReg, 0x00); 208 | writeToRegister(CommandReg, MFRC522_CALCCRC); 209 | 210 | // Wait for the self test to complete. 211 | i = 0xFF; 212 | do { 213 | n = readFromRegister(DivIrqReg); 214 | i--; 215 | } while ((i != 0) && !(n & 0x04)); 216 | 217 | for (i=0; i < 64; i++) { 218 | if (readFromRegister(FIFODataReg) != selfTestResult[i]) { 219 | Serial.println(i); 220 | return false; 221 | } 222 | } 223 | return true; 224 | } 225 | 226 | /**************************************************************************/ 227 | /*! 228 | 229 | @brief Sends a command to a tag. 230 | 231 | @param cmd The command to the MFRC522 to send a command to the tag. 232 | @param data The data that is needed to complete the command. 233 | @param dlen The length of the data. 234 | @param result The result returned by the tag. 235 | @param rlen The number of valid bits in the resulting value. 236 | 237 | @returns Returns the status of the calculation. 238 | MI_ERR if something went wrong, 239 | MI_NOTAGERR if there was no tag to send the command to. 240 | MI_OK if everything went OK. 241 | 242 | */ 243 | /**************************************************************************/ 244 | int MFRC522::commandTag(byte cmd, byte *data, int dlen, byte *result, int *rlen) { 245 | int status = MI_ERR; 246 | byte irqEn = 0x00; 247 | byte waitIRq = 0x00; 248 | byte lastBits, n; 249 | int i; 250 | 251 | switch (cmd) { 252 | case MFRC522_AUTHENT: 253 | irqEn = 0x12; 254 | waitIRq = 0x10; 255 | break; 256 | case MFRC522_TRANSCEIVE: 257 | irqEn = 0x77; 258 | waitIRq = 0x30; 259 | break; 260 | default: 261 | break; 262 | } 263 | 264 | writeToRegister(CommIEnReg, irqEn|0x80); // interrupt request 265 | clearBitMask(CommIrqReg, 0x80); // Clear all interrupt requests bits. 266 | setBitMask(FIFOLevelReg, 0x80); // FlushBuffer=1, FIFO initialization. 267 | 268 | writeToRegister(CommandReg, MFRC522_IDLE); // No action, cancel the current command. 269 | 270 | // Write to FIFO 271 | for (i=0; i < dlen; i++) { 272 | writeToRegister(FIFODataReg, data[i]); 273 | } 274 | 275 | // Execute the command. 276 | writeToRegister(CommandReg, cmd); 277 | if (cmd == MFRC522_TRANSCEIVE) { 278 | setBitMask(BitFramingReg, 0x80); // StartSend=1, transmission of data starts 279 | } 280 | 281 | // Waiting for the command to complete so we can receive data. 282 | i = 25; // Max wait time is 25ms. 283 | do { 284 | delay(1); 285 | // CommIRqReg[7..0] 286 | // Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq 287 | n = readFromRegister(CommIrqReg); 288 | i--; 289 | } while ((i!=0) && !(n&0x01) && !(n&waitIRq)); 290 | 291 | clearBitMask(BitFramingReg, 0x80); // StartSend=0 292 | 293 | if (i != 0) { // Request did not time out. 294 | if(!(readFromRegister(ErrorReg) & 0x1D)) { // BufferOvfl Collerr CRCErr ProtocolErr 295 | status = MI_OK; 296 | if (n & irqEn & 0x01) { 297 | status = MI_NOTAGERR; 298 | } 299 | 300 | if (cmd == MFRC522_TRANSCEIVE) { 301 | n = readFromRegister(FIFOLevelReg); 302 | lastBits = readFromRegister(ControlReg) & 0x07; 303 | if (lastBits) { 304 | *rlen = (n-1)*8 + lastBits; 305 | } else { 306 | *rlen = n*8; 307 | } 308 | 309 | if (n == 0) { 310 | n = 1; 311 | } 312 | 313 | if (n > MAX_LEN) { 314 | n = MAX_LEN; 315 | } 316 | 317 | // Reading the recieved data from FIFO. 318 | for (i=0; i