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.

'5438 I2C master tx always showing busy

Other Parts Discussed in Thread: MSP430F5438, TPS65023

Hi there,

I'm trying to communicate over I2C using a '5438 as master with an LCD on the USCI B3 line.  I can use P10OUT to manually toggle the SDA and SCL lines with the slave connected.  Whenever I initialize the port, however, the UCBBUSY bit is always set.  This is the initialization code:

P10SEL |= BIT1 | BIT2; // Assign I2C pins to USCI_B3
UCB3CTL1 |= UCSWRST; // Enable SW reset
UCB3CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
UCB3CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
UCB3BR0 = 160; // fSCL = SMCLK/160 = ~100kHz
UCB3BR1 = 0;
UCB3I2CSA = 0x28; // Slave Address is 050h
UCB3CTL1 &= M_CPL(UCSWRST); // Clear SW reset, resume operation
UCB3IE |= UCTXIE | UCNACKIE; // Enable TX and NACK interrupt

At this point in the code, all of the IFG's are cleared but USBBUSY is set.  My o-scope show SCL low and SDA high.  When I signal transmission...

UCB3CTL1 |= UCTR + UCTXSTT;

The interrupt is called.  I fill the UCB3TXBUF buffer but nothing has changed on the bus.

 My question is, what causes the UCBBUSY bit to be set?  Could something be holding the SCL line low?  There is another slave on the I2C bus...

