Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Need an example to read rfid card from MFRC522 rfid scanner using spi protocol and correct reply this time

Hi,

I am also facing same issue i am able to read the version register correctly and able to perform self test successfully

I am using 17.1.0n RF5  SDK

 I am using SPI Master Example 

https://devzone.nordicsemi.com/f/nordic-q-a/55860/need-mfrc522-c-library-for-nrf52833   

Here is the link to same devzone ticket i am getting the same issue in that ticket and cannot able to solve the same please provide me some example to detect and read rfid cards that i am not able to do.

ticket no -241550,

    I am not sure that it has done caning because that is the issue it is giving me communication error not bale to solve by me.Please check and do the needful 

I am   developing NRF52832 DK. in Linux ubuntu OS and my board is PC10040

I'm building library C SPI mfrc522 for NRF52832.
I'm implement PCD_Read and write PCD_register look OK, But i call function PICC_IsNewCardPresent()  in main loop not detected NFC tag, in debug terminal it is coming Timeoout in communication" error

my main file

#include "nrf_drv_spi.h"
#include "app_util_platform.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "boards.h"
#include "app_error.h"
#include <string.h>
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "mfrc522.h"




#define SPI_INSTANCE  0 /**< SPI instance index. */
static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */
static volatile bool spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */

#define TEST_STRING "Nordic"
static uint8_t       m_tx_buf[2];//   /**< TX buffer. */
static uint8_t       m_rx_buf[1];    /**< RX buffer. */
static uint8_t       m_write_buf[1];    /**< RX buffer. */
static const uint8_t m_length = 1;        /**< Transfer length. */
static const uint8_t m_tx_length = 2;        /**< Transfer length. */
/**
 * @brief SPI user event handler.
 * @param event
 */


void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                       void *                    p_context)
{

    spi_xfer_done = true;
 #if 0    
    NRF_LOG_INFO("Transfer completed.");

   
    if (m_rx_buf[0] != 0)
    {
        NRF_LOG_INFO(" Received:");
        NRF_LOG_HEXDUMP_INFO(m_rx_buf, strlen((const char *)m_rx_buf));
    }
    
#endif
}



int main(void)
{
    bsp_board_init(BSP_INIT_LEDS);

    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

#if 0
    nrf_gpio_cfg_output(SPI_SS_PIN);
    nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
    spi_config.ss_pin   = SPI_SS_PIN;
    spi_config.miso_pin = SPI_MISO_PIN;
    spi_config.mosi_pin = SPI_MOSI_PIN;
    spi_config.sck_pin  = SPI_SCK_PIN;
    APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));
#endif
   
    NRF_LOG_INFO("SPI example started.");
    mfrc522_init();
    //PCD_PerformSelfTest();
    //PCD_Reset();


    while (1)
    {
        // Reset rx buffer and transfer done flag
        memset(m_rx_buf, 0, m_length);
        spi_xfer_done = false;

        APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, m_length, m_rx_buf, m_length));

        PICC_IsNewCardPresent();
      
      
    #if  0
        while (!spi_xfer_done)
        {
            __WFE();
        }

        NRF_LOG_FLUSH();
   #endif
        bsp_board_led_invert(BSP_BOARD_LED_0);
        nrf_delay_ms(200);
    }
}

my output when i debug in debug terminal :---(error)

<info> app: SPI example started.
<info> app: version:F
<info> app: TModeReg:80
<info> app: TPrescalerReg:A9
<info> app: TPrescalerReg:A9
<info> app: STATUS_TIMEOUT2
<info> app: result:3               
<info> app: STATUS_TIMEOUT2
<info> app: result:3

i have used the above attched library please check on mfrc522.c and mfrc522.h files for any quries

I am getting "Timeoout in communication" error even though i have placed the rfid id card continously on the scanner                                                                                                     #define STATUS_OK (0x00)// Success
#define STATUS_ERROR (0x01)// Error in communication
#define STATUS_COLLISION (0x02)// Collission detected
#define STATUS_TIMEOUT (0x03)// Timeout in communication.  ---i am getting this status as per my .h file   in my library.

PLEASE anyone help me out i  have been working on the same from past two weeks i have checked the hardware functionalities of the MFRC522 it is in working condition and i am having 2 rfid scanners in both also same issue please help me out..

If possible share the complete code to just read the cards iit will be helpful.

These are the libraries which i am using .h and .c files  

#include "mfrc522.h"
#define debug_info(...) NRF_LOG_INFO(__VA_ARGS__) 
#define SPI_INSTANCE  0 /**< SPI instance index. */
static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */
static volatile bool spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */


static uint8_t       m_tx_buf[2];// = TEST_STRING;           /**< TX buffer. */
static uint8_t       m_rx_buf[1];    /**< RX buffer. */
static uint8_t       m_write_buf[1];    /**< RX buffer. */
static const uint8_t m_length = 1;        /**< Transfer length. */
static const uint8_t m_tx_length = 2;        /**< Transfer length. */
/**
 * @brief SPI user event handler.
 * @param event
 */
