Merge branch 'master' into example_firmware_check

This commit is contained in:
Rotzbua
2015-09-04 11:40:28 +02:00
6 changed files with 153 additions and 43 deletions

View File

@@ -18,18 +18,8 @@
MFRC522::MFRC522( byte chipSelectPin, ///< Arduino pin connected to MFRC522's SPI slave select input (Pin 24, NSS, active low)
byte resetPowerDownPin ///< Arduino pin connected to MFRC522's reset and power down input (Pin 6, NRSTPD, active low)
) {
// Set the chipSelectPin as digital output, do not select the slave yet
_chipSelectPin = chipSelectPin;
pinMode(_chipSelectPin, OUTPUT);
digitalWrite(_chipSelectPin, HIGH);
// Set the resetPowerDownPin as digital output, do not reset or power down.
_resetPowerDownPin = resetPowerDownPin;
pinMode(_resetPowerDownPin, OUTPUT);
digitalWrite(_resetPowerDownPin, LOW);
// Set SPI bus to work with MFRC522 chip.
setSPIConfig();
} // End constructor
/**
@@ -100,7 +90,7 @@ void MFRC522::PCD_ReadRegister( byte reg, ///< The register to read from. One o
if (count == 0) {
return;
}
//Serial.print("Reading "); Serial.print(count); Serial.println(" bytes from register.");
//Serial.print(F("Reading ")); Serial.print(count); Serial.println(F(" bytes from register."));
byte address = 0x80 | (reg & 0x7E); // MSB == 1 is for reading. LSB is not used in address. Datasheet section 8.1.2.3.
byte index = 0; // Index in values array.
digitalWrite(_chipSelectPin, LOW); // Select slave
@@ -194,6 +184,16 @@ byte MFRC522::PCD_CalculateCRC( byte *data, ///< In: Pointer to the data to tra
* Initializes the MFRC522 chip.
*/
void MFRC522::PCD_Init() {
// Set the chipSelectPin as digital output, do not select the slave yet
pinMode(_chipSelectPin, OUTPUT);
digitalWrite(_chipSelectPin, HIGH);
// Set the resetPowerDownPin as digital output, do not reset or power down.
pinMode(_resetPowerDownPin, OUTPUT);
// Set SPI bus to work with MFRC522 chip.
setSPIConfig();
if (digitalRead(_resetPowerDownPin) == LOW) { //The MFRC522 chip is in power down mode.
digitalWrite(_resetPowerDownPin, HIGH); // Exit power down mode. This triggers a hard reset.
// Section 8.8.2 in the datasheet says the oscillator start-up time is the start up time of the crystal + 37,74<37>s. Let us be generous: 50ms.
@@ -323,6 +323,12 @@ bool MFRC522::PCD_PerformSelfTest() {
// Pick the appropriate reference values
const byte *reference;
switch (version) {
case 0x88: // Fudan Semiconductor FM17522 clone
reference = FM17522_firmware_reference;
break;
case 0x90: // Version 0.0
reference = MFRC522_firmware_referenceV0_0;
break;
case 0x91: // Version 1.0
reference = MFRC522_firmware_referenceV1_0;
break;
@@ -545,7 +551,7 @@ byte MFRC522::PICC_Select( Uid *uid, ///< Pointer to Uid struct. Normally outp
byte count;
byte index;
byte uidIndex; // The first index in uid->uidByte[] that is used in the current Cascade Level.
char currentLevelKnownBits; // The number of known UID bits in the current Cascade Level.
int8_t currentLevelKnownBits; // The number of known UID bits in the current Cascade Level.
byte buffer[9]; // The SELECT/ANTICOLLISION commands uses a 7 byte standard frame + 2 bytes CRC_A
byte bufferUsed; // The number of bytes used in the buffer, ie the number of bytes to transfer to the FIFO.
byte rxAlign; // Used in BitFramingReg. Defines the bit position for the first bit received.
@@ -641,7 +647,7 @@ byte MFRC522::PICC_Select( Uid *uid, ///< Pointer to Uid struct. Normally outp
while (!selectDone) {
// Find out how many bits and bytes to send and receive.
if (currentLevelKnownBits >= 32) { // All UID bits in this Cascade Level are known. This is a SELECT.
//Serial.print("SELECT: currentLevelKnownBits="); Serial.println(currentLevelKnownBits, DEC);
//Serial.print(F("SELECT: currentLevelKnownBits=")); Serial.println(currentLevelKnownBits, DEC);
buffer[1] = 0x70; // NVB - Number of Valid Bits: Seven whole bytes
// Calculate BCC - Block Check Character
buffer[6] = buffer[2] ^ buffer[3] ^ buffer[4] ^ buffer[5];
@@ -657,7 +663,7 @@ byte MFRC522::PICC_Select( Uid *uid, ///< Pointer to Uid struct. Normally outp
responseLength = 3;
}
else { // This is an ANTICOLLISION.
//Serial.print("ANTICOLLISION: currentLevelKnownBits="); Serial.println(currentLevelKnownBits, DEC);
//Serial.print(F("ANTICOLLISION: currentLevelKnownBits=")); Serial.println(currentLevelKnownBits, DEC);
txLastBits = currentLevelKnownBits % 8;
count = currentLevelKnownBits / 8; // Number of whole bytes in the UID part.
index = 2 + count; // Number of whole bytes: SEL + NVB + UIDs
@@ -1141,6 +1147,7 @@ byte MFRC522::PCD_MIFARE_Transceive( byte *sendData, ///< Pointer to the data t
/**
* Returns a __FlashStringHelper pointer to a status code name.
*
* @return const __FlashStringHelper *
*/
const __FlashStringHelper *MFRC522::GetStatusCodeName(byte code ///< One of the StatusCode enums.
) {
@@ -1194,6 +1201,7 @@ byte MFRC522::PICC_GetType(byte sak ///< The SAK byte returned from PICC_Select
/**
* Returns a __FlashStringHelper pointer to the PICC type name.
*
* @return const __FlashStringHelper *
*/
const __FlashStringHelper *MFRC522::PICC_GetTypeName(byte piccType ///< One of the PICC_Type enums.
) {
@@ -1224,7 +1232,10 @@ void MFRC522::PICC_DumpToSerial(Uid *uid ///< Pointer to Uid struct returned fro
// UID
Serial.print(F("Card UID:"));
for (byte i = 0; i < uid->size; i++) {
Serial.print(uid->uidByte[i] < 0x10 ? " 0" : " ");
if(uid->uidByte[i] < 0x10)
Serial.print(F(" 0"));
else
Serial.print(F(" "));
Serial.print(uid->uidByte[i], HEX);
}
Serial.println();
@@ -1299,7 +1310,7 @@ void MFRC522::PICC_DumpMifareClassicToSerial( Uid *uid, ///< Pointer to Uid str
// Dump sectors, highest address first.
if (no_of_sectors) {
Serial.println(F("Sector Block 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 AccessBits"));
for (char i = no_of_sectors - 1; i >= 0; i--) {
for (int8_t i = no_of_sectors - 1; i >= 0; i--) {
PICC_DumpMifareClassicSectorToSerial(uid, key, i);
}
}
@@ -1354,11 +1365,14 @@ void MFRC522::PICC_DumpMifareClassicSectorToSerial(Uid *uid, ///< Pointer to U
byte buffer[18];
byte blockAddr;
isSectorTrailer = true;
for (char blockOffset = no_of_blocks - 1; blockOffset >= 0; blockOffset--) {
for (int8_t blockOffset = no_of_blocks - 1; blockOffset >= 0; blockOffset--) {
blockAddr = firstBlock + blockOffset;
// Sector number - only on first line
if (isSectorTrailer) {
Serial.print(sector < 10 ? " " : " "); // Pad with spaces
if(sector < 10)
Serial.print(F(" ")); // Pad with spaces
else
Serial.print(F(" ")); // Pad with spaces
Serial.print(sector);
Serial.print(F(" "));
}
@@ -1366,7 +1380,14 @@ void MFRC522::PICC_DumpMifareClassicSectorToSerial(Uid *uid, ///< Pointer to U
Serial.print(F(" "));
}
// Block number
Serial.print(blockAddr < 10 ? " " : (blockAddr < 100 ? " " : " ")); // Pad with spaces
if(blockAddr < 10)
Serial.print(F(" ")); // Pad with spaces
else {
if(blockAddr < 100)
Serial.print(F(" ")); // Pad with spaces
else
Serial.print(F(" ")); // Pad with spaces
}
Serial.print(blockAddr);
Serial.print(F(" "));
// Establish encrypted communications before reading the first block
@@ -1388,7 +1409,10 @@ void MFRC522::PICC_DumpMifareClassicSectorToSerial(Uid *uid, ///< Pointer to U
}
// Dump data
for (byte index = 0; index < 16; index++) {
Serial.print(buffer[index] < 0x10 ? " 0" : " ");
if(buffer[index] < 0x10)
Serial.print(F(" 0"));
else
Serial.print(F(" "));
Serial.print(buffer[index], HEX);
if ((index % 4) == 3) {
Serial.print(F(" "));
@@ -1423,8 +1447,8 @@ void MFRC522::PICC_DumpMifareClassicSectorToSerial(Uid *uid, ///< Pointer to U
if (firstInGroup) {
// Print access bits
Serial.print(F(" [ "));
Serial.print((g[group] >> 2) & 1, DEC); Serial.print(" ");
Serial.print((g[group] >> 1) & 1, DEC); Serial.print(" ");
Serial.print((g[group] >> 2) & 1, DEC); Serial.print(F(" "));
Serial.print((g[group] >> 1) & 1, DEC); Serial.print(F(" "));
Serial.print((g[group] >> 0) & 1, DEC);
Serial.print(F(" ] "));
if (invertedError) {
@@ -1466,12 +1490,18 @@ void MFRC522::PICC_DumpMifareUltralightToSerial() {
// Dump data
for (byte offset = 0; offset < 4; offset++) {
i = page + offset;
Serial.print(i < 10 ? " " : " "); // Pad with spaces
if(i < 10)
Serial.print(F(" ")); // Pad with spaces
else
Serial.print(F(" ")); // Pad with spaces
Serial.print(i);
Serial.print(F(" "));
for (byte index = 0; index < 4; index++) {
i = 4 * offset + index;
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
if(buffer[i] < 0x10)
Serial.print(F(" 0"));
else
Serial.print(F(" "));
Serial.print(buffer[i], HEX);
}
Serial.println();
@@ -1695,6 +1725,7 @@ bool MFRC522::MIFARE_UnbrickUidSector(bool logErrors) {
}
return false;
}
return true;
}
/////////////////////////////////////////////////////////////////////////////////////

View File

@@ -58,13 +58,13 @@
* MIFARE Ultralight (MF0ICU1):
* Has 16 pages of 4 bytes = 64 bytes.
* Pages 0 + 1 is used for the 7-byte UID.
* Page 2 contains the last chech digit for the UID, one byte manufacturer internal data, and the lock bytes (see http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2)
* Page 2 contains the last check digit for the UID, one byte manufacturer internal data, and the lock bytes (see http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2)
* Page 3 is OTP, One Time Programmable bits. Once set to 1 they cannot revert to 0.
* Pages 4-15 are read/write unless blocked by the lock bytes in page 2.
* MIFARE Ultralight C (MF0ICU2):
* Has 48 pages of 4 bytes = 64 bytes.
* Has 48 pages of 4 bytes = 192 bytes.
* Pages 0 + 1 is used for the 7-byte UID.
* Page 2 contains the last chech digit for the UID, one byte manufacturer internal data, and the lock bytes (see http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2)
* Page 2 contains the last check digit for the UID, one byte manufacturer internal data, and the lock bytes (see http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2)
* Page 3 is OTP, One Time Programmable bits. Once set to 1 they cannot revert to 0.
* Pages 4-39 are read/write unless blocked by the lock bytes in page 2.
* Page 40 Lock bytes
@@ -79,8 +79,23 @@
#include <SPI.h>
// Firmware data for self-test
// Reference values based on firmware version; taken from 16.1.1 in spec.
// Version 1.0
// Reference values based on firmware version
// Hint: if needed, you can remove unused self-test data to save flash memory
//
// Version 0.0 (0x90)
// Philips Semiconductors; Preliminary Specification Revision 2.0 - 01 August 2005; 16.1 Sefttest
const byte MFRC522_firmware_referenceV0_0[] PROGMEM = {
0x00, 0x87, 0x98, 0x0f, 0x49, 0xFF, 0x07, 0x19,
0xBF, 0x22, 0x30, 0x49, 0x59, 0x63, 0xAD, 0xCA,
0x7F, 0xE3, 0x4E, 0x03, 0x5C, 0x4E, 0x49, 0x50,
0x47, 0x9A, 0x37, 0x61, 0xE7, 0xE2, 0xC6, 0x2E,
0x75, 0x5A, 0xED, 0x04, 0x3D, 0x02, 0x4B, 0x78,
0x32, 0xFF, 0x58, 0x3B, 0x7C, 0xE9, 0x00, 0x94,
0xB4, 0x4A, 0x59, 0x5B, 0xFD, 0xC9, 0x29, 0xDF,
0x35, 0x96, 0x98, 0x9E, 0x4F, 0x30, 0x32, 0x8D
};
// Version 1.0 (0x91)
// NXP Semiconductors; Rev. 3.8 - 17 September 2014; 16.1.1 Self test
const byte MFRC522_firmware_referenceV1_0[] PROGMEM = {
0x00, 0xC6, 0x37, 0xD5, 0x32, 0xB7, 0x57, 0x5C,
0xC2, 0xD8, 0x7C, 0x4D, 0xD9, 0x70, 0xC7, 0x73,
@@ -91,7 +106,8 @@ const byte MFRC522_firmware_referenceV1_0[] PROGMEM = {
0x1F, 0xA7, 0xF3, 0x53, 0x14, 0xDE, 0x7E, 0x02,
0xD9, 0x0F, 0xB5, 0x5E, 0x25, 0x1D, 0x29, 0x79
};
// Version 2.0
// Version 2.0 (0x92)
// NXP Semiconductors; Rev. 3.8 - 17 September 2014; 16.1.1 Self test
const byte MFRC522_firmware_referenceV2_0[] PROGMEM = {
0x00, 0xEB, 0x66, 0xBA, 0x57, 0xBF, 0x23, 0x95,
0xD0, 0xE3, 0x0D, 0x3D, 0x27, 0x89, 0x5C, 0xDE,
@@ -102,6 +118,18 @@ const byte MFRC522_firmware_referenceV2_0[] PROGMEM = {
0x86, 0x96, 0x83, 0x38, 0xCF, 0x9D, 0x5B, 0x6D,
0xDC, 0x15, 0xBA, 0x3E, 0x7D, 0x95, 0x3B, 0x2F
};
// Clone
// Fudan Semiconductor FM17522 (0x88)
const byte FM17522_firmware_reference[] PROGMEM = {
0x00, 0xD6, 0x78, 0x8C, 0xE2, 0xAA, 0x0C, 0x18,
0x2A, 0xB8, 0x7A, 0x7F, 0xD3, 0x6A, 0xCF, 0x0B,
0xB1, 0x37, 0x63, 0x4B, 0x69, 0xAE, 0x91, 0xC7,
0xC3, 0x97, 0xAE, 0x77, 0xF4, 0x37, 0xD7, 0x9B,
0x7C, 0xF5, 0x3C, 0x11, 0x8F, 0x15, 0xC3, 0xD7,
0xC1, 0x5B, 0x00, 0x2A, 0xD0, 0x75, 0xDE, 0x9E,
0x51, 0x64, 0xAB, 0x3E, 0xE9, 0x15, 0xB5, 0xAB,
0x56, 0x9A, 0x98, 0x82, 0x26, 0xEA, 0x2A, 0x62
};
class MFRC522 {
public:
@@ -218,8 +246,8 @@ public:
PICC_CMD_WUPA = 0x52, // Wake-UP command, Type A. Invites PICCs in state IDLE and HALT to go to READY(*) and prepare for anticollision or selection. 7 bit frame.
PICC_CMD_CT = 0x88, // Cascade Tag. Not really a command, but used during anti collision.
PICC_CMD_SEL_CL1 = 0x93, // Anti collision/Select, Cascade Level 1
PICC_CMD_SEL_CL2 = 0x95, // Anti collision/Select, Cascade Level 1
PICC_CMD_SEL_CL3 = 0x97, // Anti collision/Select, Cascade Level 1
PICC_CMD_SEL_CL2 = 0x95, // Anti collision/Select, Cascade Level 2
PICC_CMD_SEL_CL3 = 0x97, // Anti collision/Select, Cascade Level 3
PICC_CMD_HLTA = 0x50, // HaLT command, Type A. Instructs an ACTIVE PICC to go to state HALT.
// The commands used for MIFARE Classic (from http://www.nxp.com/documents/data_sheet/MF1S503x.pdf, Section 9)
// Use PCD_MFAuthent to authenticate access to a sector, then use these commands to read/write/modify the blocks on the sector.

View File

@@ -28,11 +28,11 @@ The following table shows the typical pin layout used:
+-----------+----------+-------------+---------+---------+---------------+-----------+--------+
| SPI SS | SDA [3]_ | 10 [2]_ | 53 [2]_ | D10 | 10 | 10 | 10 |
+-----------+----------+-------------+---------+---------+---------------+-----------+--------+
| SPI MOSI | MOSI | 11 / ICSP-4 | 52 | D11 | ICSP-4 | 16 | 11 |
| SPI MOSI | MOSI | 11 / ICSP-4 | 51 | D11 | ICSP-4 | 16 | 11 |
+-----------+----------+-------------+---------+---------+---------------+-----------+--------+
| SPI MISO | MISO | 12 / ICSP-1 | 51 | D12 | ICSP-1 | 14 | 12 |
| SPI MISO | MISO | 12 / ICSP-1 | 50 | D12 | ICSP-1 | 14 | 12 |
+-----------+----------+-------------+---------+---------+---------------+-----------+--------+
| SPI SCK | SCK | 13 / ICSP-3 | 50 | D13 | ICSP-3 | 15 | 13 |
| SPI SCK | SCK | 13 / ICSP-3 | 52 | D13 | ICSP-3 | 15 | 13 |
+-----------+----------+-------------+---------+---------+---------------+-----------+--------+
.. [1] Configurable, typically defined as RST_PIN in sketch/program.
@@ -82,13 +82,54 @@ Protocols
2. The reader and the tags communicate using a 13.56 MHz electromagnetic field.
* The protocol is defined in ISO/IEC 14443-3:2011 Part 3.
* The protocol is defined in ISO/IEC 14443-3:2011 Part 3 Type A.
* Details are found in chapter 6 *"Type A Initialization and anticollision"*.
* See http://wg8.de/wg8n1496_17n3613_Ballot_FCD14443-3.pdf for a free version
of the final draft (which might be outdated in some areas).
* The reader do not support ISO/IEC 14443-3 Type B.
Troubleshooting
-------
* **I don't get input from reader** or **WARNING: Communication failure, is the MFRC522 properly connected?**
#. Check your connection, see `Pin Layout`_ .
#. Check voltage. Most breakouts work with 3.3V.
#. The SPI only works with 3.3V, most breakouts seems 5V tollerant, but try a level shifter.
* **Sometimes I get timeouts** or **tag/card sometimes not work.**
#. Try other site of the antenna.
#. Try to decrease distance between MFRC522.
#. Increase antenna gain per firmware: ``mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max);``
#. Use better power supply.
#. Hardware corrupted, most products are from china and sometimes the quality is really low. Contact your seller.
* **My tag/card doesn't work.**
#. Distance between antenna and token too huge (>1cm).
#. You got wrong PICC. Is it really 13.56MGhz? Is it really a Mifare Type A?
#. NFC tokens are not supported. Some may work.
#. Animal marker are not supported. They use other frequency.
#. Hardware corrupted, most products are from china and sometimes the quality is really low. Contact your seller.
* **My mobile phone doesn't recognize the MFRC522** or **my MFRC522 can't read data from other MFRC522**
#. Card simmulation is not supported.
#. Communication with mobile phones is not supported.
#. Peer to peer communication is not supported.
* **I need more features.**
#. If software: code it and make a pull request.
#. If hardware: buy a more expensive like PN532 (supports NFC and many more, but costs about $15)
License
-------

View File

@@ -64,7 +64,7 @@ void loop() {
// Ask personal data: Family name
Serial.println(F("Type Family name, ending with #"));
len=Serial.readBytesUntil('#', (char *) buffer, 30) ; // read family name from serial
for (byte i = len; i < 30; i++) buffer[i] = '\s'; // pad with spaces
for (byte i = len; i < 30; i++) buffer[i] = ' '; // pad with spaces
block = 1;
//Serial.println(F("Authenticating using key A..."));
@@ -106,7 +106,7 @@ void loop() {
// Ask personal data: First name
Serial.println(F("Type First name, ending with #"));
len=Serial.readBytesUntil('#', (char *) buffer, 20) ; // read first name from serial
for (byte i = len; i < 20; i++) buffer[i] = '\s'; // pad with spaces
for (byte i = len; i < 20; i++) buffer[i] = ' '; // pad with spaces
block = 4;
//Serial.println(F("Authenticating using key A..."));

View File

@@ -9,5 +9,5 @@
},
"exclude": "doc",
"frameworks": "arduino",
"platforms": "atmelavr"
"platforms": ["atmelavr", "ststm32"]
}

10
library.properties Normal file
View File

@@ -0,0 +1,10 @@
name=MFRC522
#date as version - no leading zero
version=2015.9.4
author=GithubCommunity
maintainer=miguelbalboa
sentence=Arduino RFID Library for MFRC522 (SPI)
paragraph=Read/Write a RFID Card or Tag using the ISO/IEC 14443A/MIFARE interface.
category=Communication
url=https://github.com/miguelbalboa/rfid
architectures=avr,STM32F1