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.

Piccolo 28035 - I2C issues.



Attempting to communicate with I2C device. START + Address + R/W delivered with no ACK. I2C peripheral stops sending SCL clocks after the first cycle with no ACK from device. Is there a setting that would allow extra clocks (SCL) to allow the device more time to acknowledge?

I2C Device - Newhaven LCD: NHD C160100DiZ-FSW-FBW

 

  • That is not how the protocol works.  If the slave device, in this case the Newhaven LCD, does not acknowledge the Start+Address+R/W, then the I2C peripheral will rightfully halt operation and provide an indication to your application layer of this.  Your software will then need to decide what action to take.  If you want to retry, you will need to terminate that specific transaction and try again.  If you decide to "move on", you still need to terminate the transaction to place the I2C bus into an idle state.

  • Below is an excerpt from the spec. which gives us more things to look for:  

    When SDA remains HIGH during this 9th clock pulse, this is defined as the Not Acknowledge signal. The master can then generate either a STOP condition to abort the transfer, or a repeated START condition to start a new transfer. There are five conditions that lead to the generation of a NACK:

    1. No receiver is present on the bus with the transmitted address so there is no device to respond with an acknowledge.

    2. The receiver is unable to receive or transmit because it’s performing some real-time function and is not ready to start communication with the master.

    3. During the transfer the receiver gets data or commands that it does not understand.

    4. During the transfer, the receiver cannot receive any more data bytes.

    5. A master-receiver needs to signal the end of the transfer to the slave transmitter.

     

  • Thank you for your responses.

    New developments on this issue.  I was able to communicate with the LCD by using GPIO lines and "bit banging" the SDA and SCL data out. When I do that, I flip the SDA line from an output to an input right before the 9th SCL clock and it works fine, I get the ACK from the LCD and I can observe it on the scope. This way I can communicate and use the display. I would prefer not to do this, I would like to use the peripheral instead.

    ** Experimenting with GPIO Lines:  I did not flip the SDA line to an input before the 9th clock,  when I looked at the signal on the scope I saw a slight drop in the voltage but not enought to make it to the "Low" level threshold. 

    When using the SDA and SCL lines on the Piccolo (GPIO29 and 28 as I2C)  I send out the exact same START+SLAVE+R/W and I can see the same slight drop in voltage tha I described above (** Experimenting) , on the SDA line. It seems like the I2C controller does not release the SDA line for the LCD to pull it down and ACK. But it definitely seems that it is trying to ACK.  Any comments on this? Please let me know. Thank you.

    Adnorin

  • Adnorin,

    Can you post the code snippet for the GPIO approach that works? Just the piece that bangs out SDA/SCL.

    Thanks

    Brad  

  • Here is the snippet....

    Thank you again. Have a good weekend!

    /*****************************************************/
    void delay(int intDelayTime)
    {
        int i;
        for(i=0; i<2*intDelayTime; i++);

    }
    /*****************************************************/
    void I2C_out(unsigned char j) //I2C Output
    {
        int n;
        unsigned char d;
        d=j;
        delay(intPeriod);
        for(n=0;n<8;n++)
        { //send 8 bits
            if((d&0x80)==0x80) //get only the MSB
            {
                SDA=1; //if 1, then SDA=1
            }
            else
            {
                SDA=0; //if 0, then SDA=0
            }
            d=(d<<1); //shift data byte left
            delay(intPeriod);
            SCL = 0;
            delay(intPeriod);
            SCL = 1; //clock in data
            delay(2*intPeriod);
            SCL = 0;   
            delay(intPeriod);   
        }

        EALLOW;
        GpioCtrlRegs.GPBDIR.bit.GPIO34 = GPIO_INPUT;
        EDIS;
      
        delay(2*intPeriod);
        SCL = 1;
        delay(2*intPeriod);
        SCL=0;

        while(SDA==1)
        { //wait here until ACK
            delay(intPeriod);
            SCL=1;
            delay(intPeriod);
            SCL=0;
            delay(intPeriod);
        }

        delay(intPeriod);
        SCL=0;

        EALLOW;
        GpioCtrlRegs.GPBDIR.bit.GPIO34 = GPIO_OUTPUT;
        EDIS;

    }
    /*****************************************************/

  • With your software bit-bang approach are you doing it on the Piccolo device or from another microcontroler?

    If your doing it from the Piccolo are you using the same I/O pins, just reconfiguring them from I2C mode to GPIO mode?  (GPIO28/29 or 32/33)?

    If so what state are the internal pull-ups set to?

    //    GpioCtrlRegs.GPAPUD.bit.GPIO28 = 0;    // Enable pull-up for GPIO28 (SDAA)

    //    GpioCtrlRegs.GPAPUD.bit.GPIO29 = 0;    // Enable pull-up for GPIO29 (SCLA)

    Brad

  • Yes, I am doing it from the same Piccolo. I am using different pins, for the SDA and SCL GPIO31 and 34.  I did try changing the settings for the GPAPUD, no success. Tried both 0 and 1.  No difference. Thanks again.

    Adnorin

  • Let me start by thanking you for all the responses with good information.

    I finally got the I2C peripheral working on the Piccolo. I connected the same pins (GPIO28 and GPIO29 configured as I2C) to a good known I2C device used in a different product and it displayed the same behavior. It seemed that the device would try to ACK but the Piccolo would not release the line (Open Drain Mode) for the device to pull it down all the way to GND. Then I switched the lines from the 28 and 29 to the secondary I2C port on the Piccolo (GPIO32 and 33 configured as I2C) and it worked! It worked on the I2C I/O expander and it worked on the LCD.  There must be something wrong with GPIO28 and 29 on the piccolo when configured as I2C (SDA and SCL) could be my piccolo board or all, I am not sure. Thanks again for your help.

    Adnorin 

  • On more suggestion. I'm not sure if the question about pullups above was answered. You should not rely on the internal pullups of the device as the pullups for the I2C. You need to use external pullups.

     

  • Yes I am using external pullups.  I tried different values too (2K, 5K, 10K, 12K and 15K). It currently has 5K pullups connected to GPIO32 and 33 configured as SDA and SCL.  It is working fine on those pins. It did not work on GPIO28 and 29 configured as SDA and SCL, which was my first attempt with the Piccolo.  This is my first time using the 28035 but we have products that use I2C and I have worked on those quite extensively, just different processors (DSPs: 2808, 2812, 6410, 6713 and 6727). Thank you again for all the advice.

    Adnorin

  • Matt,

      Does this suggestion about not using the internal pullups for I2C also apply to the 28335?

    Steve

  • Hello Adnorin,
    I am having the same exact problem on my c2000 launchpad using the TMS230x280x27. The New Haven LCD does not respond to the slave address. Unfortunately I tried switching to the alternate I2c port (GPIO32&33) but I am still having the same issues. Have you been able to uncover anymore information that might assist me?
    Sincerely
    James
  • I have the same problem with this launch pad but with other device... How you solve this problem?? Thanks!!
  • Rodrigo,

    If the slave does not acknowledge the address, then either the address is incorrect or the slave has a problem. Some datasheets left-shift the address by one bit to reflect the format of the I2C address byte.