# Strange I2C Behaviour

I'm currently trying to re-use some hw from an old project which happens to have the correct ICs I need for a prototype, but the engineer that designed it has left, so i'm essentially now reverse engineering it...

I'm writing PIC24F code from scratch for it, and I can get the I2C bus running (verified with scope and logic analyzer) but have strange ACK/NACK behaviour from the other ICs on the board.

I have devices at 0x68 and 0x40, and both ACK to an initial address write. I thought I was winning, until testing other addresses.. and they all ACK too.

If I continue to try to write to the bus after the first ACK, all I get is NACK for the data frames I write.

My question is, in what scenarios would this occur? I've been debugging this for 2 days and a little haggard now.

Brief description of hw/sw -

• PIC24FJ256GB106
• Analog Devices DSP
• Should be 400kHz I2C, with 2.2K pullups. Voltages all check out.
• All start/stop/restart traces are fine. The bus appears to be working.
• Baud rate on PIC seems fine. I've recalculated according to datasheet.
• Analog scope trace shows 0v and 3.3v acheived, analyzer gives correct logic for various tests (using I2C decoder)
• Using Microchip PIC24 periph. library
• Addresses of ICs confirmed, but none accept data frames, only initial ACK from slave address

It's quite vague not providing traces, I'll try to later when I'm back with the HW. It's infuriating as this HW definitely works and is currently in mass production, so it can't be a hardware problem.

Scope trace - (Analog trace of SDA for reference)

SDA seems to be being released correctly by the slave, but I'm confused as to what is pulling it low for ACK on other addresses. The scope trace shows a write to 0x68 with 0x08 then 0x1C.

I get an ACK for the address but NACK for everythign else, this is the same on all addresses though...

I2C Library setup call -

c1 = (I2C_ON | I2C_GCALL_DIS | I2C_IDLE_STOP | I2C_IPMI_DIS | I2C_7BIT_ADD | I2C_SLW_DIS | I2C_STR_DIS);
c2 = 4.2;    /* Baud rate */

OpenI2C2(c1,c2);


Everything else is done as the Microchip example shows in the xc16 docs. I might resort to porting some old bit banged i2c just to be sure their functions aren't being weird with me... I know the old engineer used some Renesas lib from another project, this is why I'm rewriting it.

• Do you have a datasheet of the ICs and maybe a scope grab? Dec 5, 2012 at 16:33
• it sounds like you may inandvertently be doing general call? Dec 5, 2012 at 16:38
• Make sure that the processor is running at fast enough. What speed is the PIC running at?
– TDL
Dec 5, 2012 at 22:44
• @vicatcu - just tried specifically disabling general call in the config bits for the bus.. nothing.
– njt
Dec 6, 2012 at 14:05
• @TDL - PIC external clock is at 8mhz, so should be OK as this is an existing hw design.
– njt
Dec 6, 2012 at 14:06

It looks to me that you're ORing terms that you need to be ANDing. I2C_ON is 0xFFFF, so the register is going to be all 1's.

Take a look at the i2c.h file for PIC24:

#define I2C_ON                      0xFFFF /*I2C module enabled */


No matter what else you put in the configuration word, they're all going to be 1. Many settings you need (general call off, 7-bit address, etc.) need their corresponding bits to be zero.

Here's how I init the I2C peripheral on a dsPIC33 (essentially the same peripheral and same library calls):

OpenI2C1(I2C1_ON & I2C1_IDLE_CON & I2C1_7BIT_ADD & I2C1_STR_EN & I2C1_SLW_DIS & I2C1_GCALL_DIS & I2C1_SM_EN & I2C1_IPMI_DIS, clk);


Also bear in mind that the clock argument should be unsigned int - not 4.2 :)

(When in doubt, don't use the library call and manually set the SFR bits yourself.)

• Ah, great! Yep, that's now giving me a NACK on everything... so I'm guessing my address of 68h must be wrong. I tried 40h and that accepts a write followed by data, so a little more detective work to be done I think. Thanks!
– njt
Dec 7, 2012 at 9:05