I've got the MFRC522 (datasheet here) RFID module and Nucleo board (F411RE). I've tried to find a library for this module which would be made for STM32 but I haven't been successful. I've found few but neither of them worked. (It didn't even compile and fixing the errors just made it even worse...) So I decided to port the standard Arduino library (source code here) which I know is working fine to STM32. I've removed all the calls for Serial functions and I've rewritten the SPI write and read methods to use HAL instead of Arduino's SPI class.
void MFRC522::PCD_WriteRegister(PCD_Register reg, uint8_t value) {
HAL_GPIO_WritePin(csPort, csPin, GPIO_PIN_RESET);
HAL_SPI_Transmit(readers[reader], (uint8_t*)®, 1, 100);
HAL_SPI_Transmit(readers[reader], &value, 1, 100);
HAL_GPIO_WritePin(csPort, csPin, GPIO_PIN_SET);
}
uint8_t MFRC522::PCD_ReadRegister(PCD_Register reg) {
uint8_t data;
uint8_t zero = 0x00;
uint8_t addr = 0x80 | reg;
HAL_GPIO_WritePin(csPort, csPin, GPIO_PIN_RESET);
HAL_SPI_Transmit(readers[reader], &addr, 1, 100);
HAL_SPI_TransmitReceive(readers[reader], &zero, &data, 1, 100);
HAL_GPIO_WritePin(csPort, csPin, GPIO_PIN_SET);
return data;
}
I'm using this code to read the card:
bool readID() {
if (!rfid.PICC_IsNewCardPresent()) {
return false;
}
if (!rfid.PICC_ReadCardSerial()) {
return false;
}
for (int i = 0; i < 4; i++) {
lastId[i] = rfid.uid.uidByte[i];
}
rfid.PICC_HaltA();
return true;
}
But the problem is, that PICC_IsNewCardPresent() method always returns false. Using the debugger I've managed to find out that the problem is PCD_CommunicateWithPICC method:
uint16_t i;
for (i = 2000; i > 0; i--) {
uint8_t n = PCD_ReadRegister(ComIrqReg); // ComIrqReg[7..0] bits are: Set1 TxIRq RxIRq IdleIRq HiAlertIRq LoAlertIRq ErrIRq TimerIRq
if (n & waitIRq/*constant 0x30*/) { // One of the interrupts that signal success has been set.
break;
}
if (n & 0x01) { // Timer interrupt - nothing received in 25ms
return STATUS_TIMEOUT;
}
}
Which alwais ends at
return STATUS_TIMEOUT;
the loop does not even run second time... I've captured reading the ComIrqReg register on my oscilloscope, the STM32 sent 0x88 which corresponds with the read ComIrqReg request and the IC responded with 0x45. I checked the n variable value in the debugger and it also read the 0x45, so my read method is probably not the issue.
Picture of the captured communication
I've also looked at the initialization of the module and I've checked few of the bytes if they correspond with the bytes that should have been sent and it also looks fine to me.
Picture of the captured initialization
The read value of 0x45 is 0b01000101, which means n&0x01 is 0b1 eg. true and it returns STATUS_TIMEOUT... I need to have the 5th or 6th LSB true.
Do you have any idea, why the module always returns the 0x45 value? I can't think of anything... The module is 100% working (confirmed with Arduino) so the problem has to be in the STM32 part. What would you try?
Thanks for any help!