Add SPI speed option + Various minor changes (#276)

+ Change default SPI speed to SPI_CLOCK_DIV4
This commit is contained in:
tuyethoa08041997
2017-02-22 21:00:31 +07:00
committed by Rotzbua
parent 5f6c8f9a01
commit 12a00174b5
2 changed files with 66 additions and 70 deletions

View File

@@ -43,12 +43,12 @@ MFRC522::MFRC522( byte chipSelectPin, ///< Arduino pin connected to MFRC522's S
* Writes a byte to the specified register in the MFRC522 chip. * Writes a byte to the specified register in the MFRC522 chip.
* The interface is described in the datasheet section 8.1.2. * The interface is described in the datasheet section 8.1.2.
*/ */
void MFRC522::PCD_WriteRegister( byte reg, ///< The register to write to. One of the PCD_Register enums. void MFRC522::PCD_WriteRegister( PCD_Register reg, ///< The register to write to. One of the PCD_Register enums.
byte value ///< The value to write. byte value ///< The value to write.
) { ) {
SPI.beginTransaction(SPISettings(SPI_CLOCK_DIV4, MSBFIRST, SPI_MODE0)); // Set the settings to work with SPI bus SPI.beginTransaction(SPISettings(MFRC522_SPICLOCK, MSBFIRST, SPI_MODE0)); // Set the settings to work with SPI bus
digitalWrite(_chipSelectPin, LOW); // Select slave digitalWrite(_chipSelectPin, LOW); // Select slave
SPI.transfer(reg & 0x7E); // MSB == 0 is for writing. LSB is not used in address. Datasheet section 8.1.2.3. SPI.transfer(reg); // MSB == 0 is for writing. LSB is not used in address. Datasheet section 8.1.2.3.
SPI.transfer(value); SPI.transfer(value);
digitalWrite(_chipSelectPin, HIGH); // Release slave again digitalWrite(_chipSelectPin, HIGH); // Release slave again
SPI.endTransaction(); // Stop using the SPI bus SPI.endTransaction(); // Stop using the SPI bus
@@ -58,13 +58,13 @@ void MFRC522::PCD_WriteRegister( byte reg, ///< The register to write to. One o
* Writes a number of bytes to the specified register in the MFRC522 chip. * Writes a number of bytes to the specified register in the MFRC522 chip.
* The interface is described in the datasheet section 8.1.2. * The interface is described in the datasheet section 8.1.2.
*/ */
void MFRC522::PCD_WriteRegister( byte reg, ///< The register to write to. One of the PCD_Register enums. void MFRC522::PCD_WriteRegister( PCD_Register reg, ///< The register to write to. One of the PCD_Register enums.
byte count, ///< The number of bytes to write to the register byte count, ///< The number of bytes to write to the register
byte *values ///< The values to write. Byte array. byte *values ///< The values to write. Byte array.
) { ) {
SPI.beginTransaction(SPISettings(SPI_CLOCK_DIV4, MSBFIRST, SPI_MODE0)); // Set the settings to work with SPI bus SPI.beginTransaction(SPISettings(MFRC522_SPICLOCK, MSBFIRST, SPI_MODE0)); // Set the settings to work with SPI bus
digitalWrite(_chipSelectPin, LOW); // Select slave digitalWrite(_chipSelectPin, LOW); // Select slave
SPI.transfer(reg & 0x7E); // MSB == 0 is for writing. LSB is not used in address. Datasheet section 8.1.2.3. SPI.transfer(reg); // MSB == 0 is for writing. LSB is not used in address. Datasheet section 8.1.2.3.
for (byte index = 0; index < count; index++) { for (byte index = 0; index < count; index++) {
SPI.transfer(values[index]); SPI.transfer(values[index]);
} }
@@ -76,12 +76,12 @@ void MFRC522::PCD_WriteRegister( byte reg, ///< The register to write to. One o
* Reads a byte from the specified register in the MFRC522 chip. * Reads a byte from the specified register in the MFRC522 chip.
* The interface is described in the datasheet section 8.1.2. * The interface is described in the datasheet section 8.1.2.
*/ */
byte MFRC522::PCD_ReadRegister( byte reg ///< The register to read from. One of the PCD_Register enums. byte MFRC522::PCD_ReadRegister( PCD_Register reg ///< The register to read from. One of the PCD_Register enums.
) { ) {
byte value; byte value;
SPI.beginTransaction(SPISettings(SPI_CLOCK_DIV4, MSBFIRST, SPI_MODE0)); // Set the settings to work with SPI bus SPI.beginTransaction(SPISettings(MFRC522_SPICLOCK, MSBFIRST, SPI_MODE0)); // Set the settings to work with SPI bus
digitalWrite(_chipSelectPin, LOW); // Select slave digitalWrite(_chipSelectPin, LOW); // Select slave
SPI.transfer(0x80 | (reg & 0x7E)); // MSB == 1 is for reading. LSB is not used in address. Datasheet section 8.1.2.3. SPI.transfer(0x80 | reg); // MSB == 1 is for reading. LSB is not used in address. Datasheet section 8.1.2.3.
value = SPI.transfer(0); // Read the value back. Send 0 to stop reading. value = SPI.transfer(0); // Read the value back. Send 0 to stop reading.
digitalWrite(_chipSelectPin, HIGH); // Release slave again digitalWrite(_chipSelectPin, HIGH); // Release slave again
SPI.endTransaction(); // Stop using the SPI bus SPI.endTransaction(); // Stop using the SPI bus
@@ -92,7 +92,7 @@ byte MFRC522::PCD_ReadRegister( byte reg ///< The register to read from. One of
* Reads a number of bytes from the specified register in the MFRC522 chip. * Reads a number of bytes from the specified register in the MFRC522 chip.
* The interface is described in the datasheet section 8.1.2. * The interface is described in the datasheet section 8.1.2.
*/ */
void MFRC522::PCD_ReadRegister( byte reg, ///< The register to read from. One of the PCD_Register enums. void MFRC522::PCD_ReadRegister( PCD_Register reg, ///< The register to read from. One of the PCD_Register enums.
byte count, ///< The number of bytes to read byte count, ///< The number of bytes to read
byte *values, ///< Byte array to store the values in. byte *values, ///< Byte array to store the values in.
byte rxAlign ///< Only bit positions rxAlign..7 in values[0] are updated. byte rxAlign ///< Only bit positions rxAlign..7 in values[0] are updated.
@@ -101,27 +101,23 @@ void MFRC522::PCD_ReadRegister( byte reg, ///< The register to read from. One o
return; return;
} }
//Serial.print(F("Reading ")); Serial.print(count); Serial.println(F(" 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 address = 0x80 | reg; // MSB == 1 is for reading. LSB is not used in address. Datasheet section 8.1.2.3.
byte index = 0; // Index in values array. byte index = 0; // Index in values array.
SPI.beginTransaction(SPISettings(SPI_CLOCK_DIV4, MSBFIRST, SPI_MODE0)); // Set the settings to work with SPI bus SPI.beginTransaction(SPISettings(MFRC522_SPICLOCK, MSBFIRST, SPI_MODE0)); // Set the settings to work with SPI bus
digitalWrite(_chipSelectPin, LOW); // Select slave digitalWrite(_chipSelectPin, LOW); // Select slave
count--; // One read is performed outside of the loop count--; // One read is performed outside of the loop
SPI.transfer(address); // Tell MFRC522 which address we want to read SPI.transfer(address); // Tell MFRC522 which address we want to read
while (index < count) { if (rxAlign) { // Only update bit positions rxAlign..7 in values[0]
if (index == 0 && rxAlign) { // Only update bit positions rxAlign..7 in values[0]
// Create bit mask for bit positions rxAlign..7 // Create bit mask for bit positions rxAlign..7
byte mask = 0; byte mask = (0xFF << rxAlign) & 0xFF;
for (byte i = rxAlign; i <= 7; i++) {
mask |= (1 << i);
}
// Read value and tell that we want to read the same address again. // Read value and tell that we want to read the same address again.
byte value = SPI.transfer(address); byte value = SPI.transfer(address);
// Apply mask to both current value of values[0] and the new data in value. // Apply mask to both current value of values[0] and the new data in value.
values[0] = (values[index] & ~mask) | (value & mask); values[0] = (values[0] & ~mask) | (value & mask);
index++;
} }
else { // Normal case while (index < count) {
values[index] = SPI.transfer(address); // Read value and tell that we want to read the same address again. values[index] = SPI.transfer(address); // Read value and tell that we want to read the same address again.
}
index++; index++;
} }
values[index] = SPI.transfer(0); // Read the final byte. Send 0 to stop reading. values[index] = SPI.transfer(0); // Read the final byte. Send 0 to stop reading.
@@ -132,7 +128,7 @@ void MFRC522::PCD_ReadRegister( byte reg, ///< The register to read from. One o
/** /**
* Sets the bits given in mask in register reg. * Sets the bits given in mask in register reg.
*/ */
void MFRC522::PCD_SetRegisterBitMask( byte reg, ///< The register to update. One of the PCD_Register enums. void MFRC522::PCD_SetRegisterBitMask( PCD_Register reg, ///< The register to update. One of the PCD_Register enums.
byte mask ///< The bits to set. byte mask ///< The bits to set.
) { ) {
byte tmp; byte tmp;
@@ -143,7 +139,7 @@ void MFRC522::PCD_SetRegisterBitMask( byte reg, ///< The register to update. One
/** /**
* Clears the bits given in mask from register reg. * Clears the bits given in mask from register reg.
*/ */
void MFRC522::PCD_ClearRegisterBitMask( byte reg, ///< The register to update. One of the PCD_Register enums. void MFRC522::PCD_ClearRegisterBitMask( PCD_Register reg, ///< The register to update. One of the PCD_Register enums.
byte mask ///< The bits to clear. byte mask ///< The bits to clear.
) { ) {
byte tmp; byte tmp;
@@ -163,29 +159,27 @@ MFRC522::StatusCode MFRC522::PCD_CalculateCRC( byte *data, ///< In: Pointer to
) { ) {
PCD_WriteRegister(CommandReg, PCD_Idle); // Stop any active command. PCD_WriteRegister(CommandReg, PCD_Idle); // Stop any active command.
PCD_WriteRegister(DivIrqReg, 0x04); // Clear the CRCIRq interrupt request bit PCD_WriteRegister(DivIrqReg, 0x04); // Clear the CRCIRq interrupt request bit
PCD_SetRegisterBitMask(FIFOLevelReg, 0x80); // FlushBuffer = 1, FIFO initialization PCD_WriteRegister(FIFOLevelReg, 0x80); // FlushBuffer = 1, FIFO initialization
PCD_WriteRegister(FIFODataReg, length, data); // Write data to the FIFO PCD_WriteRegister(FIFODataReg, length, data); // Write data to the FIFO
PCD_WriteRegister(CommandReg, PCD_CalcCRC); // Start the calculation PCD_WriteRegister(CommandReg, PCD_CalcCRC); // Start the calculation
// Wait for the CRC calculation to complete. Each iteration of the while-loop takes 17.73μs. // Wait for the CRC calculation to complete. Each iteration of the while-loop takes 17.73μs.
// TODO check/modify for other architectures than Arduino Uno 16bit // TODO check/modify for other architectures than Arduino Uno 16bit
uint16_t i = 5000;
byte n;
while (1) {
n = PCD_ReadRegister(DivIrqReg); // DivIrqReg[7..0] bits are: Set2 reserved reserved MfinActIRq reserved CRCIRq reserved reserved
if (n & 0x04) { // CRCIRq bit set - calculation done
break;
}
if (--i == 0) { // The emergency break. We will eventually terminate on this one after 89ms. Communication with the MFRC522 might be down.
return STATUS_TIMEOUT;
}
}
PCD_WriteRegister(CommandReg, PCD_Idle); // Stop calculating CRC for new content in the FIFO.
// Wait for the CRC calculation to complete. Each iteration of the while-loop takes 17.73us.
for (uint16_t i = 5000; i > 0; i--) {
// DivIrqReg[7..0] bits are: Set2 reserved reserved MfinActIRq reserved CRCIRq reserved reserved
byte n = PCD_ReadRegister(DivIrqReg);
if (n & 0x04) { // CRCIRq bit set - calculation done
PCD_WriteRegister(CommandReg, PCD_Idle); // Stop calculating CRC for new content in the FIFO.
// Transfer the result from the registers to the result buffer // Transfer the result from the registers to the result buffer
result[0] = PCD_ReadRegister(CRCResultRegL); result[0] = PCD_ReadRegister(CRCResultRegL);
result[1] = PCD_ReadRegister(CRCResultRegH); result[1] = PCD_ReadRegister(CRCResultRegH);
return STATUS_OK; return STATUS_OK;
}
}
// 89ms passed and nothing happend. Communication with the MFRC522 might be down.
return STATUS_TIMEOUT;
} // End PCD_CalculateCRC() } // End PCD_CalculateCRC()
@@ -315,7 +309,7 @@ bool MFRC522::PCD_PerformSelfTest() {
// 2. Clear the internal buffer by writing 25 bytes of 00h // 2. Clear the internal buffer by writing 25 bytes of 00h
byte ZEROES[25] = {0x00}; byte ZEROES[25] = {0x00};
PCD_SetRegisterBitMask(FIFOLevelReg, 0x80); // flush the FIFO buffer PCD_WriteRegister(FIFOLevelReg, 0x80); // flush the FIFO buffer
PCD_WriteRegister(FIFODataReg, 25, ZEROES); // write 25 bytes of 00h to FIFO PCD_WriteRegister(FIFODataReg, 25, ZEROES); // write 25 bytes of 00h to FIFO
PCD_WriteRegister(CommandReg, PCD_Mem); // transfer to internal buffer PCD_WriteRegister(CommandReg, PCD_Mem); // transfer to internal buffer
@@ -424,16 +418,13 @@ MFRC522::StatusCode MFRC522::PCD_CommunicateWithPICC( byte command, ///< The co
byte rxAlign, ///< In: Defines the bit position in backData[0] for the first bit received. Default 0. byte rxAlign, ///< In: Defines the bit position in backData[0] for the first bit received. Default 0.
bool checkCRC ///< In: True => The last two bytes of the response is assumed to be a CRC_A that must be validated. bool checkCRC ///< In: True => The last two bytes of the response is assumed to be a CRC_A that must be validated.
) { ) {
byte n, _validBits;
uint16_t i;
// Prepare values for BitFramingReg // Prepare values for BitFramingReg
byte txLastBits = validBits ? *validBits : 0; byte txLastBits = validBits ? *validBits : 0;
byte bitFraming = (rxAlign << 4) + txLastBits; // RxAlign = BitFramingReg[6..4]. TxLastBits = BitFramingReg[2..0] byte bitFraming = (rxAlign << 4) + txLastBits; // RxAlign = BitFramingReg[6..4]. TxLastBits = BitFramingReg[2..0]
PCD_WriteRegister(CommandReg, PCD_Idle); // Stop any active command. PCD_WriteRegister(CommandReg, PCD_Idle); // Stop any active command.
PCD_WriteRegister(ComIrqReg, 0x7F); // Clear all seven interrupt request bits PCD_WriteRegister(ComIrqReg, 0x7F); // Clear all seven interrupt request bits
PCD_SetRegisterBitMask(FIFOLevelReg, 0x80); // FlushBuffer = 1, FIFO initialization PCD_WriteRegister(FIFOLevelReg, 0x80); // FlushBuffer = 1, FIFO initialization
PCD_WriteRegister(FIFODataReg, sendLen, sendData); // Write sendData to the FIFO PCD_WriteRegister(FIFODataReg, sendLen, sendData); // Write sendData to the FIFO
PCD_WriteRegister(BitFramingReg, bitFraming); // Bit adjustments PCD_WriteRegister(BitFramingReg, bitFraming); // Bit adjustments
PCD_WriteRegister(CommandReg, command); // Execute the command PCD_WriteRegister(CommandReg, command); // Execute the command
@@ -445,18 +436,19 @@ MFRC522::StatusCode MFRC522::PCD_CommunicateWithPICC( byte command, ///< The co
// In PCD_Init() we set the TAuto flag in TModeReg. This means the timer automatically starts when the PCD stops transmitting. // In PCD_Init() we set the TAuto flag in TModeReg. This means the timer automatically starts when the PCD stops transmitting.
// Each iteration of the do-while-loop takes 17.86μs. // Each iteration of the do-while-loop takes 17.86μs.
// TODO check/modify for other architectures than Arduino Uno 16bit // TODO check/modify for other architectures than Arduino Uno 16bit
i = 2000; uint16_t i;
while (1) { for (i = 2000; i > 0; i--) {
n = PCD_ReadRegister(ComIrqReg); // ComIrqReg[7..0] bits are: Set1 TxIRq RxIRq IdleIRq HiAlertIRq LoAlertIRq ErrIRq TimerIRq byte n = PCD_ReadRegister(ComIrqReg); // ComIrqReg[7..0] bits are: Set1 TxIRq RxIRq IdleIRq HiAlertIRq LoAlertIRq ErrIRq TimerIRq
if (n & waitIRq) { // One of the interrupts that signal success has been set. if (n & waitIRq) { // One of the interrupts that signal success has been set.
break; break;
} }
if (n & 0x01) { // Timer interrupt - nothing received in 25ms if (n & 0x01) { // Timer interrupt - nothing received in 25ms
return STATUS_TIMEOUT; return STATUS_TIMEOUT;
} }
if (--i == 0) { // The emergency break. If all other conditions fail we will eventually terminate on this one after 35.7ms. Communication with the MFRC522 might be down.
return STATUS_TIMEOUT;
} }
// 35.7ms and nothing happend. Communication with the MFRC522 might be down.
if (i == 0) {
return STATUS_TIMEOUT;
} }
// Stop now if any errors except collisions were detected. // Stop now if any errors except collisions were detected.
@@ -465,9 +457,11 @@ MFRC522::StatusCode MFRC522::PCD_CommunicateWithPICC( byte command, ///< The co
return STATUS_ERROR; return STATUS_ERROR;
} }
byte _validBits;
// If the caller wants data back, get it from the MFRC522. // If the caller wants data back, get it from the MFRC522.
if (backData && backLen) { if (backData && backLen) {
n = PCD_ReadRegister(FIFOLevelReg); // Number of bytes in the FIFO byte n = PCD_ReadRegister(FIFOLevelReg); // Number of bytes in the FIFO
if (n > *backLen) { if (n > *backLen) {
return STATUS_NO_ROOM; return STATUS_NO_ROOM;
} }

View File

@@ -78,6 +78,8 @@
#include <Arduino.h> #include <Arduino.h>
#include <SPI.h> #include <SPI.h>
#define MFRC522_SPICLOCK SPI_CLOCK_DIV4 // MFRC522 accept upto 10MHz
// Firmware data for self-test // Firmware data for self-test
// Reference values based on firmware version // Reference values based on firmware version
// Hint: if needed, you can remove unused self-test data to save flash memory // Hint: if needed, you can remove unused self-test data to save flash memory
@@ -328,13 +330,13 @@ public:
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
// Basic interface functions for communicating with the MFRC522 // Basic interface functions for communicating with the MFRC522
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
void PCD_WriteRegister(byte reg, byte value); void PCD_WriteRegister(PCD_Register reg, byte value);
void PCD_WriteRegister(byte reg, byte count, byte *values); void PCD_WriteRegister(PCD_Register reg, byte count, byte *values);
byte PCD_ReadRegister(byte reg); byte PCD_ReadRegister(PCD_Register reg);
void PCD_ReadRegister(byte reg, byte count, byte *values, byte rxAlign = 0); void PCD_ReadRegister(PCD_Register reg, byte count, byte *values, byte rxAlign = 0);
void setBitMask(unsigned char reg, unsigned char mask); void setBitMask(unsigned char reg, unsigned char mask);
void PCD_SetRegisterBitMask(byte reg, byte mask); void PCD_SetRegisterBitMask(PCD_Register reg, byte mask);
void PCD_ClearRegisterBitMask(byte reg, byte mask); void PCD_ClearRegisterBitMask(PCD_Register reg, byte mask);
StatusCode PCD_CalculateCRC(byte *data, byte length, byte *result); StatusCode PCD_CalculateCRC(byte *data, byte length, byte *result);
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////