9 years, 6 months ago.

Trouble with I2C not always writing data

I am developing some code to interface with an RFID tag reader. I thought this would be simple, but I2C is not acting like I would expect. I have pasted my code at the bottom of this message. I am using the STM32F030R8 nucleo board if it matters. I have a logic analyzer connected to the pins, and I have logic traces from a working EVM system, not mbed (I'm porting from LPC to STM)

Here are the problems I am having: 1. Though there is a second line sending at "0xAA" nothing actually gets sent. The code skips to the next send of an 0x50 (the address). This is just here for exploration, but it perplexes my why no message is sent.

2. There is 5ms of space between bytes that get written. I don't know if this causes a problem or not, but the working code sends the following sequence.

Setup Write 0 (NAK) Setup Write 0x50 (ACK) 0x7F (ACK) Setup read 0x51 (ACK) 0x18 (NAK)

These are all spaced with only a few uS in between. With mbed, there is much larger space, so the code below sends the following: setup write 0 (nak) 5ms setup write 0x50 (NAK) read 0x51 (NAK)

Even when the chip receives the same message, it does not respond the same, so I think the delay is causing this.

Can anyone help me break though this logjam?

I2C test program


include "mbed.h"
 
#define CLRC663_ADDR (0x50) // RFID Address Register
#define RFID_VERSION (0x7F) //version register 
I2C i2c(PB_9, PB_8);
 
DigitalOut myled(LED1);
 
Serial pc(SERIAL_TX, SERIAL_RX);
 

int main()
{
 
pc.baud(115200);
    i2c.frequency(1000000);
    char data_write[2];
    char data_read[2];
    int status;
    
 
        data_write[0] = 0x7F;
        
       i2c.start();
       i2c.write(0);
       i2c.write(0xAA);
       status = i2c.write(CLRC663_ADDR, data_write, 2, true); // no stop
       if(status !=0) pc.printf("write error\n");

       status != i2c.read(CLRC663_ADDR, data_read, 1, false);
       if(status !=0) pc.printf("read error\n");
       else  pc.printf("value = %x\n", data_read[0]); // Display result
        
       myled = !myled;
 
}

1 Answer

9 years, 6 months ago.

I dunno about STM devices, but actally I am surprised an NXP device did want to send that. First you send the general call address, which is not implemented according to the datasheet of your device. Then you send 0xAA after sending an address byte (the 0x00), which didn't get ACKed, which makes no sense according to the I2C standard.

Lines 25, 26 and 27 should be removed I think. Then your line 28 says it is going to send 2 data bytes, however I would assume you only want to send one byte (0x7F). If you change that to 1 I am prety sure it will all work properly.

Oh and in general for testing I wouldn't put it in fast mode+ (1mbit/s).

Thanks Erik -

I had tried the things you suggest, and I have just gone back and tried them again. I brought speed down to 100Khz, I removed all extra writes, but I still the the NAK.

here is my code now:

Code rev 2

#include "mbed.h"
 
#define CLRC663_ADDR (0x50) // RFID Address Register
#define RFID_VERSION (0x7F) //version register 
I2C i2c(PB_9, PB_8);
 
DigitalOut myled(LED1);
 
Serial pc(SERIAL_TX, SERIAL_RX);
 
 
int main()
{
 
pc.baud(115200);
    //i2c.frequency(1000000);
    char data_write[2];
    char data_read[2];
    int status;
    

       data_write[0] = RFID_VERSION;
        
       status = i2c.write(CLRC663_ADDR, data_write, 1, true); // no stop
       if(status !=0) pc.printf("write error\n");

    while(1) {
       myled = !myled;
       wait(0.1);
       }
    
 
}

Here is the logic analyzer image:

/media/uploads/glansberry/logicanalyzer_i2c_prob_1.jpg

Here is the logic analyzer image of the working device (driven from LPC) /media/uploads/glansberry/logicanalyzer_i2c_working.jpg

Also, I am totally confused by the spacing between messages, as seen in this trace. Nevermind that that the second message is a repeat of the send to 0x50. /media/uploads/glansberry/logicanalyzer_i2c_prob_longtimebase.jpg

posted by Geoffrey Lansberry 04 Nov 2014

Then if you get a NACK there I would say the most likely reason is that your address is wrong (or wiring). You can try making simple program which scans all possible address and see what that results in. All interface pins set correctly?

Edit: So your picture shows the same: It sends he address, but results in a NAK. Can you check the same with your old setup?

posted by Erik - 04 Nov 2014

OK - it is working now! Problem was that the powerdown signal was marked with the wrong polarity on the schematic. Once I changed that, and added a small delay to allow the part to get going, communications started working. Thanks Erik for your time and advice!

posted by Geoffrey Lansberry 05 Nov 2014

Glad to hear it works now :)

posted by Erik - 05 Nov 2014