Thanks in advance for your help,
Drogo

  • The UCBBUSY bit gets set when SCL is low and the USCI wants to send data. The question is now: Why is SCL low? Of course, there could be another slave device pulling the SCL low. But why should it do that? Maybe the value for the pullup resistors is to high? What value did you use?

    Regards,
    Johannes

  • Can the error be reproduced using similar or modified code example from the web, using a TI Board and 2 MSP430’s?

    Also what value of pull-ups are you using?

  • Hi,

    I am also facing the same problem. In MSP430F5438, I2C doesn't work as UCBBUSY is always set.

    My pull up resistors are 10K.

    SCL is always high and SDA is always low.

    Regards,

    Mohammadi

     

     

  • Mohammadi Bharmal said:
    UCBBUSY is always set.
    SCL is always high and SDA is always low.

    That cannot be. UCBBUSY is set when SCL is low while the master expects it high. A low SCL indicates that either another master is clockign the bus or a slave is busy and stretches the clock until it is ready again. When SCL is always high, UCBBUSY shouldn't be set. Did you mix up the two?

    What is your port setup? Are there pulldowns active on the port pins? Or set to low output? Any shortcut on the lines? and the most important question: Do you use the right port pins?

  • Hi,

    There was a mistake in the sequence of events that I was doing...

    Here is the code that works perfectly..

    This is a I2C driver of TI's TPS65023 for MSP430F54x :

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    #include "msp430x54x.h"

    //------ TPS65023 Registers ------
    #define VERSION     0x00
    #define PGOODZ     0x01
    #define MASK         0x02
    #define REG_CTRL   0x03
    #define CON_CTRL  0x04
    #define CON_CTRL2 0x05
    #define DEFCORE     0x06
    #define DEFSLEW     0x07
    #define LDO_CTRL   0x08

    //------ Functions ------
    void read_all_reg(void);
    void program_ldo(char);

    //------ Global Variables ------
    unsigned char RXData;

    //------ main starts here ------
    void main(void)
    {
      long i;

      //disable watchdog
      WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
     
      //just a delay
      for(i=0;i<10000;i++);
      
      //I2C pins
      P10SEL |= 0x06;                           // Assign I2C pins to USCI_B3
     
      //I2C Control registers
      UCB3CTL1 |= UCSWRST;                      // Enable SW reset
      UCB3CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
      UCB3CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK
      UCB3BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz
      UCB3BR1 = 0;
      UCB3I2COA = 0x0000;
      UCB3I2CSA = 0x0048;                         // Slave Address is 048h = TPS65023
      UCB3CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
     
      //LDOs set
      program_ldo(OV3640);
     
      //while loop
      while (1)
      {
        read_all_reg();
      }
    }

    void read_all_reg(void)
    {
      long i;
      int j;
     
      for(j=0;j<9;j++)
      { 
        //Just a delay
        for(i=0;i<100;i++);

        //Start Transmitter
        UCB3CTL1 |= UCTR + UCTXSTT;             // I2C start condition
       
        //Load Data
        while(!(UCB3IFG & UCTXIFG));            // Transmit ready ??
        UCB3TXBUF = j;                          // Load TX buffer

        while(UCB3CTL1 & UCTXSTT);              // Start condition sent?   
        while(UCB3IFG & UCNACKIFG);             // NACK ??
        while(!(UCB3IFG & UCTXIFG));            // Transmit ready ??
            
        //Restart Receiver
        UCB3CTL1 &= ~UCTR;                      // I2C RX
        UCB3CTL1 |= UCTXSTT;                    // Repeated start condition
        UCB3IFG &= ~UCTXIFG;
        while(UCB3CTL1 & UCTXSTT);              // Start condition sent?
      
        //Stop
        UCB3CTL1 |= UCTXSTP;                    // I2C stop condition   

        //Receive data
        while(!(UCB3IFG & UCRXIFG));   
        RXData = UCB3RXBUF;                     // Get RX data         
      }     
    }

    void program_ldo(char camera)
    {
        long i;
       
        //Just a delay
        for(i=0;i<100;i++);

        //I2C Start Transmitter   
        UCB3CTL1 |= UCTR + UCTXSTT;             // I2C start condition
       
        //Load Data
        while(!(UCB3IFG & UCTXIFG));            // Transmit ready ??
        UCB3TXBUF = LDO_CTRL;                   // Load TX buffer

        while(UCB3CTL1 & UCTXSTT);              // Start condition sent?   
        while(UCB3IFG & UCNACKIFG);             // NACK ??
        while(!(UCB3IFG & UCTXIFG));            // Transmit ready ??

        UCB3TXBUF = 0x73;                     // Load TX buffer

        while(UCB3IFG & UCNACKIFG);             // NACK ??
        while(!(UCB3IFG & UCTXIFG));            // Transmit ready ??
       
        //Stop
        UCB3CTL1 |= UCTXSTP;                    // I2C stop condition   
            
    }

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

     

  • I am using internal pull up resistors, using,

    P3REN |=0x80;

    But both my clk and data are low.

    Can someone please letme know if internal pull up could be used for i2c this way.

  • Simle answer: No. In most cases the I2C pullups should be in the 5-10kOhm range. Internal resistors are around 40kOhm. And maybe the internal resistors are automatically disabled when you enable the ports for I2C use, I am not sure about that - I never tried because their value is to big anyway.

    Regards,
    Johannes

     

  • Unless there is a heavy load on the lines (several I2C slaves), the internal 40k pullups should do fine. If they are active at all. If 40K is too big for 1 slave, 10k would be too ig for 4 slaves too.
    Reading the 5438 datasheet (I don't know which processor is actually in question here)  reveals that the pullups are independently of the PxSEL bits and active if PxREN.y is 1 and PxDIR.y is 0.
    Only for those port pins where the module is analog (ADC, VREF, XTAL), the PxSEL will disable the pullups.

    The family users guide tells, that PxDIR needs to be set according to the module function:
    PxDIR bits for I/O pins that are selected for other functions must be set as required by the other function.
    If doing so, this of course would disable the pullups. The device datasheet, however, tells that the direction is controlled by the USCI module (as required by the protocol, since SDA constantly changes between input and output), so setting the pins as input should enable the pullups while the USCI module still switches between input and output. (the USCI will also disable the high-side of the output driver). There's still some uncertainity left.

    So if the lines stay low, then  I'd re-check the port initialisaion code. It's likely that there' s something wrong.

    Re-reading the question I might add:

    P3REN |=0x80;

    will only enable pullups on one pin (UCB1SDA on the 5438) only. And since P3OUT isn't written to, it is likely that they are set as pulldowns. (the datasheet does not list any initialisation value).

  • Krish,

    On older families such as the 2xx, the pullups can be configured and used for I2C - but for reasons Johannes mentioned I would not recommend it for a robust I2C design. If you are trying to do a proof-of-concept implementation its probably ok to use the internal pullups.

    For the 5xx family, IF the direction of the port pin is output,  the resistor (pull up or pull down) is controlled by the PxOUT setting (see section 8.2.4 5xx UG). So the internal pullups cannot be used for I2C (as direction is dependent on I2C module).

    Regards,

    Priya

  • Hi, Thank you all for the reply.

    I am using MSP430f5438 experimenter board to test i2c functionality.

    I am using the code at, http://focus.ti.com/mcu/docs/mcuprodcodeexamples.tsp?sectionId=96&tabId=1468, (in master mode multiple bytes). I just thought of testing it on the board/kit (before customising it to my requ.,),  But, when the code  executes   UCB0CTL1 |= UCTR + UCTXSTT, the clock goes low and the data line is permanently high..

    Without the slave, I thought on oscilloscope i could atleast observe the slave address after start condition. But, am not seeing it.

    regards,

     

  • Priya Thanigai said:
    see section 8.2.4


    Indeed, so the ports must be set to inputs for the pullups to work.
    Then there's section 8.2.6 telling that you must set the proper direction. Which one for SDA? it constantly changes direction, so you can as well leave the PxDIR on input (and the pullups active).
    Then there's the device datasheet, telling that the USCI module will set the direction as required, independently of PxDIR, but the port schematics does not tell how the USCI module does it and whether it will affect the pullups or not. So from the datasheet and user guide alone you cannot tell anything. You can only experiment and see what happens. (I filed a datasheet comment about this)

    krish said:
    Without the slave, I thought on oscilloscope i could atleast observe the slave address after start condition. But, am not seeing it.


    Without a pullup, an oscilloscope cannot differentiate between low signal and open/high-impedance. The voltage on the probe is zero even if you do not attach the probe to anything at all. There might as well be a signal but you simply cannot see it. Like making gestures in a dark room. Or blinking with a flashlight with the batteries removed.

     

  • I filed a document comment about this and got the following response:

    Our engineer states that if the USCI sets the module to input direction, the pull up or pull down can be used. If the USCI sets the module to output direction, pull up or pull downs are disabled. For I2C, since the direction is set to output, the pullups are not readily available. The documentation will be made clearer and thanks for the feedback.

  • Hello all,

    I'm facing the same problem on the F4132, but in my case both lines are Hi, just like Busy bit. As soon the UCB0 config is done this bit goes high, and the lines doesn't work.

    Any tip?

    Tks...

**Attention** This is a public forum