# How to ensure data integrity when using I2C with a PIC

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?

• while(!i2c_write_byte(data)) will get stuck in infinite loop if the ACK doesn't come. – John U Feb 21 '14 at 12:48
• @JohnU yeah, I noticed that.... – longtengaa Feb 21 '14 at 15:15

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.

• So basically you are saying it's rare for I2C to have data corruption problems and I shall not worry about it? – longtengaa Feb 21 '14 at 15:19
• @Lucaz: Basically it shouldn't happen with a competent hardware design. That means keep the IIC bus short, all on the same board with the same ground plane, proper pullups, and proper wait between all state changes in the master firmware. – Olin Lathrop Feb 21 '14 at 15:27
• So in industrial production, there still isn't any data detection or correction for I2C? – longtengaa Feb 21 '14 at 15:35
• @Lucaz: Not unless you build it into the higher protocol layers yourself. IIC is considered more like digital signals on the same board that you expect to just work, and that are guarantee so by careful design. The protocol hard-coded into various IIC slave chips doesn't allow for integrity checking, like packets with checksums. – Olin Lathrop Feb 21 '14 at 15:41
• Then as for higher protocol layers, I should first write some data into slave and check slave's register to see if I wrote it right? or something like that? – longtengaa Feb 21 '14 at 15:50

You may want to look into some protocols that use I2C as their foundation, like SMBus (or PMBus):

• These protocols introduce a packet error checksum (PEC), which is a CRC-check of the entire message. The slave will transmit its computed PEC and the master will compute its own. If they match, no worries. If not, discard the data and try the transaction again from the top.

• These protocols put a time-out upper limit on clock stretching, forcing the I2C hardware to reset itself if a transaction takes too long. Pure I2C can have indefinite clock stretching.

Also, don't be afraid to hammer the bus as hard as you can as a strife test. I used to rely on off-the-shelf I2C masters (iPort and Aardvark) to characterize the performance of our products on the bench, but quickly found that they were incapable of exercising the bus fast enough to uncover firmware issues like race conditions or overwhelming of the task scheduling mechanism. I ended up writing my own bus master in C / inline assembly (using a dsPIC at 50 MIPS) specifically to exercise the I2C/PMBus interface as quickly as the slave would allow with trivial latency. Wow, did I find issues :)

• +1 good to know SMBus or PMBus can work around this. But unfortunately the other IC I'm using is not SMBus compatible. – longtengaa Feb 22 '14 at 3:48