Can't get MFRC522 (RFID) to work with PIC18F452 and SPI bus

Discussion in 'Embedded Systems and Microcontrollers' started by vv7, Jul 20, 2018.

  1. vv7

    Thread Starter New Member

    Jul 20, 2018
    4
    0
    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 ):

    [​IMG]

    Schematic:

    [​IMG]

    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
    [​IMG] ) ).

    ---------------------------------------------------------------

    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):

    [​IMG]

    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?

    [​IMG]

    ---------------------------------------------------------------

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

    Code (Text):
    1. // configuration and LCD libraries
    2. ... ( LCD works properly )
    3. ...
    4.  
    5. // RFID MFRC522 pins
    6. #define rf_ss  LATAbits.LA0
    7. #define rf_sck  LATAbits.LA1
    8. #define rf_mosi LATAbits.LA2
    9. #define rf_rst  LATAbits.LA3
    10. #define rf_miso PORTAbits.RA5 // input
    11.  
    12. // A custom function to send data to SPI bus
    13. unsigned char SPI_WB( unsigned char d ) {
    14.   __delay_us( 500 );
    15.   unsigned char r = 0; // to get a MISO values
    16.   for ( unsigned char i = 0; i < 8; i++ ) {
    17.   rf_mosi = ( d >> i ) & 0x01;
    18.   __delay_us( 100 );
    19.   rf_sck = 1;
    20.   __delay_us( 100 );
    21.   r = ( ( rf_miso << i ) | r );
    22.   __delay_us( 100 );
    23.   rf_sck = 0;
    24.   __delay_us( 1000 );
    25.   }
    26.   __delay_us( 100 );
    27.   return r;
    28. }
    29.  
    30. // A custom function to write data to register
    31. void SPI_WR( unsigned char a, unsigned char v ) {
    32.   rf_ss = 0;
    33.   SPI_WB( ( a << 1 ) & 0x7E ); // Address format: 0XXXXXX0
    34.   SPI_WB( v );
    35.   rf_ss = 1;
    36. }
    37.  
    38. unsigned char SPI_RR( unsigned char a ) {
    39.   rf_ss = 0;
    40.   SPI_WB( ( ( a << 1 ) & 0x7E ) | 0x80 );
    41.   rf_ss = 1;
    42.   return SPI_WB( 0x00 );
    43. }
    44.  
    45. #define MFRC522_CR 0x01 // Command register
    46. #define MFRC522_SR 0x0F // MFRC522 Soft Reset command
    47. #define MFRC522_V 0x37 // MFRC522 Version register
    48.  
    49.  
    50. void main( ) {
    51.   rf_ss = 1;
    52.   __delay_us( 1000 );
    53.   SPI_WR( CommandReg, MFRC522_SR ); // A result of logic picture is below
    54.   unsigned char str;
    55.   sprintf( str, "Version: 0x%x", SPI_RR( MFRC522_V ) ); LCD_W( str ); // Unfortunately returns "Version: 0x0"
    56.   while( 1 ) { }
    57. }
    58. ...
    ---------------------------------------------------------------

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

    [​IMG]

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

    [​IMG]

    or (with immediate MOSI zero, to easier view)

    [​IMG]

    ---------------------------------------------------------------

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

    [​IMG]

    ---------------------------------------------------------------

    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:

    [​IMG]

    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:

    Code (Text):
    1. unsigned char SPI_WB( unsigned char d ) {
    2.   __delay_us( 500 );
    3.   unsigned char r = 0;
    4. //  for ( unsigned char i = 0; i < 8; i++ ) {
    5.   for ( unsigned char i = 8; i > 0; i-- ) {
    6. //  rf_mosi = ( d >> i ) & 0x01;
    7.   rf_mosi = ( d >> ( i - 1 ) ) & 0x01;
    8.   __delay_us( 100 );
    9.   rf_sck = 1;
    10.   __delay_us( 100 );
    11. //  r = ( ( rf_miso << i ) | r );
    12.   r = ( ( rf_miso << ( i - 1 ) ) | r );
    13.   __delay_us( 100 );
    14.   rf_sck = 0;
    15. //  rf_mosi = 0; // immediate zero
    16.   __delay_us( 1000 );
    17.   }
    18.   __delay_us( 100 );
    19.   return r;
    20. }
    And the result in analyzer looks like:

    [​IMG]

    and with "immediate zero":

    [​IMG]

    ---------------------------------------------------------------

    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!
     
  2. Ian Rogers

    Active Member

    Dec 12, 2012
    402
    98
    A) Cant see where you disabled the ADC..
    B) Cant see where you set the pins as outputs...

    A) ADCON = xxx
    B) TRISA = xxxx
     
    vv7 likes this.
  3. vv7

    Thread Starter New Member

    Jul 20, 2018
    4
    0
    Oh, of course, sorry about that. The main() looks like:

    Code (Text):
    1. function main() {
    2.   ADCON0 = 0;
    3.   ADCON1 = 0b00000110; // Set the whole PORTA as digital I/O
    4.    
    5.   TRISA = 0b00010000; // RFID RC522
    6.    
    7.   LATA = 0;
    8.   rf_ss = 1;
    9.   __delay_us( 1000 );
    10.  
    11.   SPI_WR( CommandReg, MFRC522_SR ); // A result of logic picture is below
    12.   unsigned char str;
    13.   sprintf( str, "Version: 0x%x", SPI_RR( MFRC522_V ) ); LCD_W( str ); // Unfortunately returns "Version: 0x0"
    14.  
    15.   while( 1 ) { }
    16. }
     
  4. Ian Rogers

    Active Member

    Dec 12, 2012
    402
    98
    As the main() is still a Function, do I assume you usually program in basic?

    RST High or Low?? I don't see a control for it!!
     
  5. Raymond Genovese

    Active Member

    Mar 5, 2016
    971
    534
    Just a possibility: MISO doesn't appear to have any data because it never is driven to a logic level high on the PIC input port bit (RA5).

    MISO is driven from 3.3V logic on the 522 to RA5 (as an input).

    p235 DS Note 1: Pins configured as digital inputs (in this case RA5) will convert an analog input according to the Schmitt Trigger input specification .

    The Schmitt Trigger input specification requires 0.8VDD or 4.0V for a logic high (VIH) (p335). Since the 522 can never provide this, MISO is never read as '1'. So, you would need to provide 3.3v to 5v translation rather than running it directly into RA5.

    or, it's something else :)



    Who is "Dear Arduino"?
     
    Last edited: Jul 21, 2018
    vv7 likes this.
  6. vv7

    Thread Starter New Member

    Jul 20, 2018
    4
    0
    Thank you very much! So, just found that:

    [​IMG]
    This is a back side of an oscillator
    [​IMG]

    Could that be the problem?

    Btw, regards 4.0V stuff, why then it works on arduino () Does it have longer range of input voltages?
     
  7. Raymond Genovese

    Active Member

    Mar 5, 2016
    971
    534
    Don’t take my word for it, but consider testing it out.

    To answer your question, though…on an ATmega328/P used in some Arduinos (like an UNO), I think that all of the GPIO pins have a minimum VIH of .7-.8 V, so that is the minimum to be considered a logic high. At least from a brief glancing of the datasheet.

    Some of the IO pins on the PIC that you are using have a VIH of ~2.0V if you are powering the PIC at 5.0V, which you are. So, in the case of those pins the, 3.3V from the 522 would be able to hit the logic high on the PIC. But, not all of the PIC I/O pins are like that. Some of the I/O pins have a different requirement (probably because those pins have multiple functions) and I think that the one that you chose is such a case - at least that is how I am reading the datasheet..

    There are lots of ways to translate from 3.3V to 5.0, including little inexpensive translator boards just for that purpose – do a search and you will see lots of info and ways to get that done. Maybe the easiest way would be to use a TTL buffered pin on the PIC (see the data sheet), instead of the one that you are using.

    As for the crystal on the board, it looks kind of soldered-grungy, but I don’t see that the traces are torn up.

    Edited to add: That one trace below, looks worse than the other, but I can't tell if the trace is actually broken. Did you test for continuity?
    Untitled-1.jpg

    Hope this helps.
     
    Last edited: Jul 21, 2018
  8. Raymond Genovese

    Active Member

    Mar 5, 2016
    971
    534
    I have to correct myself because I was wrong. I was looking at and linked to the PIC18F4520 data sheet and your schematic says that you are using the PIC18F452 (I really need to either stop leaning back so far in my chair when typing or get better glasses).

    On the PIC18F452, only RA4 on PORTA has the Schmitt Trigger input specification, and you are using RA5, so this is not the issue.

    "The RA4 pin is multiplexed with the Timer0 module clock input to become the RA4/T0CKI pin. The RA4/ T0CKI pin is a Schmitt Trigger input and an open drain output. All other RA port pins have TTL input levels and full CMOS output drivers"

    Have you figured out the problem yet? Please don't forget to let us know.
     
  9. vv7

    Thread Starter New Member

    Jul 20, 2018
    4
    0
    Sorry for a late reply.

    So, a troublemaker was a DC-DC Converter MP1584EN which was used as power for RC522 ( 5V to 3.3 ):

    [​IMG]

    It was probably too noisy for RC522.
    Thank you very much for trying.

    Best regards
     
  10. Raymond Genovese

    Active Member

    Mar 5, 2016
    971
    534
    Good deal on finding the problem! Even though I didn't have the solution, I am also very happy that you posted the status/solution. This helps everyone.
     
Loading...