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.

TMS320F280049: i2c slave not responding

Part Number: TMS320F280049
Other Parts Discussed in Thread: ADS112C04

Hi Team,

I am using the following code for implementing i2c communication with ADS112C04 using micro TMS280049 as master. I wrote the code for sanity check within the configuration registers. All my commands got acknowledged by the slave device, but it doesn`t giving back the data which I am asking for. Following is the code and I am attaching the scope shots which I obtained at generation of each START signal marked as (1),(2),(3) and (4) in the code.

#include"F28x_Project.h"

void main(void)
{
// Intiate system controls, GPIO pins, interrupt

    InitSysCtrl();
    InitGpio();

    EALLOW;

        GpioCtrlRegs.GPAGMUX2.bit.GPIO26    = 2; // I2CA_SDA
        GpioCtrlRegs.GPAMUX2.bit.GPIO26     = 3;
        GpioCtrlRegs.GPAQSEL2.bit.GPIO26    = 3; // Input qualification : Asynchronous
        GpioCtrlRegs.GPAPUD.bit.GPIO26      = 0; // Pull up enable

        GpioCtrlRegs.GPAGMUX2.bit.GPIO27    = 2; // I2CA_SCL
        GpioCtrlRegs.GPAMUX2.bit.GPIO27     = 3;
        GpioCtrlRegs.GPAQSEL2.bit.GPIO27    = 3; // Input qualification : Asynchronous
        GpioCtrlRegs.GPAPUD.bit.GPIO27      = 0; // Pull up enable

        GpioCtrlRegs.GPBGMUX2.bit.GPIO56    = 0; // IRQ_1
        GpioCtrlRegs.GPBMUX2.bit.GPIO56     = 0;

        GpioCtrlRegs.GPBGMUX1.bit.GPIO34    = 0; // ADC_RST
        GpioCtrlRegs.GPBGMUX1.bit.GPIO34    = 0;
        GpioCtrlRegs.GPBDIR.bit.GPIO34      = 1; // Direction as output

    EDIS;

        GpioDataRegs.GPBCLEAR.bit.GPIO34    = 1; // ADC held at reset state

        I2caRegs.I2CMDR.bit.IRS             = 0; // I2C is disabled
        I2caRegs.I2CPSC.bit.IPSC            = 9; // System clock divider value
        I2caRegs.I2CCLKL                    = 45; // Low time divider
        I2caRegs.I2CCLKH                    = 45; // High time divider
        I2caRegs.I2CMDR.bit.BC              = 0; // 8 bits per data byte
        I2caRegs.I2CFFTX.bit.I2CFFEN        = 1; // FIFO mode enabled
        I2caRegs.I2CFFTX.bit.TXFFIL         = 10; // Transmit FIFO interrupt level
        I2caRegs.I2CFFTX.bit.TXFFRST        = 1; // Enable transmit FIFO operation
        I2caRegs.I2CFFRX.bit.RXFFRST        = 1; // Enable receive FIFO operation
        I2caRegs.I2CFFRX.bit.RXFFIL         = 10; // Receive FIFO interrupt level
        I2caRegs.I2CMDR.bit.IRS             = 1; // I2C is enabled

        GpioDataRegs.GPBSET.bit.GPIO34      = 1; // ADC released from reset state

        I2caRegs.I2CSAR.bit.SAR             = 0x40; // Slave address register

        I2caRegs.I2CCNT                     = 1; // Data count
        I2caRegs.I2CMDR.bit.MST             = 1; // Master mode
        I2caRegs.I2CMDR.bit.TRX             = 1; // Transmitter mode
        I2caRegs.I2CMDR.bit.FREE            = 1; // I2C runs in free mode
        I2caRegs.I2CMDR.bit.STP             = 1; // Generate stop signal
        I2caRegs.I2CDXR.bit.DATA            = 0x06; // RESET command
        I2caRegs.I2CMDR.bit.STT             = 1; // Generate start signal (1)

       while(I2caRegs.I2CSTR.bit.XRDY == 0 )
        {

        }


        I2caRegs.I2CCNT                     = 2; // Data count
        I2caRegs.I2CMDR.bit.MST             = 1; // Master mode
        I2caRegs.I2CDXR.bit.DATA            = 0x44; // WREG command and Configuration register 1 address
        I2caRegs.I2CDXR.bit.DATA            = 0x02; // CR 1 data
        I2caRegs.I2CMDR.bit.STP             = 1; // Generate stop signal
        I2caRegs.I2CMDR.bit.STT             = 1; // Generate start signal (2)



        while(I2caRegs.I2CSTR.bit.XRDY == 0 )
                {

                }


        I2caRegs.I2CCNT                     = 1; // Data count
        I2caRegs.I2CMDR.bit.MST             = 1; // Master mode
        I2caRegs.I2CDXR.bit.DATA            = 0x24; // RREG command and CR 1 address
        I2caRegs.I2CMDR.bit.STT             = 1; // Generate start signal (3)

        I2caRegs.I2CMDR.bit.TRX             = 0; // Receiver mode
        I2caRegs.I2CMDR.bit.STT             = 1; // Repeated start signal (4)

        I2caRegs.I2CMDR.bit.STP             = 1; // Generate stop signal


        for(;;)
        {

        }

}

 

(1)

 

(2)

(3)

(4)

As we can see in figure (4) I am receiving a NACK but no data back from slave. It should be 0x02 which is the same value I wrote on configuration register 1 but it 0x00 instead.

Please help me to identify what might be gone wrong here.

Thank you 

Vineeth

 

  • Your scope captures look good to me--they seem to match what is in the ADS112C04 datasheet. There are a few places in your code where I think you should be waiting for I2CMDR.STP to clear instead of checking XRDY, but the timing seems to have worked out anyway.

    I'm going to ask ADS112C04 support to take a look at this thread and see if they can spot an issue.

    Whitney

  • Hi Whitney,

    Thank you for your response.  Thank you for sending this to ADS112C04 support.

    Meanwhile as you said I should have been waiting for STP to clear at places. But for conditions like repeated start where should I check for stop condition, I am little bit confused here. Or is it enough that I check XRDY  before repeated start?

    My main concern is that when ever I set STT bit for a START condition the master appears to release START condition along with slave address and read/ write bit all at once. 

    Thank you,

    Vineeth

  • Vineeth N said:

    Meanwhile as you said I should have been waiting for STP to clear at places. But for conditions like repeated start where should I check for stop condition, I am little bit confused here. Or is it enough that I check XRDY  before repeated start?

    Right, only check the STP bit in conditions where you've set it--so in the case of the repeated start, you would use XRDY instead. This page has a section on repeated start--you'll see that it also suggests checking ARDY in case of a NACK, so you'll want to add that when you add NACK handling to your code.

    Vineeth N said:

    My main concern is that when ever I set STT bit for a START condition the master appears to release START condition along with slave address and read/ write bit all at once.

    That is the expected behavior of the I2C module on the F28004x.

    Whitney

  • Hi Whitney,

    I will go with XRDY and ARDY as you said.

    Whitney Dewey said:
    Right, only check the STP bit in conditions where you've set it--so in the case of the repeated start, you would use XRDY instead. This page has a section on repeated start--you'll see that it also suggests checking ARDY in case of a NACK, so you'll want to add that when you add NACK handling to your code.

    In  this page ( https://processors.wiki.ti.com/index.php/I2C_Tips#Repeated_Start ) the given code is in non repeat mode (RM = 0). The first address write is given without a STOP condition.

    /* Set the I2C controller to write len bytes */
     *I2C_ICCNT = write_len;
     *I2C_ICSAR = slaveaddr;
     *I2C_ICMDR = ICMDR_IRS | ICMDR_STT | ICMDR_TRX | ICMDR_MST | ICMDR_FREE;

    and then before read the i2c configured again with STOP condition,

    /* Set the I2C controller to read len bytes */
     *I2C_ICCNT = read_len;
     *I2C_ICMDR = ICMDR_IRS | ICMDR_STT | ICMDR_STP | ICMDR_MST | ICMDR_FREE;

    So, if we set STP bit at the time before repeated start and since the data counter already reached zero will lead to generation of a  STOP signal. After this we will not get any response until i2c is configured again. 

    Thank you

    Vineeth 

  • Hi Vineeth,

    I didn't realize this got sent to me until today.  Sorry for the delayed response.  Can you set your code to follow the same flow as the example Whitney provided and then send me scope plots and your code for me to review.

    Best regards,

    Bob B

  • Hi Bob,

    Thanks for the response. We were discussing the same problem on other thread. I got it solved yesterday only. I was using the run mode in single step instead of continuous run. When I changed it to continuous mode I am able to get the communication properly. Since I am doing it manually may be the communication was timed out in every time when I am trying to execute the code. And also I rewrote the code as per Whitney`s  suggestion.  Thank you for your support. Anyway I am attaching the code with this thread and you can have a look. Still, if I am doing anything wrong please let me know.

    
    #include"F28x_Project.h"
    
    void main(void)
    {
    // Intiate system controls, GPIO pins, interrupt
    
        uint16_t rx1 = 0x0000;
        uint16_t rx2 = 0x0000;
    
        InitSysCtrl();
        InitGpio();
    
        EALLOW;
    
            GpioCtrlRegs.GPAGMUX2.bit.GPIO26    = 2; // I2CA_SDA
            GpioCtrlRegs.GPAMUX2.bit.GPIO26     = 3;
            GpioCtrlRegs.GPAQSEL2.bit.GPIO26    = 3; // Input qualification : Asynchronous
            GpioCtrlRegs.GPAPUD.bit.GPIO26      = 0; // Pull up enable
    
            GpioCtrlRegs.GPAGMUX2.bit.GPIO27    = 2; // I2CA_SCL
            GpioCtrlRegs.GPAMUX2.bit.GPIO27     = 3;
            GpioCtrlRegs.GPAQSEL2.bit.GPIO27    = 3; // Input qualification : Asynchronous
            GpioCtrlRegs.GPAPUD.bit.GPIO27      = 0; // Pull up enable
    
            GpioCtrlRegs.GPBGMUX2.bit.GPIO56    = 0; // IRQ_1
            GpioCtrlRegs.GPBMUX2.bit.GPIO56     = 0;
    
            GpioCtrlRegs.GPBGMUX1.bit.GPIO34    = 0; // ADC_RST
            GpioCtrlRegs.GPBGMUX1.bit.GPIO34    = 0;
            GpioCtrlRegs.GPBDIR.bit.GPIO34      = 1; // Direction as output
    
        EDIS;
    
            GpioDataRegs.GPBCLEAR.bit.GPIO34    = 1; // ADC held at reset state
    
            I2caRegs.I2CMDR.bit.IRS             = 0; // I2C is disabled
            I2caRegs.I2CPSC.bit.IPSC            = 9; // System clock divider value
            I2caRegs.I2CCLKL                    = 45; // Low time divider
            I2caRegs.I2CCLKH                    = 45; // High time divider
            I2caRegs.I2CMDR.bit.BC              = 0; // 8 bits per data byte
            I2caRegs.I2CFFTX.bit.I2CFFEN        = 1; // FIFO mode enabled
            I2caRegs.I2CFFTX.bit.TXFFIL         = 10; // Transmit FIFO interrupt level
            I2caRegs.I2CFFTX.bit.TXFFRST        = 1; // Enable transmit FIFO operation
            I2caRegs.I2CFFRX.bit.RXFFRST        = 1; // Enable receive FIFO operation
            I2caRegs.I2CFFRX.bit.RXFFIL         = 10; // Receive FIFO interrupt level
            I2caRegs.I2CMDR.bit.IRS             = 1; // I2C is enabled
    
            GpioDataRegs.GPBSET.bit.GPIO34      = 1; // ADC released from reset state
    
            DELAY_US(1300);
            while(I2caRegs.I2CSTR.bit.BB);
    
            I2caRegs.I2CSAR.bit.SAR             = 0x40; // Slave address register
    
            I2caRegs.I2CMDR.all                 = 0x66A0; // I2CMDR = ICMDR_FREE | ICMDR_STT | ICMDR_MST | ICMDR_TRX | ICMDR_RM | ICMDR_IRS | ICMDR_BC
            while(!(I2caRegs.I2CSTR.bit.ARDY));
            I2caRegs.I2CMDR.bit.STP             = 1; // Generate stop signal
    
            while(I2caRegs.I2CMDR.bit.STP || I2caRegs.I2CSTR.bit.BB);
    
            I2caRegs.I2CCNT                     = 1; // Data count
            I2caRegs.I2CDXR.bit.DATA            = 0x06; // RESET command
            I2caRegs.I2CMDR.all                 = 0x6E20; // I2CMDR = ICMDR_FREE | ICMDR_STT | ICMDR_STP | ICMDR_MST | ICMDR_TRX | ICMDR_IRS | ICMDR_BC
    
            while(I2caRegs.I2CMDR.bit.STP || I2caRegs.I2CSTR.bit.BB);
    
            I2caRegs.I2CCNT                     = 2; // Data count
            I2caRegs.I2CDXR.bit.DATA            = 0x44; // WREG command and Configuration register 1 address(3)
            I2caRegs.I2CDXR.bit.DATA            = 0x02; // CR 1 data
            I2caRegs.I2CMDR.all                 = 0x6E20; // I2CMDR = ICMDR_FREE | ICMDR_STT | ICMDR_STP | ICMDR_MST | ICMDR_TRX | ICMDR_IRS | ICMDR_BC
    
            while(I2caRegs.I2CMDR.bit.STP || I2caRegs.I2CSTR.bit.BB);
    
            I2caRegs.I2CCNT                     = 1; // Data count
            I2caRegs.I2CDXR.bit.DATA            = 0x24; // RREG command and CR 1 address
            I2caRegs.I2CMDR.all                 = 0x6620; // I2CMDR = ICMDR_FREE | ICMDR_STT | ICMDR_MST | ICMDR_TRX | ICMDR_IRS | ICMDR_BC
    
            while(!(I2caRegs.I2CSTR.bit.ARDY));
    
            I2caRegs.I2CMDR.all                 = 0x6C20; // // I2CMDR = ICMDR_FREE | ICMDR_STT | ICMDR_STP | ICMDR_MST | ICMDR_IRS | ICMDR_BC
                    
            while (!(I2caRegs.I2CFFRX.bit.RXFFST) || I2caRegs.I2CMDR.bit.STP);
    
            I2caRegs.I2CSAR.bit.SAR             = 0x41; // Slave address register
    
            I2caRegs.I2CMDR.all                 = 0x66A0; // I2CMDR = ICMDR_FREE | ICMDR_STT | ICMDR_MST | ICMDR_TRX | ICMDR_RM | ICMDR_IRS | ICMDR_BC
            while(!(I2caRegs.I2CSTR.bit.ARDY));
            I2caRegs.I2CMDR.bit.STP             = 1; // Generate stop signal
    
            while(I2caRegs.I2CMDR.bit.STP || I2caRegs.I2CSTR.bit.BB);
    
            I2caRegs.I2CCNT                     = 1; // Data count
            I2caRegs.I2CDXR.bit.DATA            = 0x06; // RESET command
            I2caRegs.I2CMDR.all                 = 0x6E20; // I2CMDR = ICMDR_FREE | ICMDR_STT | ICMDR_STP | ICMDR_MST | ICMDR_TRX | ICMDR_IRS | ICMDR_BC
    
            while(I2caRegs.I2CMDR.bit.STP || I2caRegs.I2CSTR.bit.BB);
    
            I2caRegs.I2CCNT                     = 2; // Data count
            I2caRegs.I2CDXR.bit.DATA            = 0x44; // WREG command and Configuration register 1 address(3)
            I2caRegs.I2CDXR.bit.DATA            = 0x02; // CR 1 data
            I2caRegs.I2CMDR.all                 = 0x6E20; // I2CMDR = ICMDR_FREE | ICMDR_STT | ICMDR_STP | ICMDR_MST | ICMDR_TRX | ICMDR_IRS | ICMDR_BC
            
            while(I2caRegs.I2CMDR.bit.STP || I2caRegs.I2CSTR.bit.BB);
    
            I2caRegs.I2CCNT                     = 1; // Data count
            I2caRegs.I2CDXR.bit.DATA            = 0x24; // RREG command and CR 1 address
            I2caRegs.I2CMDR.all                 = 0x6620; // I2CMDR = ICMDR_FREE | ICMDR_STT | ICMDR_MST | ICMDR_TRX | ICMDR_IRS | ICMDR_BC
            
            while(!(I2caRegs.I2CSTR.bit.ARDY));
            
            I2caRegs.I2CMDR.all                 = 0x6C20; // I2CMDR = ICMDR_FREE | ICMDR_STT | ICMDR_STP | ICMDR_MST | ICMDR_IRS | ICMDR_BC
            
            while (I2caRegs.I2CFFRX.bit.RXFFST == 1 || I2caRegs.I2CMDR.bit.STP);
    
            rx1 = I2caRegs.I2CDRR.bit.DATA;
            rx2 = I2caRegs.I2CDRR.bit.DATA;
    
            for(;;)
            {
    
            }
    
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
     

    Best Regards,

    Vineeth

  • Hi Vineeth,

    I'm glad to hear that you have made progress with Whitney's help.  Your code appears to follow the example for repeated start, but the only way to truly verify is to observe the behavior with a scope or logic analyzer.  However, if you are now able to effectively communicate it would appear that the issue is resolved.

    Best regards,

    Bob B

  • Hi Bob,

    The issue is resolved now. Thank you for your support. 

    Best regards,

    Vineeth