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.

Using I2C UCB1 on MSP430F5529

I am struggling to get an I2C interface to work on an MSP430F5529LP. I have the ports configured correctly as I get the beginning of a transmission. I am trying to communicate with an LTC4151 device.

On my oscilloscope,

I see the start occur correctly.

I see the correct address.

I see the RD/WR pin LOW indicating a Write.

I get an ACK from the slave device.

This is where things go wrong. Below is the code I have. It is a function call that I pass in the Device Address and the Register inside the device to read.

void I2C_UCB1_CUR_MON_read(char cur_mon_addr, char cur_mon_reg){
  char temp_addr;
  UCB1I2CSA = cur_mon_addr;    // Set Slave Address
  UCB1CTL1 &= ~UCSWRST;        // Clear SW reset, resume operation
  I2C_UCB1_Char = cur_mon_reg; // Load Register that is to be accessed
  UCB1IFG &= ~UCTXIFG;         // Clear USCI_B1 TX int flag
  UCB1IE |= UCTXIE;            // Enable TX interrupt
  UCB1CTL1 |= UCTR + UCTXSTT;  // I2C TX, start condition

//------------------------------------------------------------------------------

}

No mater what I try, I am not seeing the Register value transmitted out the I2C bus. I have tried to both use the TX interrupt and to do the following

UCB1TXBUF = cur_mon_reg;

any help is appreciated.

 

 

 

  • How does your code proceed? In master transmit mode, the USCI will stall the transfer in the ACK cycle (SCL remains low) until you either write data to TXBUF or set UCTXSTP (to not write anything, a 'slave present' check). Only then will UCTXSTT clear. Then check UCNACKIFG for the slave answer and proceed with writing data to TXBUF (as soon as TXIFG is set again) or ending the transfer with setting UCTXSTP (again, when TXIFG indicates that the previous byte is being sent)
  • Thanks for the response. I am in the state where SCL is low, and remains low. My issue is that I have tried several changes to code and none seem to work. I expect I am not waiting for the right flag to be set before taking an action and the data to be sent out is just overwriting something. So To have a starting point, here is what I tried this morning. I have also disabled TX interrupt use and am just trying to write the TxBUF when I have something to transmit and the buffer is open to receive. This is likely where I am not waiting for the right flag to be set.

    void I2C_UCB1_CUR_MON_read(char cur_mon_addr, char cur_mon_reg){
    UCB1I2CSA = cur_mon_addr; // Set Slave Address
    UCB1CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    I2C_UCB1_Char = cur_mon_reg;
    UCB1CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
    while (UCB1CTL1 & UCTXSTT); // Wait start condition, address transmitted
    while (!(UCB1IFG & UCTXIFG)); // Wait for TXBUF to be empty
    UCB1TXBUF = I2C_UCB1_Char; // Transmit data I2C_UCB1_Char
    while (!(UCB1IFG & UCTXIFG)); // Wait for TXBUF to be empty
    while (UCB1CTL1 & UCTXSTP); // Ensure stop condition got sent

    //------------------------------------------------------------------------------

    }

    I never see the UCB1TXBUF = I2C_UCB1_Char; I see the ACK from the Slave. I am not sure how to see it in software nor how to respond to it.
  • The problem is that the USCI waits for something in TXBUF (or UCTXSTP set) before it completes the start byte ACK cycle. But your code waits for the start byte being sent before it writes to TXBUF. So both wait for each other on the first while. The second while is superfluous. As soon as you set UCTXSTT and UCTR, UCTXIFG gets set. You only need to wait for TXIFG for writing the second (and subsequent) byte(s) or setting UCTXSTP to end the transfer after the first byte.

**Attention** This is a public forum