void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                       void *                    p_context)
{
    spi_xfer_done = true;
//    NRF_LOG_INFO("Transfer completed.");
//    if (m_rx_buf[0] != 0)
//    {
//        NRF_LOG_INFO(" Received:");
//        NRF_LOG_HEXDUMP_INFO(m_rx_buf,1);
//    }
}
void PCD_WriteRegister(PCD_Register reg, byte value){
        nrf_gpio_pin_write(SPI_SS_PIN,0); 
        m_tx_buf[0] = reg &0x7E;
        m_tx_buf[1] = value;
        memset(m_rx_buf, 0, m_length);
        spi_xfer_done = false;

        nrf_drv_spi_transfer(&spi,&m_tx_buf[0], m_length, NULL, 0);

        while (!spi_xfer_done)
        {
            __WFE();
        }
        NRF_LOG_FLUSH();

//        m_tx_buf[1] = value;
//	memset(m_rx_buf, 0, m_length);
//        spi_xfer_done = false;
//
//        nrf_drv_spi_transfer(&spi, &m_tx_buf[1], m_length, NULL, 0);
//
//        while (!spi_xfer_done)
//        {
//            __WFE();
//        }
//        NRF_LOG_FLUSH();
//          byte cpm =  PCD_ReadRegister(reg);
//          if(cpm!=value) debug_info("WTF %x: %x - %x",reg>>1,cpm,value);
        nrf_gpio_pin_write(SPI_SS_PIN,1);
}
void PCD_WriteRegister_long(PCD_Register reg, byte count, byte *values){
		nrf_gpio_pin_write(SPI_SS_PIN,0);
        m_tx_buf[0] = reg & 0x7E;
        memset(m_rx_buf, 0, m_length);
        spi_xfer_done = false;

        nrf_drv_spi_transfer(&spi,&m_tx_buf[0], m_length, NULL, 0);

        while (!spi_xfer_done)
        {
            __WFE();
        }
        NRF_LOG_FLUSH();

	for (byte index = 0; index < count; index++) {
	  memset(m_rx_buf, 0, m_length);
          spi_xfer_done = false;
          nrf_drv_spi_transfer(&spi, &values[index], m_length, NULL, 0);
          while (!spi_xfer_done)
          {
              __WFE();
          }
          NRF_LOG_FLUSH();
	}

nrf_gpio_pin_write(SPI_SS_PIN,1);
}
byte PCD_ReadRegister(PCD_Register reg){
        nrf_gpio_pin_write(SPI_SS_PIN,0);
        
        m_tx_buf[0] = (0x80 | (reg & 0x7E));
        memset(m_rx_buf, 0, m_length);
        spi_xfer_done = false;
    
        nrf_drv_spi_transfer(&spi,&m_tx_buf[0], m_length, m_rx_buf, m_length);

        while (!spi_xfer_done)
        {
            __WFE();
        }
        memset(m_rx_buf, 0, m_length);
        spi_xfer_done = false;
        uint8_t _reg; 
        _reg = 0x00;
        nrf_drv_spi_transfer(&spi,&_reg, m_length, m_rx_buf, m_length);

        while (!spi_xfer_done)
        {
            __WFE();
        }
        NRF_LOG_FLUSH();
        nrf_gpio_pin_write(SPI_SS_PIN,1);
        return m_rx_buf[0];

}
void PCD_ReadRegister_long(PCD_Register reg, byte count, byte *values, byte rxAlign){
 nrf_gpio_pin_write(SPI_SS_PIN,0);
	if (count == 0) {
		return;
	}
        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;	
        count--;

        memset(m_rx_buf, 0, m_length);
        spi_xfer_done = false;
    
        nrf_drv_spi_transfer(&spi,&address, m_length, m_rx_buf, m_length);

        while (!spi_xfer_done)
        {
            __WFE();
        }
        NRF_LOG_FLUSH();

        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.
        memset(m_rx_buf, 0, m_length);
        spi_xfer_done = false;

        nrf_drv_spi_transfer(&spi,&address, m_length, m_rx_buf, m_length);

        while (!spi_xfer_done)
        {
          __WFE();
        }
        byte value = m_rx_buf[0];
		// 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) {
        memset(m_rx_buf, 0, m_length);
        spi_xfer_done = false;

        nrf_drv_spi_transfer(&spi,&address, m_length, m_rx_buf, m_length);

        while (!spi_xfer_done)
        {
          __WFE();
        }
        values[index] = m_rx_buf[0];
        index++;
	}
        memset(m_rx_buf, 0, m_length);
        spi_xfer_done = false;
        uint8_t _reg = 0x00;
        nrf_drv_spi_transfer(&spi,&_reg, m_length, m_rx_buf, m_length);

        while (!spi_xfer_done)
        {
          __WFE();
        }
        values[index] = m_rx_buf[0];
