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.

I2C hangs on while(UCB1CTL1 & UCTXSTT);

Other Parts Discussed in Thread: MSP430F5510, MSP430G2553, MSP430F2132

I'm trying to set up I2C communication between an MSP430F5510 (set as master), and one slave.

I have 10K pullups on both SDA and SCL

To begin with I'm just trying to write to the slave device.

I would like to write to the slave just by polling register values and without the use of interrupts. Please see my code at the end of this message.

The problem I'm having is that I initiate a write start condition with UCB1CTL1 |= UCTR + UCTXSTT;

I then check to make sure the start condition was sent with while(UCB1CTL1 & UCTXSTT); The code hangs up here. For some reason the UCTXSTT bit is never cleared.

If I comment out this line and single step through the code everything works just fine. But as soon as I try to run it full speed of course it messes up.

One strange thing is if I switch to a read operation with UCB1CTL1 &= ~UCTR and then check to see if the start condition was sent, the code while(UCB1CTL1 & UCTXSTT); does not hang. Can anyone explain why this is the case?

 

#include <msp430f5510.h>

void main(void)

{

WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

P4SEL |= 0x06;                            // Assign I2C pins to USCI_B0

UCB1CTL1 |= UCSWRST;                      // Enable SW reset

UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode

UCB1CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset

UCB1BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz

UCB1BR1 = 0;

UCB1I2CSA = 0x20;                         // Slave Address is 20h

UCB1CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation

//**Transmit 0x03 to slave, which is the pointer to the read address

while (UCB1CTL1 & UCTXSTP);           // Ensure stop condition got sent

UCB1CTL1 |= UCTR + UCTXSTT;           // I2C TX, start condition

while(UCB1CTL1 & UCTXSTT);            // Start condition sent? <-*CODE HANGS HERE*

//**Write to configuration register

UCB1TXBUF = 0x03;

while (UCB1IFG & !UCTXIFG); // Wait for TX buffer to empty

//**Set up inputs and outputs

UCB1TXBUF = 0x70;

while (UCB1IFG & !UCTXIFG); // Wait for TX buffer to empty

//**Send stop condition then start condition

UCB1CTL1 |= UCTXSTP;                  // I2C stop condition

while (UCB1CTL1 & UCTXSTP);           // Ensure stop condition got sent

UCB1CTL1 |= UCTXSTT;      // I2C TX, start condition

while(UCB1CTL1 & UCTXSTT);            // Start condition sent? <-*CODE HANGS HERE*

//**Write to output register

UCB1TXBUF = 0x01;

while (UCB1IFG & !UCTXIFG); // Wait for TX buffer to empty

//**Turn on LED's

UCB1TXBUF = 0x0A;

while (UCB1IFG & !UCTXIFG); // Wait for TX buffer to empty

UCB1CTL1 |= UCTXSTP;                  // I2C stop condition

while (UCB1CTL1 & UCTXSTP);           // Ensure stop condition got sent

while(1);

}

  • RobK said:
    or some reason the UCTXSTT bit is never cleared.

    The only reason I can thnk of is that someone or something is holding SCL low. You say you have pullups on the lines (no pullups are the mos tcommon cause for this, especially since on many MSPs, the internal pullups are disabled when the port is used as output)

    You should check the state of the lines with a scope (or with a multimeter, if you don't have a scope).

    Independently of this, your code  has a problem. After STT is clear, you must check whether UCNACKIFG has been set. If so, it means that no slave has answered. In this case you should send a stop condition and bail out. Else you'll be waiting forever of TXIFG getting set (TXIFG is set immediately when you set UCSTT in transmit mode and you can already write to TXBUF at this point, but if a NACK is received because no slave answered, the content of TXBUF is discarded or the still set TXIFG bit is cleared)

  • Hi RobK,

    I have the same identical problem with the I2C peripheral of my MSP430G2553 microcontroller.

    I also noticed that a lot of users have similar problems with the I2C used in polling mode.

    How did you fix the problem?

    I've also checked with an oscilloscope: after the start condition, the slave address is sent and  the clock remains low.

    If I manually reset the UCTXSTT bit, then the program exit the while loop, the data is sent, but I encounter the same problem after the data is sent (clock is still low)

    By the way, I have external pull up resistor.

    Thanks in advance

  • Hi friend,

    Have you fixed your problem please? I meet the same problem as you met, except my controller is MSP430F2132.

    If you have fix the problem, could you give me some advice please? Thanks a lot!

    Kind regards,

    Lijun

  • If you were using a LaunchPad, it might be necessary to remove the jumper that enables the green LED on P1.6 which is also required for I2C.

  • Removing the P1.6 jumper fixed it for me

  • Thanks guys, and I didn't use the lanchpad, but fabricated a PCB and soldered the MCU and Accelerometer on board, the ADXL346 does not acknowledge the MCU. 

    And what 's the value of the pull-up resistors you guys used please?

    kind regards

  • check the errata of the device for i2c bus.

    Regards

    Gastón

  • Hi Robk,

    the below write and read functions works for me,i hope it helps for u. I used UCB0,so  instead of UCB0 use UCB1 in the function

    void ei_vI2cWrite(Uint16 CommandByte, Uint16 Data)
    {
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition

    while((IFG2 & UCB0TXIFG) == 0);
    UCB0TXBUF = CommandByte;

    while((IFG2 & UCB0TXIFG) == 0);
    UCB0TXBUF = Data;

    while((IFG2 & UCB0TXIFG) == 0);
    UCB0CTL1 |= UCTXSTP; // I2C stop condition
    }

    Uint16 ei_uiI2cRead(Uint16 CommandByte)
    {
    Uint16 ui_Data = 0;

    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition

    while((IFG2 & UCB0TXIFG) == 0);
    UCB0TXBUF = CommandByte;

    while((IFG2 & UCB0TXIFG) == 0);
    UCB0CTL1 |= UCTXSTP;

    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTL1 &= ~UCTR; // Receiver
    UCB0CTL1 |= UCTXSTT; // Start bit
    while(UCB0CTL1 & UCTXSTT); // Wait till start bit transmitted
    UCB0CTL1 |= UCTXSTP; // Tx Stop bit

    while((IFG2 & UCB0RXIFG) == 0);
    ui_Data = UCB0RXBUF;

    return ui_Data;
    }

    regards,

    Saravanan

  • saravanan chandrasekaran said:

    Hi Robk,

    the below write and read functions works for me,i hope it helps for u. I used UCB0,so  instead of UCB0 use UCB1 in the function

    void ei_vI2cWrite(Uint16 CommandByte, Uint16 Data)
    {
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition

    while((IFG2 & UCB0TXIFG) == 0);
    UCB0TXBUF = CommandByte;

    while((IFG2 & UCB0TXIFG) == 0);
    UCB0TXBUF = Data;

    while((IFG2 & UCB0TXIFG) == 0);
    UCB0CTL1 |= UCTXSTP; // I2C stop condition
    }

    Uint16 ei_uiI2cRead(Uint16 CommandByte)
    {
    Uint16 ui_Data = 0;

    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition

    while((IFG2 & UCB0TXIFG) == 0);
    UCB0TXBUF = CommandByte;

    while((IFG2 & UCB0TXIFG) == 0);
    UCB0CTL1 |= UCTXSTP;

    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTL1 &= ~UCTR; // Receiver
    UCB0CTL1 |= UCTXSTT; // Start bit
    while(UCB0CTL1 & UCTXSTT); // Wait till start bit transmitted
    UCB0CTL1 |= UCTXSTP; // Tx Stop bit

    while((IFG2 & UCB0RXIFG) == 0);
    ui_Data = UCB0RXBUF;

    return ui_Data;
    }

    regards,

    Saravanan

    The code above does not check for a possible NACK. Datasheet says that UCTXSTT is cleared as soon as the slave acknowledges the address (Master Transmitter Mode, p471 F2x MSP430 Family User's Guide. )

    Why does the code  still hangs checking for UCTXSTT even if I check for NACK while polling UCTXSTT

  • Santiago Barros said:
    Why does the code  still hangs checking for UCTXSTT even if I check for NACK while polling UCTXSTT

    Because teh USCI in master transmit mode stops at the ACK cycle until you write the first byte to TXBUF. If you don't write to TXBUF, teh USIC doesn't complete the start byte cycle and doesn't clear STT.

    If you do and the slave doesn't ACK, the byte written to TXBUF is discarded and UCNACKIFG is set. Else transmisison of the first byte starts immediately.

    This isn't obvious from plain thinking, but the flow diagram in the users guide properly tells this.

  • The problem is that the micro do not reset any flags when polling the UCaxCTL1 register in a while loop. The only solution is to poll the UCaxIFG register in a while loop.

    TI should have this in the erata or have it checked and verified...

  • Reuel Haavrahami said:
    The problem is that the micro do not reset any flags when polling the UCaxCTL1 register in a while loop.

    Oh, it does - if the prerequisites are met. The diagram in the users guide shows clearly (even though I must admit that I missed it too at first) that in master TX mode, you have to write to TXBUF (or set UCTXSTP) before the USCI finishes the ACK cycle of the start byte and clears UCTXSTT.

  • Hi Jens

    You are correct. Set start bit, write the tx buf and then wait for the SST bit to clear, or for the IFG register to change. Or write the adrress, start bit and stop bit and only the address will be sent.

    I however thing the datasheet and the diagram are misleading. The datasheet does not mention the requirement to write the tx buf in order to start the start condition. On the contrary it had me believe the setting of  the SST bit would start the sending of the address, while one has to wait for that to complete before writhing the tx buffer. The diagram also indicates that the tx buffer should be written after the address has already been sent. All this had me think that writing the tx buffer before the end of the address would upset the USCI module. Very misleading...

    Any way, problem solved, moving on....

  • Reuel Haavrahami said:
    or for the IFG register to change

    Yes, but don't only check for TXIFG. While in a normal transfer, indeed after sending the  start byte and starting to send the first data byte, TXIFG is set again, there might be a NACK form the slave. In this case NACKIFG is set instead. (and on 2x family, NACKIFG is in a different register than TXIFG)

    Reuel Haavrahami said:
    I however thing the datasheet and the diagram are misleading. The datasheet does not mention the requirement to write the tx buf in order to start the start condition.

    The diagram clearly shows a gap after SLA/W block and before the ACk cycle, with the comment "Bus stalled until data available -> user action: write data to TXBUF". The 'UCTXSTT=0' comes after the ACK cycle. Can't be more clearly. written.

    Reuel Haavrahami said:
    n the contrary it had me believe the setting of  the SST bit would start the sending of the address

    Which it does.

    Reuel Haavrahami said:
    while one has to wait for that to complete before writhing the tx buffer.

    One has to wait until UCTXIFG is set - which happens right at the beginning, when the start condition begins. Also clearly marked in the diagram. ("S" comment: UCTXIFG=1, TXBUF discarded, when user sets UCTR and UCTXSTT).

    Reuel Haavrahami said:
    All this had me think that writing the tx buffer before the end of the address would upset the USCI module. Very misleading...

    Well, the comments are marking a point where it won't proceed without user interaction. It doe snot mean that user interaction can't happen before (but after previous control point).
    However, in any case, the diagram clearly hows that writing to TXBUF is required before the ACK cycle can complete, and clearing UCTXSTT happens after the ACK cycle.

  • Hi Jens

    Very good. Now I see the actual block in the diagram that you are talking about... Wow, that should be put in red and bold letters perhaps for those of us who don't like to read manuals that much... :D

    Thanks

  • Thanks for the code Saravanan,

    I would like just to point out that CommantByte in ei_uiI2cRead function should rather be Uint8, instead of uint16:

    Uint16 ei_uiI2cRead(Uint8 CommandByte)

  • HI Jens,

    My code gets stuck at the first while loop even though I did as you suggested and wrote to TX buffer right after I generated a start condition. Please do you know what the problem could be?

    Thanks

    void Reg_Write(unsigned char address, unsigned long data){

    int i = 0; // Counter for shifting data to serial transmit buffer

    // Set slave address, set R/_W to write, and generate start condition
    UCB1I2CSA = SLAVE_ADDRESS;
    UCB1CTL1 |= UCTR + UCTXSTT;
    UCB1TXBUF = address; // transmit register address
    while ((UCB1CTL1 & UCTXSTT) != 0); // wait until start condition is generated

    if ((UCB1STAT & UCNACKIFG) != 0) { // Check if slave has acknowledged transmission
    UCB1CTL1 |= UCTXSTP; // Abort transmission if slave does not acknowledge
    } else {

    while( !(UCB1IFG & UCTXIFG) ); // wait until byte (address) has been sent

    // Loop to send data (MSB first) to transmit buffer for transmission to slave
    for (i = 16; i >= 0; i -= 8){
    UCB1TXBUF = (data >> i);
    while ( !(UCB1IFG & UCTXIFG) );
    }

    UCB1CTL1 |= UCTXSTP; // generate stop condition
    while ( !(UCB1IFG & UCTXIFG) );
    }


    }
  • There are three things I can think of that migt cause the code to stay with UCTXSTT set:

    1) you don' thave a clock. If your clock source isn't clocked, the I2C state machine cannot proceed. It may also be that your clock divider isn't high enough and your resulting I2C clock is way above teh 400kHz maximum (you shouldn't go above 100kHz anyway unless you have some experience handling this on the hardware side), causing the state machine to crash.

    2) SDA is low

    3) SCL is low

    When SDA is low, the USIC cannot generate the start condition, as this is a high->low transistion while SCL is high. The USCI cannot pull SDA high itself, as I2C is an open-collector bus. reason might be an insufficient (not strong enough) or unpowered pull-up resistor or a slave or second master (or an unpowered or crashed slave) that keeps SDA low. Same applies to SCL. If SCL is low, this measn soemone is keeping the bus busy (even if it is just a weak/unpowered/missing pull-up) and the USCI can't do anything.

    In case of 3) you can check the UCSCLLOW bit, which is set when the USCI wants SCL to be high but sees that it is low. UCSCLLOW can also appear shortly, when the USCI releases SCL and it takes some time to go high by the pull-up (low rising edge).

**Attention** This is a public forum