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 Read - Basics

Other Parts Discussed in Thread: CC430F5137

I can't seem to find an example of this so let's start from the beginning. I'm using a CC430F5137 and trying to communicate with an Invensense Motion Sensor, address 68, and just trying to read "Who am I" at Reg 75 using I2C.

Can I assume the UCTXSTT start will add the R/W bit based on the value of UCTR? 

Then if I want to read 75, then should I write 68, then write again with SST (~UCTR) again and pick it up in the ISR under Case 10?

Thanks! John

Init: UCB0I2CSA = 0x68; 

Then in Main:

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

__bis_SR_register(LPM0_bits+GIE); // Enter LPM0, enable interrupts
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent (Maybe I shouldn't do this yet)

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

ISR Code:

Case 10: // RX
UCB0IFG &= ~UCRXIFG;
Data= UCB0RXBUF;

Case 12: //TX

if (I2cTxByteCtr == 1) {
UCB0TXBUF = 0X75; // The register I want to read (probably should be a variable)
I2cTxByteCtr = I2cTxByteCtr - 1; // Decrement TX byte counter

} else {

UCB0CTL1 |= UCTXSTP; // I2C stop condition
UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag
I2cTxByteCtr = 1;
}

  • Hi John,

    Yes, the UCTXSTT bit will add the correct R/W bit to the slave address when transmitting.  Please note that the value of the R/W bit (and the USCI functionality during the transaction) is based on the UCTR bit in UCBxCTL1 that determines if the USCI module is a transmitter or a receiver.

    I highly recommended looking at some of the code examples in the Resource Explorer in CCS for examples on how to use the USCI in I2C mode (there are both transmitter and receiver examples).  You can then base your project off of these examples.

    Mike

  • Thanks Mike. Where is the "Resource Explorer" - same as code samples? I'm using IAR not CCS. The example TI Code (cc430x513x_uscib0_i2c_04.c where the master does a read) doesn't even use Case 12 at all. Doesn't make sense.

    For some reason I'm not getting to Case 10 of the ISR for any reads. Exact code below, I think I'm close because all my initialization code worked with another I2C device, write only to a digital pot.

    UCB0I2CSA = 0x68;

    Main:

    UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition as a write to addr 68
    __bis_SR_register(LPM0_bits+GIE); // Enter LPM0, enable interrupts

    UCB0CTL1 &= ~UCTR; // I2C RX mode,

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

    ISR:

    case 10: // RECIEVE
    UCB0IFG &= ~UCRXIFG;
    accelData= UCB0RXBUF;

    case 12: // TRANSMIT

    if (I2cTxByteCtr == 1) {

    UCB0TXBUF = 0X75; //
    I2cTxByteCtr = I2cTxByteCtr - 1; // Decrement TX byte counter

    } else {
    UCB0CTL1 |= UCTXSTP; // I2C stop condition
    UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag
    I2cTxByteCtr = 1;
    }

  • Stuck for sure. May have to go to Techshop and read the data on a scope.

    Sparkfun ties the 10K pullups to Vcc which is 3.3V max (not 5V). I didn't have a problem in the past with other I2C devices, this should be OK.

    Anyone see anything wrong with my code, it never gets into the Rx case. Tried putting the P Stop command in all places, not sure where it should be - Main, ISR RX, ISR TX? 

    TI samples (Ti to TI) don't make sense for a real slave device. Anyone with code using a sensor type slave would be very much appreciated.

    Thanks,

    John

  • OK, admitting here a very junior error. I had set the slave address to 68, not 0x68. Let me share what an I2C read could look like in case someone else needs this.

    Init:

    P1MAP3 = PM_UCB0SDA; // Map UCB0SDA to P1.3
    P1MAP2 = PM_UCB0SCL; // Map UCB0SCL to P1.2
    P1SEL |= BIT2 + BIT3; // Select P1.2 & P1.3 to I2C function
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    UCB0BR0 = 24; // fSCL = SMCLK/12 = ~100kHz, can use 3 (400kHz), just slowed for testing
    UCB0BR1 = 0;
    UCB0I2CSA = 0x68; // Slave is 68 FOR THE GYRO 9150
    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    UCB0IE |= UCTXIE + UCRXIE + UCNACKIE; // Enable TX/RX interrupt, monitor for NACK (No Acknowledge)

    Main:

    UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
    __bis_SR_register(LPM0_bits+GIE); // Enter LPM0, enable interrupts

    UCB0CTL1 &= ~UCTR; // I2C RX
    UCB0CTL1 |= UCTXSTT; // I2C start condition
    __bis_SR_register(LPM0_bits+GIE); // Enter LPM0, enable interrupts

    UCB0CTL1 |= UCTXSTP; // I2C stop condition

    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    {
    switch(__even_in_range(UCB0IV,12)) {

    case 10: // RECIEVE
    UCB0IFG &= ~UCRXIFG;
    accelData= UCB0RXBUF;

    break;

    case 12: // TRANSMIT
    UCB0IFG &= ~UCTXIFG; // Clear USCI_B0 TX int flag
    UCB0TXBUF = 0x75; // "Who am I" register in the slave, should return 0x68 for this device in case 10 above.

    break;

    default:

    break;
    }

**Attention** This is a public forum