nrf_gpio_pin_write(SPI_SS_PIN,1);
}
void PCD_ClearRegisterBitMask(	PCD_Register reg,	///< The register to update. One of the PCD_Register enums.
				byte mask			///< The bits to clear.
									  ) {
	byte tmp;
	tmp = PCD_ReadRegister(reg);
	PCD_WriteRegister(reg, tmp & (~mask));		// clear bit mask
} // End PCD_ClearRegisterBitMask()
void PCD_SetRegisterBitMask(	PCD_Register reg,	///< The register to update. One of the PCD_Register enums.
				byte mask			///< The bits to set.
									) { 
	byte tmp;
	tmp = PCD_ReadRegister(reg);
	PCD_WriteRegister(reg, tmp | mask);			// set bit mask

} // End PCD_SetRegisterBitMask()
StatusCode PCD_CalculateCRC(	byte *data,		///< In: Pointer to the data to transfer to the FIFO for CRC calculation.
                                byte length,	///< In: The number of bytes to transfer.
                                byte *result	///< Out: Pointer to result buffer. Result is written to result[0..1], low byte first.
) {
	PCD_WriteRegister(CommandReg, PCD_Idle);		// Stop any active command.
	PCD_WriteRegister(DivIrqReg, 0x04);				// Clear the CRCIRq interrupt request bit
	PCD_WriteRegister(FIFOLevelReg, 0x80);			// FlushBuffer = 1, FIFO initialization
	PCD_WriteRegister_long(FIFODataReg, length, data);	// Write data to the FIFO
	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.
	// TODO check/modify for other architectures than Arduino Uno 16bit

	// 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
			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;
} // End PCD_CalculateCRC()

void PCD_AntennaOn() {
	uint8_t value = PCD_ReadRegister(TxControlReg);
	if ((value & 0x03) != 0x03) {
		PCD_WriteRegister(TxControlReg, value | 0x03);
                value = PCD_ReadRegister(TxControlReg);
	}
} // End PCD_AntennaOn()
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);
} // End PICC_RequestA()
void printf_value(uint8_t count, uint8_t *values){
    for (uint8_t index = 0; index < count; index++) {
        debug_info("%p - %x\n",&values[index],values[index]);
    }
}
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.
	byte mcmd = PCD_ReadRegister(CommandReg);
        PCD_WriteRegister(ComIrqReg, 0x7F);					// Clear all seven interrupt request bits
        PCD_WriteRegister(FIFOLevelReg, 0x80);				// FlushBuffer = 1, FIFO initialization
        PCD_WriteRegister_long(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
	}
	
	// Wait for the command to complete.
	// 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.
	// TODO check/modify for other architectures than Arduino Uno 16bit
	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
//		debug_info("n:%x",n);
                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) {
        debug_info("STATUS_TIMEOUT2");
		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_long(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;
} // End PCD_CommunicateWithPICC()
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);
} // End PCD_TransceiveData()
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 == NULL || *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;
} // End PICC_REQA_or_WUPA()
 
bool PICC_IsNewCardPresent() {
	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);
    debug_info("result:%x",result);
	return (result == STATUS_OK || result == STATUS_COLLISION);
} // End PICC_IsNewCardPresent()
void PCD_Reset() {
	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)
		nrf_delay_ms(50);
	} while ((PCD_ReadRegister(CommandReg) & (1 << 4)) && (++count) < 3);
} // End PCD_Reset()
#define pgm_read_byte(addr)   (*(const unsigned char *)(addr))
bool PCD_PerformSelfTest() {
	// This follows directly the steps outlined in 16.1.1
	// 1. Perform a soft reset.
	PCD_Reset();
	
	// 2. Clear the internal buffer by writing 25 bytes of 00h
	byte ZEROES[25] = {0x00};
	PCD_WriteRegister(FIFOLevelReg, 0x80);		// flush the FIFO buffer

	PCD_WriteRegister_long(FIFODataReg, 25, ZEROES);	// write 25 bytes of 00h to FIFO

	PCD_WriteRegister(CommandReg, PCD_Mem);		// transfer to internal buffer
	
	// 3. Enable self-test
	PCD_WriteRegister(AutoTestReg, 0x09);
	
	// 4. Write 00h to FIFO buffer
	PCD_WriteRegister(FIFODataReg, 0x00);
	
	// 5. Start self-test by issuing the CalcCRC command
	PCD_WriteRegister(CommandReg, PCD_CalcCRC);
	
	// 6. Wait for self-test to complete
	byte n;
	for (uint8_t i = 0; i < 0xFF; i++) {
		// The datasheet does not specify exact completion condition except
		// that FIFO buffer should contain 64 bytes.
		// While selftest is initiated by CalcCRC command
		// it behaves differently from normal CRC computation,
		// so one can't reliably use DivIrqReg to check for completion.
		// It is reported that some devices does not trigger CRCIRq flag
		// during selftest.
		n = PCD_ReadRegister(FIFOLevelReg);
		if (n >= 64) {
                debug_info("nnn:%x",n);
                NRF_LOG_FLUSH();
			break;
		}
	}
	PCD_WriteRegister(CommandReg, PCD_Idle);		// Stop calculating CRC for new content in the FIFO.
	
	// 7. Read out resulting 64 bytes from the FIFO buffer.
	byte result[64];
	PCD_ReadRegister_long(FIFODataReg, 64, result, 0);
	
	// Auto self-test done
	// Reset AutoTestReg register to be 0 again. Required for normal operation.
	PCD_WriteRegister(AutoTestReg, 0x00);
	
	// Determine firmware version (see section 9.3.4.8 in spec)
	byte version = PCD_ReadRegister(VersionReg);
	
	// Pick the appropriate reference values
	const byte *reference;
	debug_info("version:%x",version);
	
	// Verify that the results match up to our expectations
	for (uint8_t i = 0; i < 64; i++) {
debug_info("result[%d]:%x",i,result[i]);
NRF_LOG_FLUSH();
//		if (result[i] != pgm_read_byte(&(reference[i]))) {
//			return false;
//		}
	}
	debug_info("Test passed; all is good");
	// Test passed; all is good.
	return true;
} // End PCD_PerformSelfTest()
void mfrc522_init()
{
      nrf_gpio_cfg_output(SPI_SS_PIN);
      nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
      spi_config.ss_pin   = SPI_SS_PIN;
      spi_config.miso_pin = SPI_MISO_PIN;
      spi_config.mosi_pin = SPI_MOSI_PIN;
      spi_config.sck_pin  = SPI_SCK_PIN;
      APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));
        PCD_Reset();
      uint8_t v = PCD_ReadRegister(VersionReg);
      NRF_LOG_INFO("version:%x",v);
	// Reset baud rates
	PCD_WriteRegister(TxModeReg, 0x00);
	PCD_WriteRegister(RxModeReg, 0x00);
	// Reset ModWidthReg
	PCD_WriteRegister(ModWidthReg, 0x26);
	// When communicating with a PICC we need a timeout if something goes wrong.
	// f_timer = 13.56 MHz / (2*TPreScaler+1) where TPreScaler = [TPrescaler_Hi:TPrescaler_Lo].
	// TPrescaler_Hi are the four low bits in TModeReg. TPrescaler_Lo is TPrescalerReg.
	PCD_WriteRegister(TModeReg, 0x80);			// TAuto=1; timer starts automatically at the end of the transmission in all communication modes at all speeds
	v=PCD_ReadRegister(TModeReg);
    NRF_LOG_INFO("TModeReg:%x",v);
    PCD_WriteRegister(TPrescalerReg, 0xA9);		// TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25μs.
	v=PCD_ReadRegister(TPrescalerReg);
    NRF_LOG_INFO("TPrescalerReg:%x",v);
    PCD_WriteRegister(TPrescalerReg, 0xA9);		// TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25μs.
	v=PCD_ReadRegister(TPrescalerReg);
    NRF_LOG_INFO("TPrescalerReg:%x",v); 
    PCD_WriteRegister(TReloadRegH, 0x04);		// 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  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();
    NRF_LOG_FLUSH();
}

