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