This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

EK-TM4C129EXL: I2C not working

Part Number: EK-TM4C129EXL
Other Parts Discussed in Thread: PCA9555

Hi,

I am trying to communicate with IO Expander chip (PCA9555) via I2C. I need to read a register. I have initialized my I2C0 Port and I can see some partial communication on the scope as well.

As can be seen in the picture, I am first writing and then reading, However I dont see any data being transferred from Master to slave during the write operation and similarly No data is coming out from Slave to master during the Read operation however I do see the Slave is Asserting the ACK signal on both transactions.

Here is the Read Operation diagram for IO-Expander (PCA9555)

Here is my code;

void DCCT_I2C_Init(void)
{
    //I2C0 Module initialization
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);

    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C0)){} //Wait for I2C0 Module to stabilize
    I2CMasterEnable(DCCT_I2C_BASE);
    GPIOPinConfigure(GPIO_PB2_I2C0SCL);
    GPIOPinConfigure(GPIO_PB3_I2C0SDA);
    GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, DCCT_I2C_SCL_PIN);
    GPIOPinTypeI2C(GPIO_PORTB_BASE, DCCT_I2C_SDA_PIN);
    ROM_I2CMasterInitExpClk(DCCT_I2C_BASE, sys_clock, true);


}


uint8_t I2C_read(uint32_t ulBase, uint8_t chip_address, uint8_t internal_address)
{

    ROM_I2CMasterSlaveAddrSet(ulBase, chip_address, false); // Specify slave address with read request set to false
    //SysCtlDelay(1000);
    ROM_I2CMasterDataPut(ulBase, internal_address); //Place the Internal register address
    ROM_I2CMasterControl(ulBase, I2C_MASTER_CMD_SINGLE_SEND); // Initiate send of 1Byte character from Master to Slave
    while (!(ROM_I2CMasterBusy(ulBase))); //Wait till end of transaction

    SysCtlDelay(1000);

    ROM_I2CMasterSlaveAddrSet(ulBase, chip_address, true); // Specify slave address with read request set to true
    SysCtlDelay(1000);
    ROM_I2CMasterControl(ulBase, I2C_MASTER_CMD_SINGLE_RECEIVE);// Initiate send of character from Master to Slave
    while (!(ROM_I2CMasterBusy(ulBase))); //Wait till end of transaction

    SysCtlDelay(1000);

    return (uint8_t)(ROM_I2CMasterDataGet (ulBase)); //Read from FIFO


}


I thank you all for your time and help.

Regards.

  • When I say above; I dont see any data being transferred from Master to slave during the write operation. I am referring to line number 23 shown in the post above i.e. 

    ROM_I2CMasterDataPut(ulBase, internal_address); //Place the Internal register address

    However it only sends the Chip Address which is 0x20, then it should send the internal address of the I2C chip as shown in above code. The same applies to the next half (The read operation) as shown in the picture above.

  • Hello Sahil,

    Couple comments/questions:

    1) With I2CMasterInitExpClk, set it to false first and start at 100kbps. It's always best to get I2C running at 100kbps first so if you have any hardware issues at higher speeds, you aren't trying to debug them as a software issue.

    2) Try applying this workaround to your code: e2e.ti.com/.../2902446

    If those 2 do not help, from a hardware standpoint:

    3) What value pull-up resistors are being used?

    4) Do you have access to an o-scope? If so, you can use the scope to make sure the lines are being pulled up/down cleanly. This should go along with checking the pull-ups to make sure the hardware is good.

    See if these tips help you make any progress.
  • Hi,

    I just tried and followed the posts. I dont see any problem with the code as it is already in agreement with the reference post you provided.
    The picture I have shown is from a scope.
    There are 10K Pullups on the two lines. And Now I am running at 100kbps. Still the same problem.
  • Hello Sahil,

    Gotcha, it looked more like a logic state analyzer, those seem to be very clean transitions so you should be fine from a hardware standpoint. The pull-ups are a bit higher than I'd use, but they seem to be working well. For general reference, this app note can help with pull-up selection in the future, good resource to know about: www.ti.com/.../slva689.pdf

    Regarding the code, the workaround is not applied on your code, you have only this one line:

    while (!(ROM_I2CMasterBusy(ulBase)));

    What is recommended is the following TWO lines:

    while(!I2CMasterBusy(I2C0_BASE)); // add this line in addition to the original line

    while(I2CMasterBusy(I2C0_BASE)); // not busy

    Actually looking at your current code, you should be using

    while (ROM_I2CMasterBusy(ulBase));

    And not while (!(ROM_I2CMasterBusy(ulBase)));

    But try the workaround first and see what happens.
  • Just tried. Not luck.

    What I see is if i debug the code, my code gets stuck at
    while(!I2CMasterBusy(I2C0_BASE));
    and if i step in or step-over it remains stuck.
    Looks like the problem is in that line some how.
    However since my code is under FreeRTOS control so the systick timer resets it and prevents a permanent freeze otherwise.
  • Hello Sahil,

    Looking at your image and when accounting for what you said about data not being transferred and comparing it to good vs bad I2C transactions, I don't think you are seeing an ACK on the line. That looks like a NAK. Which would mean the slave device is not acknowledging it is being spoken to. I would recommend checking the slave address for your slave device carefully.

    If the ACK comes in properly, data transfer should happen immediately. If it doesn't, then a bit later the transaction will exit the while loops and continue to the next attempt to send data. I checked this behavior on my LaunchPad by disconnecting a slave device and saw identical waveforms to yours with the gap in the clock being during the time the NAK was present before the next transmission started.
  • Hello Ralph,

    I just checked the A0,A1 and A2 pins of the chip and I confirm they are grounded and corresponds to 0x20 address according to the datasheet. 

  • I have replaced the PCA9555 chip with assumption the chip might be bad. And still the same problem indicating the problem is with the code or controller?

  • Hello Sahil,

    I did some more checking into ACK vs NAK, and looking at your capture the slave is definitely not acknowledging the packet. When the master finishes transmission, it releases the SDA line. The slave should, when ACK'ing, take control of that line and keep it driven low through the next clock cycle. But that is not happening here. I am not sure why that would be the case though as the protocol looks right to send the slave address. You may want to post to the forums that support the PCA9555 to ask them if they have any ideas on why the PCA9555 is not ACK'ing the slave address properly.

    For reference, here is a capture of an ACK:

    And here is a capture of a NAK:

  • Hi Ralph,

    I thank you for your time and sincere efforts.  Yes I have opened the same issue on another e2e Forum (LINK)

    However, I have found the problem. The evaluation board I am using says 5V for PCA9555 and my controller is running 3.3V TTL signals which according to the datasheet of PCA9555 will not get recognized i.e. Vinput High 0.7x5V. I feeded the 5V pin with 3.3V and it fixed the problem.

    Thank you all