Electronic – How to ensure data integrity when using I2C with a PIC

dataerrori2cpic

When master device transfers a piece of data, slave will acknowledge back once the data has been received by slave. So it's not possible to ensure the data integrity by only polling ACK.

I implemented a C function:

unsigned char i2c_write_byte(unsigned char s);

Here I'm returning the ACKSTAT bit.
So if there is not an ACK sent by the slave, I will try to send the data again by using:

while(!i2c_write_byte(data));

I know the ninth clock is for ACK, but what if there is no ACK sent back by slave device.
Then it should be detected as NACK meaning the slave didn't drive SDA low which is slave never received data transferred.

So on this occasion, should I send data again or send data after a restart?

I can only think of re-send data to work around NACK problem and still can't solve the error happened in the data while in a transfer.

So how to ensure data integrity in I2C?

Best Answer

If you are having serious data integrity problems with your IIC bus, then you should first look at the hardware to see why data is getting corrupted. In a properly designed system, NACKs shouldn't happen excecpt for the slave to signal it can't take more data. NACK to a address byte means you sent the wrong address. That shouldn't happen unless you are deliberately polling to see what addresses are out there. NACK to a data byte where NACK isn't used to signal the slave can't take more is either a firmware screwup or due to excessive noise on the SCL line.

Note that ACK doesn't mean a byte was received correctly. Other than the address byte, it only means that the clock was received correctly. NACK is pretty useless to check for data corruption because by the time you actually get NACKs due to bus noise, you've got much bigger system-level problems.

Unexpected NACK means something went wrong, but you don't really know what. It is best to abort the whole message because you don't know how confused the slave is at that point. Do a stop, then a start before the next message. That should reset the low level protocol layer of all slaves. Perhaps you can retry the message once or twice, but most likely you have a higher level problem that therefore needs to be dealt with by higher levels of firmware.