mfrc522.c

#include "nrf_drv_spi.h"
#include "app_error.h"
#include <string.h>
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "nrf_delay.h"
#include "nrf_gpio.h"
typedef uint8_t byte;
typedef uint8_t PCD_Register;
typedef uint8_t PCD_Command;
typedef uint8_t PCD_RxGain;
typedef uint8_t PICC_Command;
typedef uint8_t PICC_Type;
typedef uint8_t StatusCode;
typedef uint8_t MIFARE_Misc; 
		// Page 0: Command and status
		//						  0x00			// reserved for future use
#define		CommandReg				(0x01 << 1)// starts and stops command execution
#define		ComIEnReg				(0x02 << 1)// enable and disable interrupt request control bits
#define		DivIEnReg				(0x03 << 1)// enable and disable interrupt request control bits
#define		ComIrqReg				(0x04 << 1)// interrupt request bits
#define		DivIrqReg				(0x05 << 1)// interrupt request bits
#define		ErrorReg				(0x06 << 1)// error bits showing the error status of the last command executed 
#define		Status1Reg				(0x07 << 1)// communication status bits
#define		Status2Reg				(0x08 << 1)// receiver and transmitter status bits
#define		FIFODataReg				(0x09 << 1)// input and output of 64 byte FIFO buffer
#define		FIFOLevelReg                            (0x0A << 1)// number of bytes stored in the FIFO buffer
#define		WaterLevelReg                           (0x0B << 1)// level for FIFO underflow and overflow warning
#define		ControlReg				(0x0C << 1)// miscellaneous control registers
#define		BitFramingReg                           (0x0D << 1)// adjustments for bit-oriented frames
#define		CollReg					(0x0E << 1)// bit position of the first bit-collision detected on the RF interface
		//						  0x0F			// reserved for future use
		
		// Page 1: Command
		// 						  0x10			// reserved for future use
#define		ModeReg					(0x11 << 1)// defines general modes for transmitting and receiving 
#define		TxModeReg				(0x12 << 1)// defines transmission data rate and framing
#define		RxModeReg				(0x13 << 1)// defines reception data rate and framing
#define		TxControlReg                            (0x14 << 1)// controls the logical behavior of the antenna driver pins TX1 and TX2
#define		TxASKReg				(0x15 << 1)// controls the setting of the transmission modulation
#define		TxSelReg				(0x16 << 1)// selects the internal sources for the antenna driver
#define		RxSelReg				(0x17 << 1)// selects internal receiver settings
#define		RxThresholdReg                          (0x18 << 1)// selects thresholds for the bit decoder
#define		DemodReg				(0x19 << 1)// defines demodulator settings
		// 						  0x1A			// reserved for future use
		// 						  0x1B			// reserved for future use
