Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp
00001 #include "mbed.h" 00002 #include "MFRC522.h" 00003 00004 #if defined(TARGET_KL25Z) 00005 00006 /* KL25Z Pins for MFRC522 SPI interface */ 00007 #define SPI_MOSI PTC6 00008 #define SPI_MISO PTC7 00009 #define SPI_SCLK PTC5 00010 #define SPI_CS PTC4 00011 00012 /* KL25Z Pin for MFRC522 reset */ 00013 #define MF_RESET PTC3 00014 00015 /* KL25Z Pins for UART Debug port */ 00016 #define UART_RX PTA1 00017 #define UART_TX PTA2 00018 00019 #elif defined(TARGET_LPC11U24) 00020 00021 /* LPC11U24 Pins for MFRC522 SPI interface */ 00022 #define SPI_MOSI P0_9 00023 #define SPI_MISO P0_8 00024 #define SPI_SCLK P1_29 00025 #define SPI_CS P0_2 00026 00027 /* LPC11U24 Pin for MFRC522 reset */ 00028 #define MF_RESET P1_13 00029 00030 /* LPC11U24 Pins for UART Debug port */ 00031 #define UART_RX P0_18 00032 #define UART_TX P0_19 00033 00034 /* LED Pins */ 00035 #define LED_RED P0_7 00036 #define LED_GREEN P1_22 00037 00038 #endif 00039 00040 DigitalOut LedRed (LED_RED); 00041 DigitalOut LedGreen (LED_GREEN); 00042 00043 Serial DebugUART(UART_TX, UART_RX); 00044 MFRC522 RfChip (SPI_MOSI, SPI_MISO, SPI_SCLK, SPI_CS, MF_RESET); 00045 00046 /* Local functions */ 00047 void DumpMifareClassicToSerial (MFRC522::Uid *uid, uint8_t piccType, MFRC522::MIFARE_Key *key); 00048 void DumpMifareClassicSectorToSerial(MFRC522::Uid *uid, MFRC522::MIFARE_Key *key, uint8_t sector); 00049 void DumpMifareUltralightToSerial (void); 00050 00051 /** 00052 * Dumps debug info about the selected PICC to Serial. 00053 * On success the PICC is halted after dumping the data. 00054 * For MIFARE Classic the factory default key of 0xFFFFFFFFFFFF is tried. 00055 */ 00056 void DumpToSerial(MFRC522::Uid *uid) 00057 { 00058 MFRC522::MIFARE_Key key; 00059 00060 // UID 00061 printf("Card UID: "); 00062 for (uint8_t i = 0; i < uid->size; i++) 00063 { 00064 printf(" %X02", uid->uidByte[i]); 00065 } 00066 printf("\n\r"); 00067 00068 // PICC type 00069 uint8_t piccType = RfChip.PICC_GetType(uid->sak); 00070 printf("PICC Type: %s \n\r", RfChip.PICC_GetTypeName(piccType)); 00071 00072 00073 // Dump contents 00074 switch (piccType) 00075 { 00076 case MFRC522::PICC_TYPE_MIFARE_MINI: 00077 case MFRC522::PICC_TYPE_MIFARE_1K: 00078 case MFRC522::PICC_TYPE_MIFARE_4K: 00079 // All keys are set to FFFFFFFFFFFFh at chip delivery from the factory. 00080 for (uint8_t i = 0; i < 6; i++) { key.keyByte[i] = 0xFF; } 00081 DumpMifareClassicToSerial(uid, piccType, &key); 00082 break; 00083 00084 case MFRC522::PICC_TYPE_MIFARE_UL: 00085 DumpMifareUltralightToSerial(); 00086 break; 00087 00088 case MFRC522::PICC_TYPE_ISO_14443_4: 00089 case MFRC522::PICC_TYPE_ISO_18092: 00090 case MFRC522::PICC_TYPE_MIFARE_PLUS: 00091 case MFRC522::PICC_TYPE_TNP3XXX: 00092 printf("Dumping memory contents not implemented for that PICC type. \n\r"); 00093 break; 00094 00095 case MFRC522::PICC_TYPE_UNKNOWN: 00096 case MFRC522::PICC_TYPE_NOT_COMPLETE: 00097 default: 00098 break; // No memory dump here 00099 } 00100 00101 printf("\n\r"); 00102 00103 RfChip.PICC_HaltA(); // Already done if it was a MIFARE Classic PICC. 00104 } // End PICC_DumpToSerial() 00105 00106 /** 00107 * Dumps memory contents of a MIFARE Classic PICC. 00108 * On success the PICC is halted after dumping the data. 00109 */ 00110 void DumpMifareClassicToSerial(MFRC522::Uid *uid, uint8_t piccType, MFRC522::MIFARE_Key *key) 00111 { 00112 uint8_t no_of_sectors = 0; 00113 switch (piccType) 00114 { 00115 case MFRC522::PICC_TYPE_MIFARE_MINI: 00116 // Has 5 sectors * 4 blocks/sector * 16 bytes/block = 320 bytes. 00117 no_of_sectors = 5; 00118 break; 00119 00120 case MFRC522::PICC_TYPE_MIFARE_1K: 00121 // Has 16 sectors * 4 blocks/sector * 16 bytes/block = 1024 bytes. 00122 no_of_sectors = 16; 00123 break; 00124 00125 case MFRC522::PICC_TYPE_MIFARE_4K: 00126 // Has (32 sectors * 4 blocks/sector + 8 sectors * 16 blocks/sector) * 16 bytes/block = 4096 bytes. 00127 no_of_sectors = 40; 00128 break; 00129 00130 default: 00131 // Should not happen. Ignore. 00132 break; 00133 } 00134 00135 // Dump sectors, highest address first. 00136 if (no_of_sectors) 00137 { 00138 printf("Sector Block 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 AccessBits \n\r"); 00139 printf("----------------------------------------------------------------------------------------- \n\r"); 00140 for (uint8_t i = no_of_sectors - 1; i > 0; i--) 00141 { 00142 DumpMifareClassicSectorToSerial(uid, key, i); 00143 } 00144 } 00145 00146 RfChip.PICC_HaltA(); // Halt the PICC before stopping the encrypted session. 00147 RfChip.PCD_StopCrypto1(); 00148 } // End PICC_DumpMifareClassicToSerial() 00149 00150 /** 00151 * Dumps memory contents of a sector of a MIFARE Classic PICC. 00152 * Uses PCD_Authenticate(), MIFARE_Read() and PCD_StopCrypto1. 00153 * Always uses PICC_CMD_MF_AUTH_KEY_A because only Key A can always read the sector trailer access bits. 00154 */ 00155 void DumpMifareClassicSectorToSerial(MFRC522::Uid *uid, MFRC522::MIFARE_Key *key, uint8_t sector) 00156 { 00157 uint8_t status; 00158 uint8_t firstBlock; // Address of lowest address to dump actually last block dumped) 00159 uint8_t no_of_blocks; // Number of blocks in sector 00160 bool isSectorTrailer; // Set to true while handling the "last" (ie highest address) in the sector. 00161 00162 // The access bits are stored in a peculiar fashion. 00163 // There are four groups: 00164 // g[3] Access bits for the sector trailer, block 3 (for sectors 0-31) or block 15 (for sectors 32-39) 00165 // g[2] Access bits for block 2 (for sectors 0-31) or blocks 10-14 (for sectors 32-39) 00166 // g[1] Access bits for block 1 (for sectors 0-31) or blocks 5-9 (for sectors 32-39) 00167 // g[0] Access bits for block 0 (for sectors 0-31) or blocks 0-4 (for sectors 32-39) 00168 // Each group has access bits [C1 C2 C3]. In this code C1 is MSB and C3 is LSB. 00169 // The four CX bits are stored together in a nible cx and an inverted nible cx_. 00170 uint8_t c1, c2, c3; // Nibbles 00171 uint8_t c1_, c2_, c3_; // Inverted nibbles 00172 bool invertedError = false; // True if one of the inverted nibbles did not match 00173 uint8_t g[4]; // Access bits for each of the four groups. 00174 uint8_t group; // 0-3 - active group for access bits 00175 bool firstInGroup; // True for the first block dumped in the group 00176 00177 // Determine position and size of sector. 00178 if (sector < 32) 00179 { // Sectors 0..31 has 4 blocks each 00180 no_of_blocks = 4; 00181 firstBlock = sector * no_of_blocks; 00182 } 00183 else if (sector < 40) 00184 { // Sectors 32-39 has 16 blocks each 00185 no_of_blocks = 16; 00186 firstBlock = 128 + (sector - 32) * no_of_blocks; 00187 } 00188 else 00189 { // Illegal input, no MIFARE Classic PICC has more than 40 sectors. 00190 return; 00191 } 00192 00193 // Dump blocks, highest address first. 00194 uint8_t byteCount; 00195 uint8_t buffer[18]; 00196 uint8_t blockAddr; 00197 isSectorTrailer = true; 00198 for (uint8_t blockOffset = no_of_blocks - 1; blockOffset > 0; blockOffset--) 00199 { 00200 blockAddr = firstBlock + blockOffset; 00201 00202 // Sector number - only on first line 00203 if (isSectorTrailer) 00204 { 00205 printf(" %2d ", sector); 00206 } 00207 else 00208 { 00209 printf(" "); 00210 } 00211 00212 // Block number 00213 printf(" %3d ", blockAddr); 00214 00215 // Establish encrypted communications before reading the first block 00216 if (isSectorTrailer) 00217 { 00218 status = RfChip.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, firstBlock, key, uid); 00219 if (status != MFRC522::STATUS_OK) 00220 { 00221 printf("PCD_Authenticate() failed: %s \r\n", RfChip.GetStatusCodeName(status)); 00222 return; 00223 } 00224 } 00225 00226 // Read block 00227 byteCount = sizeof(buffer); 00228 status = RfChip.MIFARE_Read(blockAddr, buffer, &byteCount); 00229 if (status != MFRC522::STATUS_OK) 00230 { 00231 printf("MIFARE_Read() failed: %s \r\n", RfChip.GetStatusCodeName(status)); 00232 continue; 00233 } 00234 00235 // Dump data 00236 for (uint8_t index = 0; index < 16; index++) 00237 { 00238 printf(" %3d", buffer[index]); 00239 // if ((index % 4) == 3) 00240 // { 00241 // printf(" "); 00242 // } 00243 } 00244 00245 // Parse sector trailer data 00246 if (isSectorTrailer) 00247 { 00248 c1 = buffer[7] >> 4; 00249 c2 = buffer[8] & 0xF; 00250 c3 = buffer[8] >> 4; 00251 c1_ = buffer[6] & 0xF; 00252 c2_ = buffer[6] >> 4; 00253 c3_ = buffer[7] & 0xF; 00254 invertedError = (c1 != (~c1_ & 0xF)) || (c2 != (~c2_ & 0xF)) || (c3 != (~c3_ & 0xF)); 00255 00256 g[0] = ((c1 & 1) << 2) | ((c2 & 1) << 1) | ((c3 & 1) << 0); 00257 g[1] = ((c1 & 2) << 1) | ((c2 & 2) << 0) | ((c3 & 2) >> 1); 00258 g[2] = ((c1 & 4) << 0) | ((c2 & 4) >> 1) | ((c3 & 4) >> 2); 00259 g[3] = ((c1 & 8) >> 1) | ((c2 & 8) >> 2) | ((c3 & 8) >> 3); 00260 isSectorTrailer = false; 00261 } 00262 00263 // Which access group is this block in? 00264 if (no_of_blocks == 4) 00265 { 00266 group = blockOffset; 00267 firstInGroup = true; 00268 } 00269 else 00270 { 00271 group = blockOffset / 5; 00272 firstInGroup = (group == 3) || (group != (blockOffset + 1) / 5); 00273 } 00274 00275 if (firstInGroup) 00276 { 00277 // Print access bits 00278 printf(" [ %d %d %d ] ", (g[group] >> 2) & 1, (g[group] >> 1) & 1, (g[group] >> 0) & 1); 00279 if (invertedError) 00280 { 00281 printf(" Inverted access bits did not match! "); 00282 } 00283 } 00284 00285 if (group != 3 && (g[group] == 1 || g[group] == 6)) 00286 { // Not a sector trailer, a value block 00287 printf(" Addr = 0x%02X, Value = 0x%02X%02X%02X%02X", buffer[12], 00288 buffer[3], 00289 buffer[2], 00290 buffer[1], 00291 buffer[0]); 00292 } 00293 00294 printf("\n\r"); 00295 } 00296 00297 return; 00298 } // End PICC_DumpMifareClassicSectorToSerial() 00299 00300 /** 00301 * Dumps memory contents of a MIFARE Ultralight PICC. 00302 */ 00303 void DumpMifareUltralightToSerial(void) 00304 { 00305 uint8_t status; 00306 uint8_t byteCount; 00307 uint8_t buffer[18]; 00308 uint8_t i; 00309 00310 printf("Page 0 1 2 3"); 00311 // Try the mpages of the original Ultralight. Ultralight C has more pages. 00312 for (uint8_t page = 0; page < 16; page +=4) 00313 { 00314 // Read pages 00315 byteCount = sizeof(buffer); 00316 status = RfChip.MIFARE_Read(page, buffer, &byteCount); 00317 if (status != MFRC522::STATUS_OK) 00318 { 00319 printf("MIFARE_Read() failed: %s \n\r", RfChip.GetStatusCodeName(status)); 00320 break; 00321 } 00322 00323 // Dump data 00324 for (uint8_t offset = 0; offset < 4; offset++) 00325 { 00326 i = page + offset; 00327 printf(" %2d ", i); // Pad with spaces 00328 for (uint8_t index = 0; index < 4; index++) 00329 { 00330 i = 4 * offset + index; 00331 printf(" %02X ", buffer[i]); 00332 } 00333 00334 printf("\n\r"); 00335 } 00336 } 00337 } // End PICC_DumpMifareUltralightToSerial() 00338 00339 int main() 00340 { 00341 /* Set debug UART speed */ 00342 DebugUART.baud(115200); 00343 printf("< mbed RFID demo >\n\r"); 00344 printf("\n\r"); 00345 00346 /* Init. RC522 Chip */ 00347 RfChip.PCD_Init(); 00348 00349 /* Read RC522 version */ 00350 uint8_t temp = RfChip.PCD_ReadRegister(MFRC522::VersionReg); 00351 printf("MFRC522 version: %d\n\r", temp & 0x07); 00352 printf("\n\r"); 00353 00354 while(1) 00355 { 00356 LedRed = 1; 00357 LedGreen = 1; 00358 00359 // Look for new cards 00360 if ( ! RfChip.PICC_IsNewCardPresent()) 00361 { 00362 wait_ms(500); 00363 continue; 00364 } 00365 00366 LedRed = 0; 00367 00368 // Select one of the cards 00369 if ( ! RfChip.PICC_ReadCardSerial()) 00370 { 00371 wait_ms(500); 00372 continue; 00373 } 00374 00375 LedRed = 1; 00376 LedGreen = 0; 00377 00378 // Dump debug info about the card. PICC_HaltA() is automatically called. 00379 DumpToSerial(&(RfChip.uid)); 00380 wait_ms(200); 00381 } 00382 }
Generated on Tue Jul 12 2022 19:01:03 by
1.7.2