[英]MFRC522 PICC responded with NAK (Porting MFRC522 arduino library[C++] to [C])
[英]RFID522 Module doesn't work after porting driver from C++ to C
我正在從 Arduino 移植一個用 C++ 編寫的驅動程序並用 C 再次編寫它,以在 PIC16 微控制器上使用它,但它不起作用,不知道為什么,自從我第一次嘗試調試它看已經有幾天了哪里有問題的巴士還趕不上,所以我希望有人能幫助我。 我做了一個測試功能,當它通過這部分代碼時使 LED 變高
if ( !PICC_IsNewCardPresent()){
return;
}
但它永遠不會通過。 我通過 MPLAB IDE 代碼生成器生成了 SPI 代碼。 我沒有使用驅動程序中的所有功能。 我不能在這里包含所有東西,所以這是原始代碼: https : //github.com/miguelbalboa/rfid/tree/master/src
mfrc522.h
#ifndef MFRC522_h
#define MFRC522_h
#include "stdint.h"
#include "string.h"
#include<stdbool.h>
#define nullptr ((void*)0)
#define byte unsigned char
// Size of the MFRC522 FIFO
static byte FIFO_SIZE = 64; // The FIFO is 64 bytes.
// Default value for unused pin
static uint8_t UNUSED_PIN = UINT8_MAX;
typedef enum PCD_Register {
// Page 0: Command and status
// 0x00
CommandReg = 0x01 << 1,
ComIEnReg = 0x02 << 1,
DivIEnReg = 0x03 << 1,
ComIrqReg = 0x04 << 1,
DivIrqReg = 0x05 << 1,
ErrorReg = 0x06 << 1,
Status1Reg = 0x07 << 1,
Status2Reg = 0x08 << 1,
FIFODataReg = 0x09 << 1,
FIFOLevelReg = 0x0A << 1,
WaterLevelReg = 0x0B << 1,
ControlReg = 0x0C << 1,
BitFramingReg = 0x0D << 1,
CollReg = 0x0E << 1,
// 0x0F
// Page 1: Command
// 0x10
ModeReg = 0x11 << 1,
TxModeReg = 0x12 << 1,
RxModeReg = 0x13 << 1,
TxControlReg = 0x14 << 1,
TxASKReg = 0x15 << 1,
TxSelReg = 0x16 << 1,
RxSelReg = 0x17 << 1,
RxThresholdReg = 0x18 << 1,
DemodReg = 0x19 << 1,
// 0x1A
// 0x1B
MfTxReg = 0x1C << 1,
MfRxReg = 0x1D << 1,
// 0x1E
SerialSpeedReg = 0x1F << 1,
// Page 2: Configuration
// 0x20
CRCResultRegH = 0x21 << 1, // shows the MSB and LSB values of the CRC calculation
CRCResultRegL = 0x22 << 1,
// 0x23 // reserved for future use
ModWidthReg = 0x24 << 1, // controls the ModWidth setting?
// 0x25 // reserved for future use
RFCfgReg = 0x26 << 1, // configures the receiver gain
GsNReg = 0x27 << 1, // selects the conductance of the antenna driver pins TX1 and TX2 for modulation
CWGsPReg = 0x28 << 1, // defines the conductance of the p-driver output during periods of no modulation
ModGsPReg = 0x29 << 1, // defines the conductance of the p-driver output during periods of modulation
TModeReg = 0x2A << 1, // defines settings for the internal timer
TPrescalerReg = 0x2B << 1, // the lower 8 bits of the TPrescaler value. The 4 high bits are in TModeReg.
TReloadRegH = 0x2C << 1, // defines the 16-bit timer reload value
TReloadRegL = 0x2D << 1,
TCounterValueRegH = 0x2E << 1, // shows the 16-bit timer value
TCounterValueRegL = 0x2F << 1,
// Page 3: Test Registers
// 0x30 // reserved for future use
TestSel1Reg = 0x31 << 1, // general test signal configuration
TestSel2Reg = 0x32 << 1, // general test signal configuration
TestPinEnReg = 0x33 << 1, // enables pin output driver on pins D1 to D7
TestPinValueReg = 0x34 << 1, // defines the values for D1 to D7 when it is used as an I/O bus
TestBusReg = 0x35 << 1, // shows the status of the internal test bus
AutoTestReg = 0x36 << 1, // controls the digital self-test
VersionReg = 0x37 << 1, // shows the software version
AnalogTestReg = 0x38 << 1, // controls the pins AUX1 and AUX2
TestDAC1Reg = 0x39 << 1, // defines the test value for TestDAC1
TestDAC2Reg = 0x3A << 1, // defines the test value for TestDAC2
TestADCReg = 0x3B << 1 // shows the value of ADC I and Q channels
// 0x3C // reserved for production tests
// 0x3D // reserved for production tests
// 0x3E // reserved for production tests
// 0x3F // reserved for production tests
}PCD_Register;
typedef enum PCD_Command {
PCD_Idle = 0x00, // no action, cancels current command execution
PCD_Mem = 0x01, // stores 25 bytes into the internal buffer
PCD_GenerateRandomID = 0x02, // generates a 10-byte random ID number
PCD_CalcCRC = 0x03, // activates the CRC coprocessor or performs a self-test
PCD_Transmit = 0x04, // transmits data from the FIFO buffer
PCD_NoCmdChange = 0x07, // no command change, can be used to modify the CommandReg register bits without affecting the command, for example, the PowerDown bit
PCD_Receive = 0x08, // activates the receiver circuits
PCD_Transceive = 0x0C, // transmits data from FIFO buffer to antenna and automatically activates the receiver after transmission
PCD_MFAuthent = 0x0E, // performs the MIFARE standard authentication as a reader
PCD_SoftReset = 0x0F // resets the MFRC522
}PCD_Command;
typedef enum PCD_RxGain {
RxGain_18dB = 0x00 << 4, // 000b - 18 dB, minimum
RxGain_23dB = 0x01 << 4, // 001b - 23 dB
RxGain_18dB_2 = 0x02 << 4, // 010b - 18 dB, it seems 010b is a duplicate for 000b
RxGain_23dB_2 = 0x03 << 4, // 011b - 23 dB, it seems 011b is a duplicate for 001b
RxGain_33dB = 0x04 << 4, // 100b - 33 dB, average, and typical default
RxGain_38dB = 0x05 << 4, // 101b - 38 dB
RxGain_43dB = 0x06 << 4, // 110b - 43 dB
RxGain_48dB = 0x07 << 4, // 111b - 48 dB, maximum
RxGain_min = 0x00 << 4, // 000b - 18 dB, minimum, convenience for RxGain_18dB
RxGain_avg = 0x04 << 4, // 100b - 33 dB, average, convenience for RxGain_33dB
RxGain_max = 0x07 << 4 // 111b - 48 dB, maximum, convenience for RxGain_48dB
}PCD_RxGain;
// Commands sent to the PICC.
typedef enum PICC_Command {
// The commands used by the PCD to manage communication with several PICCs (ISO 14443-3, Type A, section 6.4)
PICC_CMD_REQA = 0x26, // REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for anticollision or selection. 7 bit frame.
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 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.
PICC_CMD_RATS = 0xE0, // Request command for Answer To Reset.
// The commands used for MIFARE Classic (from http://www.mouser.com/ds/2/302/MF1S503x-89574.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.
// The read/write commands can also be used for MIFARE Ultralight.
PICC_CMD_MF_AUTH_KEY_A = 0x60, // Perform authentication with Key A
PICC_CMD_MF_AUTH_KEY_B = 0x61, // Perform authentication with Key B
PICC_CMD_MF_READ = 0x30, // Reads one 16 byte block from the authenticated sector of the PICC. Also used for MIFARE Ultralight.
PICC_CMD_MF_WRITE = 0xA0, // Writes one 16 byte block to the authenticated sector of the PICC. Called "COMPATIBILITY WRITE" for MIFARE Ultralight.
PICC_CMD_MF_DECREMENT = 0xC0, // Decrements the contents of a block and stores the result in the internal data register.
PICC_CMD_MF_INCREMENT = 0xC1, // Increments the contents of a block and stores the result in the internal data register.
PICC_CMD_MF_RESTORE = 0xC2, // Reads the contents of a block into the internal data register.
PICC_CMD_MF_TRANSFER = 0xB0, // Writes the contents of the internal data register to a block.
// The commands used for MIFARE Ultralight (from http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf, Section 8.6)
// The PICC_CMD_MF_READ and PICC_CMD_MF_WRITE can also be used for MIFARE Ultralight.
PICC_CMD_UL_WRITE = 0xA2 // Writes one 4 byte page to the PICC.
}PICC_Command;
// MIFARE constants that does not fit anywhere else
typedef enum MIFARE_Misc {
MF_ACK = 0xA, // The MIFARE Classic uses a 4 bit ACK/NAK. Any other value than 0xA is NAK.
MF_KEY_SIZE = 6 // A Mifare Crypto1 key is 6 bytes.
}MIFARE_Misc;
typedef enum StatusCode {
STATUS_OK , // Success
STATUS_ERROR , // Error in communication
STATUS_COLLISION , // Collission detected
STATUS_TIMEOUT , // Timeout in communication.
STATUS_NO_ROOM , // A buffer is not big enough.
STATUS_INTERNAL_ERROR , // Internal error in the code. Should not happen ;-)
STATUS_INVALID , // Invalid argument.
STATUS_CRC_WRONG , // The CRC_A does not match
STATUS_MIFARE_NACK = 0xff // A MIFARE PICC responded with NAK.
}StatusCode;
// A struct used for passing the UID of a PICC.
typedef struct {
byte size; // Number of bytes in the UID. 4, 7 or 10.
byte uidByte[10];
byte sak; // The SAK (Select acknowledge) byte returned from the PICC after successful selection.
} Uid;
// A struct used for passing a MIFARE Crypto1 key
typedef struct {
byte keyByte[MF_KEY_SIZE];
} MIFARE_Key;
// Member variables
Uid uid; // Used by PICC_ReadCardSerial().
void PCD_WriteRegister(PCD_Register reg, byte value);
void PCD_WriteRegister_n(PCD_Register reg, byte count, byte *values);
byte PCD_ReadRegister(PCD_Register reg);
void PCD_ReadRegister_n(PCD_Register reg, byte count, byte *values, byte rxAlign);
void PCD_SetRegisterBitMask(PCD_Register reg, byte mask);
void PCD_ClearRegisterBitMask(PCD_Register reg, byte mask);
StatusCode PCD_CalculateCRC(byte *data, byte length, byte *result);
void PCD_Init(void);
void PCD_Reset(void);
void PCD_AntennaOn(void);
void PCD_AntennaOff(void);
byte PCD_GetAntennaGain(void);
void PCD_SetAntennaGain(byte mask);
StatusCode PCD_TransceiveData(byte *sendData, byte sendLen, byte *backData, byte *backLen, byte *validBits, byte rxAlign, bool checkCRC);
StatusCode PCD_CommunicateWithPICC(byte command, byte waitIRq, byte *sendData, byte sendLen, byte *backData, byte *backLen, byte *validBits, byte rxAlign, bool checkCRC);
StatusCode PICC_RequestA(byte *bufferATQA, byte *bufferSize);
StatusCode PICC_WakeupA(byte *bufferATQA, byte *bufferSize);
StatusCode PICC_REQA_or_WUPA(byte command, byte *bufferATQA, byte *bufferSize);
StatusCode PICC_Select(Uid *uid, byte validBits);
StatusCode PICC_HaltA(void);
StatusCode PCD_Authenticate(byte command, byte blockAddr, MIFARE_Key *key, Uid *uid);
void PCD_StopCrypto1(void);
StatusCode MIFARE_Read(byte blockAddr, byte *buffer, byte *bufferSize);
StatusCode MIFARE_Write(byte blockAddr, byte *buffer, byte bufferSize);
StatusCode PCD_MIFARE_Transceive(byte *sendData, byte sendLen, bool acceptTimeout);
PICC_Type PICC_GetType(byte sak);
// Advanced functions for MIFARE
void MIFARE_SetAccessBits(byte *accessBitBuffer, byte g0, byte g1, byte g2, byte g3);
bool PICC_IsNewCardPresent(void);
bool PICC_ReadCardSerial(void);
#endif
mfrc522.c
#include "mfrc522.h"
#include "spi1.h"
#include "pin_manager.h"
#include "mcc_generated_files/pin_manager.h"
#define _XTAL_FREQ 4000000UL
void PCD_WriteRegister( PCD_Register reg, ///< The register to write to. One of the PCD_Register enums.
byte value ///< The value to write.
) {
//SPI.beginTransaction(SPISettings(MFRC522_SPICLOCK, MSBFIRST, SPI_MODE0)); // Set the settings to work with SPI bus
//digitalWrite(_chipSelectPin, LOW); // Select slave
SLave_Select_SetLow();
//SPI.transfer(reg); // MSB == 0 is for writing. LSB is not used in address. Datasheet section 8.1.2.3.
SPI1_ExchangeByte(reg);
//SPI.transfer(value);
SPI1_ExchangeByte(value);
//digitalWrite(_chipSelectPin, HIGH); // Release slave again
SLave_Select_SetHigh();
//SPI.endTransaction(); // Stop using the SPI bus
} // End PCD_WriteRegister()
void PCD_WriteRegister_n( 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 *values ///< The values to write. Byte array.
) {
SLave_Select_SetLow();
SPI1_ExchangeByte(reg);
for (byte index = 0; index < count; index++) {
SPI1_ExchangeByte(values[index]);
}
SLave_Select_SetHigh();
}
byte PCD_ReadRegister( PCD_Register reg
) {
byte value;
SLave_Select_SetLow();
SPI1_ExchangeByte(0x80 | reg);
value = SPI1_ExchangeByte(0);
SLave_Select_SetHigh();
return value;
}
void PCD_ReadRegister_n( PCD_Register reg,
byte count,
byte *values,
byte rxAlign
) {
if (count == 0) {
return;
}
byte address = 0x80 | reg;
byte index = 0;
SLave_Select_SetLow();
count--;
SPI1_ExchangeByte(address);
if (rxAlign) { // Only update bit positions rxAlign..7 in values[0]
// Create bit mask for bit positions rxAlign..7
byte mask = (0xFF << rxAlign) & 0xFF;
// Read value and tell that we want to read the same address again.
byte value = SPI1_ExchangeByte(address);
// Apply mask to both current value of values[0] and the new data in value.
values[0] = (values[0] & ~mask) | (value & mask);
index++;
}
while (index < count) {
values[index] = SPI1_ExchangeByte(address);
index++;
}
// Release slave again
SLave_Select_SetHigh();
}
void PCD_SetRegisterBitMask( PCD_Register reg,
byte mask
) {
byte tmp;
tmp = PCD_ReadRegister(reg);
PCD_WriteRegister(reg, tmp | mask);
}
void PCD_ClearRegisterBitMask( PCD_Register reg,
byte mask
) {
byte tmp;
tmp = PCD_ReadRegister(reg);
PCD_WriteRegister(reg, tmp & (~mask));
} )
StatusCode PCD_CalculateCRC( byte *data,
byte length,
byte *result
) {
PCD_WriteRegister(CommandReg, PCD_Idle);
PCD_WriteRegister(DivIrqReg, 0x04);
PCD_WriteRegister(FIFOLevelReg, 0x80);
PCD_WriteRegister_n(FIFODataReg, length, data);
PCD_WriteRegister(CommandReg, PCD_CalcCRC);
for (uint16_t i = 5000; i > 0; i--) {
byte n = PCD_ReadRegister(DivIrqReg);
if (n & 0x04) {
PCD_WriteRegister(CommandReg, PCD_Idle); in the FIFO.
// Transfer the result from the registers to the result buffer
result[0] = PCD_ReadRegister(CRCResultRegL);
result[1] = PCD_ReadRegister(CRCResultRegH);
return STATUS_OK;
}
}
// 89ms passed and nothing happend. Communication with the MFRC522 might be down.
return STATUS_TIMEOUT;
}
void PCD_Init(void) {
SLave_Select_SetLow();
PCD_Reset();
// Reset baud rates
PCD_WriteRegister(TxModeReg, 0x00);
PCD_WriteRegister(RxModeReg, 0x00);
// Reset ModWidthReg
PCD_WriteRegister(ModWidthReg, 0x26);
PCD_WriteRegister(TModeReg, 0x80); // TAuto=1; timer starts automatically at the end of the transmission in all communication modes at all speeds
PCD_WriteRegister(TPrescalerReg, 0xA9); // TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25μs.
PCD_WriteRegister(TReloadRegH, 0x03); // Reload timer with 0x3E8 = 1000, ie 25ms before timeout.
PCD_WriteRegister(TReloadRegL, 0xE8);
PCD_WriteRegister(TxASKReg, 0x40); // Default 0x00. Force a 100 % ASK modulation independent of the ModGsPReg register setting
PCD_WriteRegister(ModeReg, 0x3D); // Default 0x3F. Set the preset value for the CRC coprocessor for the CalcCRC command to 0x6363 (ISO 14443-3 part 6.2.4)
PCD_AntennaOn(); // Enable the antenna driver pins TX1 and TX2 (they were disabled by the reset)
}
void PCD_Reset(void) {
PCD_WriteRegister(CommandReg, PCD_SoftReset); // Issue the SoftReset command.
// The datasheet does not mention how long the SoftRest command takes to complete.
// But the MFRC522 might have been in soft power-down mode (triggered by bit 4 of CommandReg)
// Section 8.8.2 in the datasheet says the oscillator start-up time is the start up time of the crystal + 37,74μs. Let us be generous: 50ms.
uint8_t count = 0;
do {
// Wait for the PowerDown bit in CommandReg to be cleared (max 3x50ms)
__delay_ms(50);
} while ((PCD_ReadRegister(CommandReg) & (1 << 4)) && (++count) < 3);
}
void PCD_AntennaOn(void) {
byte value = PCD_ReadRegister(TxControlReg);
if ((value & 0x03) != 0x03) {
PCD_WriteRegister(TxControlReg, value | 0x03);
}
}
void PCD_AntennaOff(void) {
PCD_ClearRegisterBitMask(TxControlReg, 0x03);
}
byte PCD_GetAntennaGain(void) {
return PCD_ReadRegister(RFCfgReg) & (0x07<<4);
}
void PCD_SetAntennaGain(byte mask) {
if (PCD_GetAntennaGain() != mask) { // only bother if there is a change
PCD_ClearRegisterBitMask(RFCfgReg, (0x07<<4)); // clear needed to allow 000 pattern
PCD_SetRegisterBitMask(RFCfgReg, mask & (0x07<<4)); // only set RxGain[2:0] bits
}
}
StatusCode PCD_TransceiveData( byte *sendData, ///< Pointer to the data to transfer to the FIFO.
byte sendLen, ///< Number of bytes to transfer to the FIFO.
byte *backData, ///< nullptr or pointer to buffer if data should be read back after executing the command.
byte *backLen, ///< In: Max number of bytes to write to *backData. Out: The number of bytes returned.
byte *validBits, ///< In/Out: The number of valid bits in the last byte. 0 for 8 valid bits. Default nullptr.
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.
) {
byte waitIRq = 0x30; // RxIRq and IdleIRq
return PCD_CommunicateWithPICC(PCD_Transceive, waitIRq, sendData, sendLen, backData, backLen, validBits, rxAlign, checkCRC);
}
StatusCode PCD_CommunicateWithPICC( byte command, ///< The command to execute. One of the PCD_Command enums.
byte waitIRq, ///< The bits in the ComIrqReg register that signals successful completion of the command.
byte *sendData, ///< Pointer to the data to transfer to the FIFO.
byte sendLen, ///< Number of bytes to transfer to the FIFO.
byte *backData, ///< nullptr or pointer to buffer if data should be read back after executing the command.
byte *backLen, ///< In: Max number of bytes to write to *backData. Out: The number of bytes returned.
byte *validBits, ///< In/Out: The number of valid bits in the last byte. 0 for 8 valid bits.
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.
) {
// Prepare values for BitFramingReg
byte txLastBits = validBits ? *validBits : 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(ComIrqReg, 0x7F); // Clear all seven interrupt request bits
PCD_WriteRegister(FIFOLevelReg, 0x80); // FlushBuffer = 1, FIFO initialization
PCD_WriteRegister_n(FIFODataReg, sendLen, sendData); // Write sendData to the FIFO
PCD_WriteRegister(BitFramingReg, bitFraming); // Bit adjustments
PCD_WriteRegister(CommandReg, command); // Execute the command
if (command == PCD_Transceive) {
PCD_SetRegisterBitMask(BitFramingReg, 0x80); // StartSend=1, transmission of data starts
}
uint16_t i;
for (i = 2000; i > 0; i--) {
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.
break;
}
if (n & 0x01) { // Timer interrupt - nothing received in 25ms
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.
byte errorRegValue = PCD_ReadRegister(ErrorReg); // ErrorReg[7..0] bits are: WrErr TempErr reserved BufferOvfl CollErr CRCErr ParityErr ProtocolErr
if (errorRegValue & 0x13) { // BufferOvfl ParityErr ProtocolErr
return STATUS_ERROR;
}
byte _validBits = 0;
// If the caller wants data back, get it from the MFRC522.
if (backData && backLen) {
byte n = PCD_ReadRegister(FIFOLevelReg); // Number of bytes in the FIFO
if (n > *backLen) {
return STATUS_NO_ROOM;
}
*backLen = n; // Number of bytes returned
PCD_ReadRegister_n(FIFODataReg, n, backData, rxAlign); // Get received data from FIFO
_validBits = PCD_ReadRegister(ControlReg) & 0x07; // RxLastBits[2:0] indicates the number of valid bits in the last received byte. If this value is 000b, the whole byte is valid.
if (validBits) {
*validBits = _validBits;
}
}
// Tell about collisions
if (errorRegValue & 0x08) { // CollErr
return STATUS_COLLISION;
}
// Perform CRC_A validation if requested.
if (backData && backLen && checkCRC) {
// In this case a MIFARE Classic NAK is not OK.
if (*backLen == 1 && _validBits == 4) {
return STATUS_MIFARE_NACK;
}
// We need at least the CRC_A value and all 8 bits of the last byte must be received.
if (*backLen < 2 || _validBits != 0) {
return STATUS_CRC_WRONG;
}
// Verify CRC_A - do our own calculation and store the control in controlBuffer.
byte controlBuffer[2];
StatusCode status = PCD_CalculateCRC(&backData[0], *backLen - 2, &controlBuffer[0]);
if (status != STATUS_OK) {
return status;
}
if ((backData[*backLen - 2] != controlBuffer[0]) || (backData[*backLen - 1] != controlBuffer[1])) {
return STATUS_CRC_WRONG;
}
}
return STATUS_OK;
}
StatusCode PICC_RequestA( byte *bufferATQA, ///< The buffer to store the ATQA (Answer to request) in
byte *bufferSize ///< Buffer size, at least two bytes. Also number of bytes returned if STATUS_OK.
) {
return PICC_REQA_or_WUPA(PICC_CMD_REQA, bufferATQA, bufferSize);
}
StatusCode PICC_WakeupA( byte *bufferATQA, ///< The buffer to store the ATQA (Answer to request) in
byte *bufferSize ///< Buffer size, at least two bytes. Also number of bytes returned if STATUS_OK.
) {
return PICC_REQA_or_WUPA(PICC_CMD_WUPA, bufferATQA, bufferSize);
}
StatusCode PICC_REQA_or_WUPA( byte command, ///< The command to send - PICC_CMD_REQA or PICC_CMD_WUPA
byte *bufferATQA, ///< The buffer to store the ATQA (Answer to request) in
byte *bufferSize ///< Buffer size, at least two bytes. Also number of bytes returned if STATUS_OK.
) {
byte validBits;
StatusCode status;
if (bufferATQA == nullptr || *bufferSize < 2) { // The ATQA response is 2 bytes long.
return STATUS_NO_ROOM;
}
PCD_ClearRegisterBitMask(CollReg, 0x80); // ValuesAfterColl=1 => Bits received after collision are cleared.
validBits = 7; // For REQA and WUPA we need the short frame format - transmit only 7 bits of the last (and only) byte. TxLastBits = BitFramingReg[2..0]
status = PCD_TransceiveData(&command, 1, bufferATQA, bufferSize, &validBits, 0, false);
if (status != STATUS_OK) {
return status;
}
if (*bufferSize != 2 || validBits != 0) { // ATQA must be exactly 16 bits.
return STATUS_ERROR;
}
return STATUS_OK;
}
StatusCode PCD_Authenticate(byte command, ///< PICC_CMD_MF_AUTH_KEY_A or PICC_CMD_MF_AUTH_KEY_B
byte blockAddr, ///< The block number. See numbering in the comments in the .h file.
MIFARE_Key *key, ///< Pointer to the Crypteo1 key to use (6 bytes)
Uid *uid ///< Pointer to Uid struct. The first 4 bytes of the UID is used.
) {
byte waitIRq = 0x10; // IdleIRq
// Build command buffer
byte sendData[12];
sendData[0] = command;
sendData[1] = blockAddr;
for (byte i = 0; i < MF_KEY_SIZE; i++) { // 6 key bytes
sendData[2+i] = key->keyByte[i];
}
for (byte i = 0; i < 4; i++) { // The last 4 bytes of the UID
sendData[8+i] = uid->uidByte[i+uid->size-4];
}
// Start the authentication.
return PCD_CommunicateWithPICC(PCD_MFAuthent, waitIRq, &sendData[0], sizeof(sendData), nullptr, nullptr, nullptr, 0, false);
} // End PCD_Authenticate()
bool PICC_IsNewCardPresent(void) {
byte bufferATQA[2];
byte bufferSize = sizeof(bufferATQA);
// Reset baud rates
PCD_WriteRegister(TxModeReg, 0x00);
PCD_WriteRegister(RxModeReg, 0x00);
// Reset ModWidthReg
PCD_WriteRegister(ModWidthReg, 0x26);
StatusCode result = PICC_RequestA(bufferATQA, &bufferSize);
return (result == STATUS_OK || result == STATUS_COLLISION);
}
主文件
#include "mcc_generated_files/mcc.h"
#include "spi1.h"
#include "mfrc522.h"
#include "pin_manager.h"
#define _XTAL_FREQ 4000000UL
void test(void){
LED_SetHigh();
while(1);
}
MIFARE_Key key;
void main(void)
{
// initialize the device
SYSTEM_Initialize();
PCD_Init();
// Prepare the key (used both as key A and as key B)
// using FFFFFFFFFFFFh which is the default at chip delivery from the factory
for (byte i = 0; i < 6; i++) {
key.keyByte[i] = 0xFF;
}
while (1){
// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
if ( !PICC_IsNewCardPresent()){
return;
}
test();
// Select one of the cards
if ( !PICC_ReadCardSerial()){
return;
}
}
}
確實是硬件的問題,正如我所料,當我查看Arduino的原理圖時,我發現他們將reset按鈕與RF522的reset pin相連,但我的板子中沒有這樣做,但是連接后它在一起,一切正常。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.