/********************************************************************************** * Autor: Fco. Javier Rodriguez Navarro www.pinguytaz.net * Version 1.0 Mayo 2.017 * * Escribimos datos en un sector y un bloque de la tarjeta RFID Mifare Classic de 1K. * Nos preguntara el bloque y el sector a leer, para evitar dejar la tarjeta o * mejor dicho el sector por error fuera de servicio no permitimos el bloque 3 * de cualquier secto y el bloque 0 del sector 0 * *----------------------------------- *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: 10584 bytes * Variables Globales 477 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 ; int sector; 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; byte datos[16] = { '(','c',')','G','A','R','U','M',' ','2','0','1','7',' ', ' ',' '}; 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. bloque = leeInt("Bloque", 2); Serial.println(bloque); if (bloque == 0) sector = leeInt("Sector",1,15); else sector = leeInt("Sector",15); Serial.println(sector); Bloque0 = sector*4; // Calculamos direccion bloque 0 del sector dirBloque = Bloque0 + bloque; // Direccion del bloque a leer // Primero imprimimos los valores antiguos, luego los cambiamos y los volvemos a imprimir. // 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.print("Sector: "+String(sector)+" Bloque: "+String(bloque)+"\t"); printHex(dBloque,16); // Datos en Hexadecimal. Serial.print("\t"); printCar(dBloque,16); // Datos en Caracteres Serial.println(""); leeCar("16 caracteres a Grabar :",datos,16); printCar(datos,16); Serial.println(""); // Realiza la escritura estado = rfid.MIFARE_Write(dirBloque, datos, 16); if(estado != MFRC522::STATUS_OK) { Serial.println(rfid.GetStatusCodeName(estado)); // Existio un error return; } Serial.println("ESCRITO"); // 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.print("Sector: "+String(sector)+" Bloque: "+String(bloque)+"\t"); printHex(dBloque,16); // Datos en Hexadecimal. Serial.print("\t"); printCar(dBloque,16); // Datos en Caracteres Serial.println(""); Serial.println("A la espera de leer una tarjeta"); } // Fin OK MIFARE 1K . else { Serial.println("No conozco esa tarjeta"); } // Fin desconozco tarjeta rfid.PICC_HaltA(); rfid.PCD_StopCrypto1(); delay(250); } // Finaliza Loop /******************************************************************* * leeInt(String) * * Lee un entero por consola, entre dos valores. * * @param String con el texto de la pregunta * @param int valor minimo, si no esta es 0. * @param int valor maximo * * @return Entero leido. *****************************************************************/ int leeInt(String pregunta, int maximo) { return leeInt(pregunta,0,maximo); } int leeInt(String pregunta, int minimo, int maximo) { byte caracter=0; String numero=""; int retorno = -1; int valor=-1 ; Serial.print(pregunta+"["+String(minimo)+" - "+String(maximo)+"]: "); while (retorno == -1 ) { 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. valor = numero.toInt(); //Serial.println("Valor: "+String(valor)+" min,max "+String(minimo)+", "+String(maximo)+"---"+String(retorno)); if (valor >= minimo && valor <= maximo && numero != "") retorno = valor; else numero=""; } //retorno = numero.toInt(); return retorno; } // Fin leeInt. /******************************************************************* * leeCar(String, lectura, longitud) * * Lee tantos caracteres como indica longitud y se guardan en lectura * * @param String con el texto de la pregunta * @param byte[] con los datos leidos * @param Datos a leer * * @return Nada. *****************************************************************/ void leeCar(String pregunta, byte *buffer, int maximo) { int i=0; Serial.println(pregunta+": "); Serial.setTimeout(10000); Serial.readBytes(buffer,16); while (Serial.available()) Serial.read(); // Vacia buffer Serial.read(); } /****************************************************************** * 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(" "); } } }