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.

Understanding USCI I2C Interrupts (MSP430G2553)

Other Parts Discussed in Thread: TMP100, MSP430G2553

Hi,

I'm trying to interface my MSP430 LaunchPad with a few I2C devices but am having trouble understanding the example code.  I'm looking at the code that reads the temperature from a TMP100 module:

//******************************************************************************
//  MSP430G2xx3 Demo - USCI_B0 I2C Master to TMP100, Set P1.0 if Temp > 28C
//
//  Description: I2C interface to TMP100 temperature sensor in 9-bit mode.
//  Timer_A CCR0 interrupt is used to wake up and read the two bytes of
//  the TMP100 temperature register every 62ms. If the temperature is greater
//  than 28C, P1.0 is set, else reset. CPU is operated in LPM0. I2C speed
//  is ~100kHz.
//  ACLK = n/a, MCLK = SMCLK = TACLK = BRCLK = default DCO = ~1.2MHz
//
//         /|\           /|\ /|\
//          |   TMP100   10k 10k     MSP430G2xx3
//          |   -------   |   |   -------------------
//          +--|Vcc SDA|<-|---+->|P1.7/UCB0SDA    XIN|-
//          |  |       |  |      |                   |
//          +--|A1,A0  |  |      |               XOUT|-
//             |       |  |      |                   |
//          +--|Vss SCL|<-+------|P1.6/UCB0SCL   P1.0|---> LED
//         \|/  -------          |                   |
//
//  D. Dang
//  Texas Instruments Inc.
//  February 2011
//   Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10
//******************************************************************************
#include "msp430g2553.h"

unsigned int RxByteCtr;
unsigned int RxWord;

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  P1DIR |= BIT0;                            // P1.0 output
  P1SEL |= BIT6 + BIT7;                     // Assign I2C pins to USCI_B0
  P1SEL2|= BIT6 + BIT7;                     // Assign I2C pins to USCI_B0
  UCB0CTL1 |= UCSWRST;                      // Enable SW reset
  UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
  UCB0CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
  UCB0BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz
  UCB0BR1 = 0;
  UCB0I2CSA = 0x4e;                         // Set slave address
  UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
  IE2 |= UCB0RXIE;                          // Enable RX interrupt
  TACTL = TASSEL_2 + MC_2;                  // SMCLK, contmode

  while (1)
  {
    RxByteCtr = 2;                          // Load RX byte counter
    UCB0CTL1 |= UCTXSTT;                    // I2C start condition
    __bis_SR_register(CPUOFF + GIE);        // Enter LPM0, enable interrupts
                                            // Remain in LPM0 until all data
                                            // is RX'd

    if (RxWord < 0x1d00)                    // >28C?
      P1OUT &= ~0x01;                       // No, P1.0 = 0
    else
      P1OUT |= 0x01;                        // Yes, P1.0 = 1

    __disable_interrupt();
    TACCTL0 |= CCIE;                        // TACCR0 interrupt enabled
    __bis_SR_register(CPUOFF + GIE);        // Enter LPM0, enable interrupts
                                            // Remain in LPM0 until TACCR0
                                            // interrupt occurs
    TACCTL0 &= ~CCIE;                       // TACCR0 interrupt disabled
  }
}

#pragma vector = TIMER0_A0_VECTOR
__interrupt void TA0_ISR(void)
{
  __bic_SR_register_on_exit(CPUOFF);        // Exit LPM0
}

// The USCIAB0TX_ISR is structured such that it can be used to receive any
// 2+ number of bytes by pre-loading RxByteCtr with the byte count.
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
  RxByteCtr--;                              // Decrement RX byte counter

  if (RxByteCtr)
  {
    RxWord = (unsigned int)UCB0RXBUF << 8;  // Get received byte
    if (RxByteCtr == 1)                     // Only one byte left?
      UCB0CTL1 |= UCTXSTP;                  // Generate I2C stop condition
  }
  else
  {
    RxWord |= UCB0RXBUF;                    // Get final received byte,
                                            // Combine MSB and LSB
    __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
  }
}

Now, I think I understand most of the code (setting the register flags, LPM0, etc.), but I'm confused about a few points regarding how interrupts are handled.

1) Why do we use the USCIAB0TX vector when we are reading data?  After searching around on these forums, it would appear that I2C handles interrupts differently than the other USCI modes and fires USCIAB0TX on both read and write.  However, I can't seem to find this in the documentation.  I'm looking at the user guide here and the datasheet here.  While the datasheet does mention the different I2C functionality in the interrupt table, I can't seem to find detailed documentation regarding this behavior.  According to the user guide, the UCBxRXIFG flag is set on read.  Is this the same as an interrupt?  Why does this fire USCIAB0TX?  Sorry I am a bit new to this.

2) Second, if we are using the USCIAB0TX vector, why do we set the UCB0RXIE flag?

Any help on these points would be greatly appreciated.

Thanks,

Jeremy

  • Hi Jeremy

    Have you been able to solve the issue? Because I'm struggling with the exact same question right now.

    Thanks,

    Mat

  • The same interrupt vector can be triggered by different sources. Section 17.3.7 of the User's Guide says:

    There are two interrupt vectors for the USCI module in I²C mode. One interrupt vector is associated with the transmit and receive interrupt flags. The other interrupt vector is associated with the four state change interrupt flags.

    The names of the interrupt vectors are just names. They would make sense in the other USCI modes. It might be a good idea to define your own names for them:

    #define USCI_B0_I2C_RXTX_VECTOR   USCIAB0TX_VECTOR
    #define USCI_B0_I2C_STATUS_VECTOR USCIAB0RX_VECTOR

**Attention** This is a public forum