#define		MfTxReg					(0x1C << 1)// controls some MIFARE communication transmit parameters
#define		MfRxReg					(0x1D << 1)// controls some MIFARE communication receive parameters
		// 						  0x1E			// reserved for future use
#define		SerialSpeedReg                          (0x1F << 1)// selects the speed of the serial UART interface
		
		// Page 2: Configuration
		// 						  0x20			// reserved for future use
#define		CRCResultRegH                           (0x21 << 1)// shows the MSB and LSB values of the CRC calculation
#define		CRCResultRegL                           (0x22 << 1)
		// 						  0x23			// reserved for future use
#define		ModWidthReg				(0x24 << 1)// controls the ModWidth setting?
		// 						  0x25			// reserved for future use
#define		RFCfgReg				(0x26 << 1)// configures the receiver gain
#define		GsNReg					(0x27 << 1)// selects the conductance of the antenna driver pins TX1 and TX2 for modulation 
#define		CWGsPReg				(0x28 << 1)// defines the conductance of the p-driver output during periods of no modulation
#define		ModGsPReg				(0x29 << 1)// defines the conductance of the p-driver output during periods of modulation
#define		TModeReg				(0x2A << 1)// defines settings for the internal timer
#define		TPrescalerReg                           (0x2B << 1)// the lower 8 bits of the TPrescaler value. The 4 high bits are in TModeReg.
#define         TReloadRegH                             (0x2C << 1)//1 defines the 16-bit timer reload value
#define		TReloadRegL				(0x2D << 1)//2
#define		TCounterValueRegH                       (0x2E << 1)// shows the 16-bit timer value
#define		TCounterValueRegL                       (0x2F << 1)
		
		// Page 3: Test Registers
		// 						  0x30			// reserved for future use
#define		TestSel1Reg				(0x31 << 1)// general test signal configuration
#define		TestSel2Reg				(0x32 << 1)// general test signal configuration
#define		TestPinEnReg                            (0x33 << 1)// enables pin output driver on pins D1 to D7
#define		TestPinValueReg                         (0x34 << 1)// defines the values for D1 to D7 when it is used as an I/O bus
#define		TestBusReg				(0x35 << 1)// shows the status of the internal test bus
#define		AutoTestReg				(0x36 << 1)// controls the digital self-test
#define		VersionReg				(0x37 << 1)// shows the software version
#define		AnalogTestReg                           (0x38 << 1)// controls the pins AUX1 and AUX2
#define		TestDAC1Reg				(0x39 << 1)// defines the test value for TestDAC1
#define		TestDAC2Reg				(0x3A << 1)// defines the test value for TestDAC2
#define		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


#define		PCD_Idle				(0x00)	// no action, cancels current command execution
#define         PCD_Mem					(0x01)	// stores 25 bytes into the internal buffer
#define		PCD_GenerateRandomID                    (0x02)	// generates a 10-byte random ID number
#define		PCD_CalcCRC				(0x03)	// activates the CRC coprocessor or performs a self-test
#define		PCD_Transmit                            (0x04)	// transmits data from the FIFO buffer
#define		PCD_NoCmdChange                         (0x07)	// no command change, can be used to modify the CommandReg register bits without affecting the command, for example, the PowerDown bit
#define		PCD_Receive				(0x08)	// activates the receiver circuits
#define		PCD_Transceive                          (0x0C)	// transmits data from FIFO buffer to antenna and automatically activates the receiver after transmission
#define		PCD_MFAuthent                           (0x0E)	// performs the MIFARE standard authentication as a reader
#define		PCD_SoftReset                           (0x0F)		// resets the MFRC522



#define		RxGain_18dB				(0x00 << 4)// 000b - 18 dB, minimum
#define		RxGain_23dB				(0x01 << 4)// 001b - 23 dB
#define		RxGain_18dB_2                           (0x02 << 4)// 010b - 18 dB, it seems 010b is a duplicate for 000b
#define		RxGain_23dB_2                           (0x03 << 4)// 011b - 23 dB, it seems 011b is a duplicate for 001b
#define		RxGain_33dB				(0x04 << 4)// 100b - 33 dB, average, and typical default
#define		RxGain_38dB				(0x05 << 4)// 101b - 38 dB
#define		RxGain_43dB				(0x06 << 4)// 110b - 43 dB
#define		RxGain_48dB				(0x07 << 4)// 111b - 48 dB, maximum
#define		RxGain_min				(0x00 << 4)// 000b - 18 dB, minimum, convenience for RxGain_18dB
#define		RxGain_avg				(0x04 << 4)// 100b - 33 dB, average, convenience for RxGain_33dB
#define		RxGain_max				(0x07 << 4		// 111b - 48 dB, maximum, convenience for RxGain_48dB

