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.

What could cause an I2C transaction to fail to start after I've set UCTXSTT?

Other Parts Discussed in Thread: MSP430F2272I'm using an MSP430F2272 and putting it in I2C Master Mode. I'm controlling the I2C bus via polling, not interrupts. I want to perform a simple write to the Slave to give it a register address (it has a number of registers) and then read the contents of the register. The code worked yesterday, but after making some changes to other parts of the program (related to the UART elsewhere on the micro), no I2C clock cycles ever emerge. The code stalls waiting for UCTXSTT to be cleared. In other words, I set UCTXSTT and then would expect the module to send out the transmit data from the buffer, but it doesn't. What could be causing this? Code fragments are below. Thanks in advance for your help! Initialization: // UCB0 setup for I2C comms. Frequency has to be
  • Scott,

    I do not see and Code fragments?

    I would go back (i.e. remove the UART code) to a working I2C code.

    Then start adding the UART code in step-by-step and see where it fails.

     

    -Alex

  • I don't know why the code fragments didn't come through. The UART code uses interrupts and I'm using polling for the I2C. I'll try again to put the code fragments below. // UCB0 setup for I2C comms. Frequency has to be
  • Something about the formatting of the code fragments is confusing the forum software so that it strips out the code...what gives? Scott
  • Here's the code again. I figured out that the posts have to be in HTML (sigh). I don't know HTML, so apologies for the lack of formatting.
    Initialization section first:

    // UCB0 setup for I2C comms. Frequency has to be less than 100 kHz.


    UCB0CTL1 |= UCSWRST; // Hold UART in reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    UCB0BR0 = 12; // fSCL = SMCLK/12 = 83.3 kHz
    UCB0BR1 = 0;
    UCB0I2CSA = 0x10; // Slave Address is binary 0010000
    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation.

    .....
    Here's the code to send a register address and then get the data back in.

    TXData = 0; // Register address
    UCB0CTL1 |= UCTR + UCTXSTT; // I2C Transmit mode; send START
    while (IFG2 & ~UCB0TXIFG); // Wait for readiness of transmit buffer
    UCB0TXBUF = TXData; // Load TX buffer with register address
    while (IFG2 & ~UCB0TXIFG); // Wait for data to be sent
    IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX flag
    UCB0CTL1 |= UCTXSTP; // I2C STOP will be sent at end of byte
    UCB0CTL1 &= ~UCTR; // Clear Transmit mode bit, now in Receive mode
    UCB0CTL1 |= UCTXSTT; // START condition on bus so we can receive register data
    while (UCB0CTL1 & UCTXSTT); // Wait for START to be acknowledged by Slave
    UCB0CTL1 |= UCTXSTP; // I2C STOP will be sent at end of byte
    while (IFG2 & ~UCB0RXIFG); // Wait for data to be received in buffer
    RXData[0] = UCB0RXBUF; // Get RX data from buffer
    while (UCB0CTL1 & UCTXSTP); // Ensure STOP condition happened
  • Scott Brenneman said:
    UCB0CTL1 |= UCTR + UCTXSTT; // I2C Transmit mode; send START
    while (IFG2 & ~UCB0TXIFG); // Wait for readiness of transmit buffer

    This won't happen if no slave answers to the start.

    You should look for STT being cleared (then the address has been sent, whether a slave has responded or not). After this, either TX starts or a NACK is set.

    Scott Brenneman said:
    IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX flag

    I don't think this works. On USCI (other than the previous UART), the IFGs are state flags (level-set) and not change flags (edge-set). This means TXIFG remains set until you write something into TXBUF or disable the TX functionality. At least on the 5x USCIs it is this way. Anyway, it won't make a difference for the code.

    Scott Brenneman said:
    UCB0CTL1 |= UCTXSTP; // I2C STOP will be sent at end of byte

    No need to send a stop, you can just follow another start (this will nto free the bus, so no other master could interfere). Just send another start (repeated start condition - it's even faster since you spare the time for the stop)

    I don't see, however, something that would stall the code unde rnormal circumstances.
    Unnormal cisrumstacnes owudl be that ne slave is answering (your code simply assumes that there is always a slave responding) and th emother of all I2C problems: a missing pullup on the clock/data lines that causes the clock line to stay low and stall the bus (clock-stretching: the slave keeps the clock low to signal the master that it needs more time. The master will wait until the slave releases the clock line. there is no timeout). The MSPs internal pullups are too weak to server for the I2C bus and on most MSPs they are disabled anyway if the port pin is set to output.

**Attention** This is a public forum