/********************************************************************************** * Autor: Fco. Javier Rodriguez Navarro www.pinguytaz.net * Version 1.0 Abril 2.017 * * Lectura de un sector de la tarjeta RFID Mifare Classic de 1K. * Nos preguntara el bloque y el sector a leer. * *----------------------------------- *MFRC522 Arduino Arduino *Reader/PCD Uno Nano v3 * ---------------------------------- * RST 9 D9 * SDA(SS) 10 D10 * MOSI 11 / ICSP-4 D11 * MISO 12 / ICSP-1 D12 * SCK 13 / ICSP-3 D13 * * * Reconocimientos: * Libreria de Miguel Balboa. * * DATOS ALMACENAMIENTO: * Programa: 10.952 bytes * Variables Globales 705 bytes *********************************************************************************/ #include #include #define RST_PIN 9 // Pin 9 para el reset del RC522 #define SS_PIN 10 // Pin 10 para el SS (SDA) del RC522 MFRC522 rfid(SS_PIN, RST_PIN); // Crear instancia del MFRC522 /***************************+ SETUP solo al inicio ************/ void setup() { Serial.begin(9600); SPI.begin(); //Función que inicializa SPI rfid.PCD_Init(); //Función que inicializa RFID rfid.PCD_DumpVersionToSerial(); // Traduce PCD_ReadRegister(rfid.VersionReg) Serial.println("A la espera de leer una tarjeta"); } // Finaliza setup /***************** LOOP que se ejecuta siempre ****************/ void loop() { MFRC522::PICC_Type piccTipo; int bloque=4 ; // Tenemos 4 bloques que van del 0 al 3. Se inicializan para probocar pregunta int sector=16; // Tenemos 16 sectores que van del 0-15. Se inicializan para probocar pregunta byte dirBloque, Bloque0; byte dBloque[18]; // Los datos leidos en un bloque son 16 bytes más 2 CRC. byte numByte = sizeof(dBloque); MFRC522::StatusCode estado; // Tendra los retornos de envios de comandos. MFRC522:.STATUS_???? MFRC522::MIFARE_Key clave; if (! rfid.PICC_IsNewCardPresent()) return; // Si no detecta tarjeta otro Bucle. if (! rfid.PICC_ReadCardSerial()) return; // Lee los datos de la tarjeta, si error sale del bucle piccTipo = rfid.PICC_GetType(rfid.uid.sak); // Recoge el tipo de tarjeta PIC. Serial.println("Tipo PICC: "+ String(rfid.PICC_GetTypeName(piccTipo))); Serial.print("NUID("+ String(rfid.uid.size)+")"); printHex(rfid.uid.uidByte,rfid.uid.size); Serial.println(" SAK: "+ String(rfid.uid.sak)); if (piccTipo = MFRC522::PICC_TYPE_MIFARE_1K) // Este programa solo interpreta tarjetas MIFARE 1K 4bytes UID(NUID) { // 16 sectores y cada uno de ellos 4 bloques. while (bloque >= 4) // Preguntamos por el bloque a leer (0-3) { bloque = leeInt("Bloque"); Serial.println(bloque); } // Fin de la pregunta de bloque while (sector >= 16) // Preguntamos por el sector a leer (0-15) { sector = leeInt("Sector"); Serial.println(sector); } // Fin de la pregunta del sector. Bloque0 = sector*4; // Calculamos direccion bloque 0 del sector dirBloque = Bloque0 + bloque; // Direccion del bloque a leer // Realizamos autentificación // Clave por defecto 0xFFFFFFFFFFFF que llega de fabrica. for(byte i =0 ; i< 6 ; i++) clave.keyByte[i] = 0xFF; estado = rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, Bloque0, &clave, &rfid.uid); if (estado != MFRC522::STATUS_OK) { Serial.println("Fallo en la autentificación"); return; } // Realizamos la lectura. estado = rfid.MIFARE_Read(dirBloque, dBloque, &numByte); if(estado != MFRC522::STATUS_OK) { Serial.println(rfid.GetStatusCodeName(estado)); // Existio un error return; } Serial.println("Dir.\tSector\tBloque\t 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"); Serial.print(String(Bloque0)+"\t"+String(sector)+"\t"+String(bloque)+"\t"); printHex(dBloque,16); // Datos en Hexadecimal. if (bloque==3) Volcado_Trailer(dBloque); else if(sector==0 && bloque == 0) Volcado_Fabrica(dBloque); else Volcado_Datos(dBloque); Serial.println("--------------------------------------------------------------------"); } // Fin OK MIFARE 1K . else { Serial.println("No conozco esa tarjeta"); } // Fin desconozco tarjeta rfid.PICC_HaltA(); rfid.PCD_StopCrypto1(); delay(250); } // Finaliza Loop /******************************************************************* * Volcado_Trailer(byte *) * * Realiza un voldado de los datos de un sector Trailer * El Bloque 0 de cualquier sector se llama Sector Trailes * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 * [ KEY A ] [ A.Bits ] [ KEY B ] * * @param Datos a imprimir * @return ninguno *****************************************************************/ void Volcado_Trailer(byte *buffer) { Serial.print(" KEY A: "); printCar(buffer,6,0); Serial.println(""); Serial.print("\t\t\t\t\t\t\t\t\t KEY B: "); printCar(buffer,6,10); Serial.println(""); Serial.print("\t\t\t\t\t\t\t\t\t Bits Acceso: "); Serial.print("B3:"+String(bitRead(buffer[7],7))+String(bitRead(buffer[8],3))+String(bitRead(buffer[8],7))+" "); Serial.print("B2:"+String(bitRead(buffer[7],6))+String(bitRead(buffer[8],2))+String(bitRead(buffer[8],6))+" "); Serial.print("B1:"+String(bitRead(buffer[7],5))+String(bitRead(buffer[8],1))+String(bitRead(buffer[8],5))+" "); Serial.println("B0:"+String(bitRead(buffer[7],4))+String(bitRead(buffer[8],0))+String(bitRead(buffer[8],4))); Serial.print("\t\t\t\t\t\t\t\t\t Usu: "); printCar(buffer,1,9); Serial.println(""); } /******************************************************************* * Volcado_Fabrica(byte *) * * Realiza un voldado de los datos de fabrica de una MIFARE * El sector0 Bloque0 es de Fabricante. * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 * [ NUID ] [CRC][SAK=8][ATQA_0=4][ATQA_1=0][ Datos fabricante ] * * @param Datos a imprimir * @return ninguno *****************************************************************/ void Volcado_Fabrica(byte *buffer) { Serial.println(" NUID: "+String(buffer[0],HEX)+String(buffer[1],HEX)+String(buffer[2],HEX)+String(buffer[3],HEX)); Serial.println("\t\t\t\t\t\t\t\t\t CRC:"+String(buffer[4],HEX)); Serial.println("\t\t\t\t\t\t\t\t\t SAK:"+String(buffer[5],HEX)); Serial.println("\t\t\t\t\t\t\t\t\t ATQA:"+String(buffer[5],HEX)+String(buffer[7],HEX)); Serial.print("\t\t\t\t\t\t\t\t\t Fabricante: "); printCar(buffer,8,8); Serial.println(""); } /******************************************************************* * Volcado_Datos(byte *, int, int) * * Realiza un voldado de los datos de un bloque datos * * Los bloques pueden ser simplemente datos o Bloque Valor * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 * [ VAL ] [VAL_INV ] [ VAL ] [A] [aI] [A] [aI] * * @param Datos a imprimir * @return ninguno *****************************************************************/ void Volcado_Datos(byte *buffer) { printCar(buffer,16); Serial.println(""); } /******************************************************************* * leeInt(String) * * Lee un entero por consola * * @param String con el texto de la pregunta * @return Entero leido. *****************************************************************/ int leeInt(String pregunta) { byte caracter; String numero=""; int retorno = 0; Serial.print(pregunta+": "); while (caracter != '\n') { if(Serial.available()) caracter = Serial.read(); if (isDigit(caracter)) { //Serial.println(caracter); numero += (char) caracter; //Serial.print1ln(numero); caracter = 0; // Pone Nulo } } // Fin del While que sale cuando pulsamos el Enter. retorno = numero.toInt(); return retorno; } // Fin leeInt. /******************************************************************* * printHex((byte *buffer, byte bufferSize) * * Vuelca un array de bytes en Hexadeciaml. * * @param array de bytes a imprimir * @param Numero de bytes a volcar. * @return Ninguno. *****************************************************************/ void printHex(byte *buffer, byte bufferSize) { for (byte i = 0; i < bufferSize; i++) { Serial.print(buffer[i] < 0x10 ? " 0" : " "); Serial.print(buffer[i], HEX); } } /******************************************************************* * printDec((byte *buffer, byte bufferSize) * * Vuelca un array de bytes en Decimal. * * @param array de bytes a imprimir * @param Numero de bytes a volcar. * @return Ninguno. *******************************************************************/ void printDec(byte *buffer, byte bufferSize) { for (byte i = 0; i < bufferSize; i++) { Serial.print(buffer[i] < 0x10 ? " 0" : " "); Serial.print(buffer[i], DEC); } } /******************************************************************* * printCar((byte *buffer, byte bufferSize) * * Vuelca un array de bytes en caracteres imprimible (ASCII 32-127) * * @param array de bytes a imprimir * @param Numero de bytes a volcar. * @param Inicio del array. * @return Ninguno. *******************************************************************/ void printCar(byte *buffer, byte bufferSize) {printCar(buffer,bufferSize,0);} void printCar(byte *buffer, byte bufferSize, int inicio) { for (byte i = inicio; i < bufferSize+inicio; i++) { Serial.print(""); if(buffer[i]>32 && buffer[i]< 127) Serial.print(String((char) buffer[i])+" "); else { Serial.print(" 0x"); Serial.print(buffer[i], HEX); Serial.print(" "); } } }