#define         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.
#define		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.
#define		PICC_CMD_CT			(0x88)	// Cascade Tag. Not really a command, but used during anti collision.
#define		PICC_CMD_SEL_CL1		(0x93)	// Anti collision/Select, Cascade Level 1
#define		PICC_CMD_SEL_CL2		(0x95)	// Anti collision/Select, Cascade Level 2
#define		PICC_CMD_SEL_CL3		(0x97)	// Anti collision/Select, Cascade Level 3
#define		PICC_CMD_HLTA			(0x50)	// HaLT command, Type A. Instructs an ACTIVE PICC to go to state HALT.
#define		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.
#define		PICC_CMD_MF_AUTH_KEY_A	(0x60)	// Perform authentication with Key A
#define		PICC_CMD_MF_AUTH_KEY_B	(0x61)	// Perform authentication with Key B
#define		PICC_CMD_MF_READ		(0x30)	// Reads one 16 byte block from the authenticated sector of the PICC. Also used for MIFARE Ultralight.
#define		PICC_CMD_MF_WRITE		(0xA0)	// Writes one 16 byte block to the authenticated sector of the PICC. Called "COMPATIBILITY WRITE" for MIFARE Ultralight.
#define		PICC_CMD_MF_DECREMENT	(0xC0)	// Decrements the contents of a block and stores the result in the internal data register.
#define	PICC_CMD_MF_INCREMENT           (0xC1)	// Increments the contents of a block and stores the result in the internal data register.
#define	PICC_CMD_MF_RESTORE		(0xC2)	// Reads the contents of a block into the internal data register.
#define	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.
#define	PICC_CMD_UL_WRITE		(0xA2		// Writes one 4 byte page to the PICC.
	
#define PICC_TYPE_UNKNOWN		(0x00)
#define	PICC_TYPE_ISO_14443_4           (0x01)// PICC compliant with ISO/IEC 14443-4 
#define	PICC_TYPE_ISO_18092		(0x02) 	// PICC compliant with ISO/IEC 18092 (NFC)
#define	PICC_TYPE_MIFARE_MINI           (0x03)// MIFARE Classic protocol, 320 bytes
#define	PICC_TYPE_MIFARE_1K		(0x04)// MIFARE Classic protocol, 1KB
#define	PICC_TYPE_MIFARE_4K		(0x05)// MIFARE Classic protocol, 4KB
#define	PICC_TYPE_MIFARE_UL		(0x06)// MIFARE Ultralight or Ultralight C
#define	PICC_TYPE_MIFARE_PLUS           (0x07)// MIFARE Plus
#define	PICC_TYPE_MIFARE_DESFIRE        (0x08)// MIFARE DESFire
#define	PICC_TYPE_TNP3XXX		(0x09)// Only mentioned in NXP AN 10833 MIFARE Type Identification Procedure
#define	PICC_TYPE_NOT_COMPLETE          (0xff)	// SAK indicates UID is not complete.

#define	STATUS_OK			(0x00)// Success
#define	STATUS_ERROR			(0x01)// Error in communication
#define	STATUS_COLLISION		(0x02)// Collission detected
#define	STATUS_TIMEOUT			(0x03)// Timeout in communication.
#define	STATUS_NO_ROOM			(0x04)// A buffer is not big enough.
#define	STATUS_INTERNAL_ERROR           (0x05)// Internal error in the code. Should not happen ;-)
#define	STATUS_INVALID			(0x06)// Invalid argument.
#define	STATUS_CRC_WRONG		(0x07)// The CRC_A does not match
#define	STATUS_MIFARE_NACK		(0xff)	// A MIFARE PICC responded with NAK.

#define		MF_ACK					(0xA)		// The MIFARE Classic uses a 4 bit ACK/NAK. Any other value than 0xA is NAK.
#define		MF_KEY_SIZE				(6)			// A Mifare Crypto1 key is 6 bytes.
// 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;
/////////////////////////////////////////////////////////////////////////////////////
// Basic interface functions for communicating with the MFRC522
/////////////////////////////////////////////////////////////////////////////////////
void PCD_WriteRegister(PCD_Register reg, byte value);
void PCD_WriteRegister_long(PCD_Register reg, byte count, byte *values);
byte PCD_ReadRegister(PCD_Register reg);
void PCD_ReadRegister_long(PCD_Register reg, byte count, byte *values, byte rxAlign); //TODO rxAlign = 0
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);
/////////////////////////////////////////////////////////////////////////////////////
// Functions for manipulating the MFRC522
/////////////////////////////////////////////////////////////////////////////////////
void PCD_Init();
void PCD_Reset();
void PCD_AntennaOn();
void PCD_AntennaOff();
byte PCD_GetAntennaGain();
void PCD_SetAntennaGain(byte mask);
bool PCD_PerformSelfTest();

/////////////////////////////////////////////////////////////////////////////////////
// Power control functions
/////////////////////////////////////////////////////////////////////////////////////
void PCD_SoftPowerDown();
void PCD_SoftPowerUp();
/////////////////////////////////////////////////////////////////////////////////////
// Functions for communicating with PICCs
/////////////////////////////////////////////////////////////////////////////////////
StatusCode PCD_TransceiveData(byte *sendData, byte sendLen, byte *backData, byte *backLen, byte *validBits, byte rxAlign, bool checkCRC); // TODO eclip
StatusCode PCD_CommunicateWithPICC(byte command, byte waitIRq, byte *sendData, byte sendLen, byte *backData, byte *backLen, byte *validBits, byte rxAlign, bool checkCRC); //TODO eclip
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); //TODO eclip
StatusCode PICC_HaltA();

