Can't get MFRC522 (RFID) to work with SPI bus (bit banging)

Dear Arduino,

I don’t know where to ask so, I’ll try to ask here because MFRC522 module is arduino related (maybe) so might be that someone who worked with it could give some idea. Hope so.

A module ( MFRC522 ):

Schematic:

An MCU ( PIC18F452 ) is powered with 5V, module is powered from 5V(DC) → 3.3V(DC) converter and all logic pins ( SS(SDA), SCK, MOSI, MISO and RST ) are connected using voltage dividers ( 3K and 1K6 resistors were used ( because
) ).


We know that I2C and EA pins of RC522 chip should be connected to 0 and 1 respectively to enable SPI interface mode for MFRC522 module as in datasheet is written (Table 5):

I’ve checked with multi-meter and I2C is shorted to GND and EA is shorted to 3.3V so SPI mode should be ON, isn’t it?


Here’s some code which should initiate an MFRC522 module and print a module’s version on LCD:

// configuration and LCD libraries
... ( LCD works properly )
...

// RFID MFRC522 pins
#define rf_ss   LATAbits.LA0
#define rf_sck  LATAbits.LA1
#define rf_mosi LATAbits.LA2
#define rf_rst  LATAbits.LA3
#define rf_miso PORTAbits.RA5 // input

// A custom function to send data to SPI bus
unsigned char SPI_WB( unsigned char d ) {
    __delay_us( 500 );
    unsigned char r = 0; // to get a MISO values
    for ( unsigned char i = 0; i < 8; i++ ) {
        rf_mosi = ( d >> i ) & 0x01;
        __delay_us( 100 );
        rf_sck = 1;
        __delay_us( 100 );
        r = ( ( rf_miso << i ) | r );
        __delay_us( 100 );
        rf_sck = 0;
        __delay_us( 1000 );
    }
    __delay_us( 100 );
    return r;
}

// A custom function to write data to register
void SPI_WR( unsigned char a, unsigned char v ) {
  rf_ss = 0;
  SPI_WB( ( a << 1 ) & 0x7E ); // Address format: 0XXXXXX0
  SPI_WB( v );
  rf_ss = 1;
}

unsigned char SPI_RR( unsigned char a ) {
  rf_ss = 0;
  SPI_WB( ( ( a << 1 ) & 0x7E ) | 0x80 );
  rf_ss = 1;
  return SPI_WB( 0x00 );
}

#define MFRC522_CR 0x01 // Command register
#define MFRC522_SR 0x0F // MFRC522 Soft Reset command
#define MFRC522_V 0x37 // MFRC522 Version register


void main( ) {
  rf_ss = 1;
  __delay_us( 1000 );
  SPI_WR( CommandReg, MFRC522_SR ); // A result of logic picture is below
  unsigned char str;
  sprintf( str, "Version: 0x%x", SPI_RR( MFRC522_V ) ); LCD_W( str ); // Unfortunately returns "Version: 0x0"
  while( 1 ) { }
}
...

Logic ( SS( SDA), SCK and MOSI pins at the start of MCU ):

Full Logic ( SCK, MOSI and MISO pins at the start of MCU ):

or (with immediate MOSI zero, to easier view)


As you could see, there’s no answer from module:


Yes, PIC18F452 has special pins for SPI protocol (PORTC), but, unfortunately, I can’t use these in this project.

All in all, no return from MFRC522_V register ( At the end an LCD is populated by " Version: 0x0" ).

Is a logic and communication itself right?


Edit 1:

I’ve seen an interesting picture in MFRC522 datasheet:

Does it show that byte should be sent from left to right rather than I’ve sent from right to left? For example, 0x63 should be sent as [ 0,1,1,0,0,0,1,1 ] rather than [ 1,1,0,0,0,1,1,0 ], is it?

In case that I’ve changed function SPI_WB to be:

unsigned char SPI_WB( unsigned char d ) {
    __delay_us( 500 );
    unsigned char r = 0;
//    for ( unsigned char i = 0; i < 8; i++ ) {
    for ( unsigned char i = 8; i > 0; i-- ) {
//      rf_mosi = ( d >> i ) & 0x01;
        rf_mosi = ( d >> ( i - 1 ) ) & 0x01;
        __delay_us( 100 );
        rf_sck = 1;
        __delay_us( 100 );
//      r = ( ( rf_miso << i ) | r );
        r = ( ( rf_miso << ( i - 1 ) ) | r );
        __delay_us( 100 );
        rf_sck = 0;
//      rf_mosi = 0; // immediate zero
        __delay_us( 1000 );
    }
    __delay_us( 100 );
    return r;
}

And the result in analyzer looks like:

and with “immediate zero”:


As you could see, … unfortunately, there’s no result on MISO pin.

  1. Do you have any idea why MISO doesn’t have any data?
  2. Is it okay to use bit banged SPI and if so, does speed depend then (will it work with custom delays)?
  3. Is really set to SPI mode?
  4. Is it possible to get MFRC522 firmware version by reading version’s register at power on only (without module initializing) and if no, then which are significant for initialize?

Thank you very much for your help, really!