/////////////////////////////////////////////////////////////////////////////////////
// Convenience functions - does not add extra functionality
/////////////////////////////////////////////////////////////////////////////////////
bool PICC_IsNewCardPresent();
bool PICC_ReadCardSerial();


static   void spi_event_handler(nrf_drv_spi_evt_t const * p_event,void *p_context);
static   uint8_t spi_transmit(uint8_t data);
static   void mfrc522_write(uint8_t reg, uint8_t data);
static   uint8_t mfrc522_read(uint8_t reg);
void mfrc522_init();
void mfrc522_reset();

mfrc522.h file i am using.

Parents
  • As you verified the answer in your last ticket, we'll continue in this case instead. New activity in Verified answers will not notify support engineers and will effectively close the case. 

    Can you show me how the MFRC522 is connected to the nRF52 DK (hardware wise)? What pins on the nRF are you using to communicate with the MFRC, and at what frequency are you trying to read/write on?

    I'm afraid we don't have any example projects using the MFRC on our side as it is not our board. I'm guessing the MFRC needs to be told by the nRF to start scanning for the device. Are you able to see what function it is that returns the "STATUS_TIMEOUT" error. Is it the SPI communication or RFID communication that is timing out?

    Best regards,

    Simon

  • Can you show me how the MFRC522 is connected to the nRF52 DK (hardware wise)? What pins on the nRF are you using to communicate with the MFRC, and at what frequency are you trying to read/write on?

    i am initializing spi and rfid reader in mfrc522_init() function as below please check

    void mfrc522_init()
    {
          nrf_gpio_cfg_output(SPI_SS_PIN);
          nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
          spi_config.ss_pin   = SPI_SS_PIN;
          spi_config.miso_pin = SPI_MISO_PIN;
          spi_config.mosi_pin = SPI_MOSI_PIN;
          spi_config.sck_pin  = SPI_SCK_PIN;
          APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));
            PCD_Reset();
          uint8_t v = PCD_ReadRegister(VersionReg);
          NRF_LOG_INFO("version:%x",v);
           NRF_LOG_FLUSH();
    	// Reset baud rates
    	PCD_WriteRegister(TxModeReg, 0x00);
    	PCD_WriteRegister(RxModeReg, 0x00);
    	// Reset ModWidthReg
    	PCD_WriteRegister(ModWidthReg, 0x26);
    	// When communicating with a PICC we need a timeout if something goes wrong.
    	// f_timer = 13.56 MHz / (2*TPreScaler+1) where TPreScaler = [TPrescaler_Hi:TPrescaler_Lo].
    	// TPrescaler_Hi are the four low bits in TModeReg. TPrescaler_Lo is TPrescalerReg.
    	PCD_WriteRegister(TModeReg, 0x80);			// TAuto=1; timer starts automatically at the end of the transmission in all communication modes at all speeds
    	v=PCD_ReadRegister(TModeReg);
        NRF_LOG_INFO("TModeReg:%x",v);
         NRF_LOG_FLUSH();
        PCD_WriteRegister(TPrescalerReg, 0xA9);		// TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25μs.
    	v=PCD_ReadRegister(TPrescalerReg);
        NRF_LOG_INFO("TPrescalerReg:%x",v);
         NRF_LOG_FLUSH();
        PCD_WriteRegister(TPrescalerReg, 0xA9);		// TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25μs.
    	v=PCD_ReadRegister(TPrescalerReg);
        NRF_LOG_INFO("TPrescalerReg:%x",v);
         NRF_LOG_FLUSH(); 
        PCD_WriteRegister(TReloadRegH, 0x04);		// 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  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_Init();
            PCD_AntennaOn();
        NRF_LOG_FLUSH();
    }
    

    Pin configurations are ,

    Rfid scanner(MFRC522)

    Nrf board (PC10040)

    SDA (SS)

    31

    SCK (Clock)

    26

    MOSI

    29

    MISO

    30

    GND

    GND

    3.3V

    3.3V

    and at what frequency are you trying to read/write on?

    As per frequency i am using the default  configuration frequency option that is 4MHz as per the function below

    #define NRF_DRV_SPI_DEFAULT_CONFIG \
    { \
    .sck_pin = NRF_DRV_SPI_PIN_NOT_USED, \
    .mosi_pin = NRF_DRV_SPI_PIN_NOT_USED, \
    .miso_pin = NRF_DRV_SPI_PIN_NOT_USED, \
    .ss_pin = NRF_DRV_SPI_PIN_NOT_USED, \
    .irq_priority = SPI_DEFAULT_CONFIG_IRQ_PRIORITY, \
    .orc = 0xFF, \
    .frequency = NRF_DRV_SPI_FREQ_4M, \
    .mode = NRF_DRV_SPI_MODE_0, \
    .bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST, \
    }

    Are you able to see what function it is that returns the

    i am getting error inside PCD_CommunicateWithPICC() this function  exactly in the .c file in the text marked with red colour and  i have comment as well please check and do the needful

    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
    // debug_info("n:%x",n);
    if (n & waitIRq) {
    break;
    }
    if (n & 0x01) { 
    return STATUS_TIMEOUT;
    }
    }

    if (i == 0) {                                                              //    I AM GETTING ERROR EXACTLY HERE //
    debug_info("STATUS_TIMEOUT2");
    return STATUS_TIMEOUT;
    }


    byte errorRegValue = PCD_ReadRegister(ErrorReg);  CollErr CRCErr ParityErr ProtocolErr
    if (errorRegValue & 0x13) { 
    return STATUS_ERROR;
    }

    Is it the SPI communication or RFID communication that is timing out?

    Not sure which one is timing out please check and do the needful.

Reply
  • Can you show me how the MFRC522 is connected to the nRF52 DK (hardware wise)? What pins on the nRF are you using to communicate with the MFRC, and at what frequency are you trying to read/write on?

    i am initializing spi and rfid reader in mfrc522_init() function as below please check

    void mfrc522_init()
    {
          nrf_gpio_cfg_output(SPI_SS_PIN);
          nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
          spi_config.ss_pin   = SPI_SS_PIN;
          spi_config.miso_pin = SPI_MISO_PIN;
          spi_config.mosi_pin = SPI_MOSI_PIN;
          spi_config.sck_pin  = SPI_SCK_PIN;
          APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));
            PCD_Reset();
          uint8_t v = PCD_ReadRegister(VersionReg);
          NRF_LOG_INFO("version:%x",v);
           NRF_LOG_FLUSH();
    	// Reset baud rates
    	PCD_WriteRegister(TxModeReg, 0x00);
    	PCD_WriteRegister(RxModeReg, 0x00);
    	// Reset ModWidthReg
    	PCD_WriteRegister(ModWidthReg, 0x26);
    	// When communicating with a PICC we need a timeout if something goes wrong.
    	// f_timer = 13.56 MHz / (2*TPreScaler+1) where TPreScaler = [TPrescaler_Hi:TPrescaler_Lo].
    	// TPrescaler_Hi are the four low bits in TModeReg. TPrescaler_Lo is TPrescalerReg.
    	PCD_WriteRegister(TModeReg, 0x80);			// TAuto=1; timer starts automatically at the end of the transmission in all communication modes at all speeds
    	v=PCD_ReadRegister(TModeReg);
        NRF_LOG_INFO("TModeReg:%x",v);
         NRF_LOG_FLUSH();
        PCD_WriteRegister(TPrescalerReg, 0xA9);		// TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25μs.
    	v=PCD_ReadRegister(TPrescalerReg);
        NRF_LOG_INFO("TPrescalerReg:%x",v);
         NRF_LOG_FLUSH();
        PCD_WriteRegister(TPrescalerReg, 0xA9);		// TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25μs.
    	v=PCD_ReadRegister(TPrescalerReg);
        NRF_LOG_INFO("TPrescalerReg:%x",v);
         NRF_LOG_FLUSH(); 
        PCD_WriteRegister(TReloadRegH, 0x04);		// 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  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_Init();
            PCD_AntennaOn();
        NRF_LOG_FLUSH();
    }
    

    Pin configurations are ,

    Rfid scanner(MFRC522)

    Nrf board (PC10040)

    SDA (SS)

    31

    SCK (Clock)

    26

    MOSI

    29

    MISO

    30

    GND

    GND

    3.3V

    3.3V

    and at what frequency are you trying to read/write on?

    As per frequency i am using the default  configuration frequency option that is 4MHz as per the function below

    #define NRF_DRV_SPI_DEFAULT_CONFIG \
    { \
    .sck_pin = NRF_DRV_SPI_PIN_NOT_USED, \
    .mosi_pin = NRF_DRV_SPI_PIN_NOT_USED, \
    .miso_pin = NRF_DRV_SPI_PIN_NOT_USED, \
    .ss_pin = NRF_DRV_SPI_PIN_NOT_USED, \
    .irq_priority = SPI_DEFAULT_CONFIG_IRQ_PRIORITY, \
    .orc = 0xFF, \
    .frequency = NRF_DRV_SPI_FREQ_4M, \
    .mode = NRF_DRV_SPI_MODE_0, \
    .bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST, \
    }

    Are you able to see what function it is that returns the

    i am getting error inside PCD_CommunicateWithPICC() this function  exactly in the .c file in the text marked with red colour and  i have comment as well please check and do the needful

    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
    // debug_info("n:%x",n);
    if (n & waitIRq) {
    break;
    }
    if (n & 0x01) { 
    return STATUS_TIMEOUT;
    }
    }

    if (i == 0) {                                                              //    I AM GETTING ERROR EXACTLY HERE //
    debug_info("STATUS_TIMEOUT2");
    return STATUS_TIMEOUT;
    }


    byte errorRegValue = PCD_ReadRegister(ErrorReg);  CollErr CRCErr ParityErr ProtocolErr
    if (errorRegValue & 0x13) { 
    return STATUS_ERROR;
    }

    Is it the SPI communication or RFID communication that is timing out?

    Not sure which one is timing out please check and do the needful.

Children
No Data
Related