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.

TMP I2c CC430

Other Parts Discussed in Thread: CC430F5137, TMP100

Dear all,

Trying from 2 days figure out what is wrong with the code since the result is always wrong. I use cc430F5137 and TMP100 connected to Port 1.2 (clock) Port 1.3  (Data) 4,7K pull up  is connected However it doesn't work. 

Any help would be appriciated. Always halt on RED LED. 

#include "cc430x613x.h"

#define RED_LED BIT6
#define GRN_LED BIT0

unsigned int RxByteCtr;
unsigned int RxWord;
//volatile unsigned char RxBuffer[1];       // Allocate 128 byte of RAM

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  
  P1OUT = 0;
  P3OUT = 0;
  P1DIR |= GRN_LED;
  P3DIR |= RED_LED; 
  
//  P1SEL |= 0x06;                            // 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 = 0x40;                         // Set slave address
  UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
  UCB0IE |= UCRXIE;                          // Enable RX interrupt
  TA1CTL = TASSEL_2 + MC_2;         // ACLK, upmode, clear TAR
  
  while (1)
  {
    RxByteCtr = 2;
    UCB0CTL1 |= UCTXSTT;  
//    PRxData = (int)RxBuffer;    // Start of RX buffer
                              // Clear RX byte count
//   __bis_SR_register( CPUOFF + GIE);     // Enter LPM0, enable interrupts 

    if (RxWord < 0x1d00)                    // >28C?
      P1OUT |=GRN_LED;                            // No, P1.0 = 0
    else
      P3OUT |= RED_LED;                        // Yes, P1.0 = 1

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



// 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 = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
{
  switch(__even_in_range(UCB0IV,12))
  {
  case  0: break;                           // Vector  0: No interrupts
  case  2: break;                           // Vector  2: ALIFG
  case  4: break;                           // Vector  4: NACKIFG
  case  6:                                  // Vector  6: STTIFG
    UCB0IFG &= ~UCSTTIFG;
    break;
  case  8:                                  // Vector  8: STPIFG
    UCB0IFG &= ~UCSTPIFG;
   // if (RXByteCtr)                          // Check RX byte counter
   //   __bic_SR_register_on_exit(LPM0_bits);
    break;
  case 10:                                  // Vector 10: RXIFG
    RxByteCtr--;                              // Decrement RX byte counter

  if (RxByteCtr)
  {
  	 RxWord = (unsigned int)UCB0RXBUF << 8;                 // Get RX'd byte into buffer
  	   if (RxByteCtr == 1)                     // Only one byte left?
      UCB0CTL1 |= UCTXSTP;                  // Generate I2C stop condition
      
        else
  {
  	RxWord = (unsigned int)UCB0RXBUF;
  }
  }

  
  
   
    break;
  case 12: break;                           // Vector 12: TXIFG  
  default: break;
  }  
}

// Timer A0 interrupt service routine
#pragma vector=TIMER1_A0_VECTOR
__interrupt void TIMER1_A0_ISR(void)
{
  __bic_SR_register_on_exit(CPUOFF);        // Exit LPM0
}

P.s: http://320volt.com/wp-content/uploads/2010/10/msp430x23x0_uscib0_i2c_01.c.html

  • Several problems with your code.

    Line 19: If you don't select P1.2 and P1.3 for module use, the USCI has no access to the port pins. So uncomment this line.

    Line 25: are you sure? Most manufactures write in their datasheets the slave ID including the R/W bit. The MSP, however, requires the address without the R/W bit (it is automativcally added based on UCTR). So if the datasheet says '0x40/0x41', the 'real' 7-bit address is 0x20.

    Line 27: you only enable RX interrupt. However, if the slave isn't answering, you'll never get an RX interrupt, you'll get a NACK interrupt instead - which you didn't enable.

    Line 36: when you do not enter LPM, your code will immediately continue and try to interpret RxWord, while the USCI is still sending the start condition and has not selected the slave yet, let alone received something. So uncomment this line too, to synchronize with the I2C transfer.

    Line 45: if you want a delay strting at this point, you should also reset TAR with TACTL |= TCLR; Else, the timer has already counted all the time from the moment you configured the clock (line 28). But this might be intentional.

    Line 65+68: When you read UCB0IV, the IFG bit that cause the reported interrupt is automatically cleared. No need to manually clear it in the different cases.

    Most likely, line 25 and 27 are the problem(s)

    Ah, one more problem: you configure the timer for cont mode, despite of the comment. And do not write anything to TA1CCR0. So the interrupt comes on timer overflow. Also, the comment reads 'ACLK' but you configured the timer for SMCLK.
    With ACLK (and no crystal, no clock configuration), the interrupt would come every 2 seconds (32768Hz fallback to REFO), but with SMCLK, it comes with 15Hz. Probably too fast to detect any LED blinking, even if the code is working.

  • Thank you for your reply, I already solved the problem.  Please don't focus a lot on the comments since i didn;t edit anything of that ... 

    In case anyone needs the code here it is: 


    #include "cc430x613x.h"
    #define RED_LED BIT6
    #define GRN_LED BIT0
    unsigned int RxByteCtr;
    unsigned long RxWord;
    unsigned char count = 0;
    void main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT

    P1OUT = 0;
    P3OUT = 0;
    P1DIR |= GRN_LED;
    P3DIR |= RED_LED;

    P1SEL |= BIT2 + BIT3; // 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 = 0x4a; // Set slave address
    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    UCB0IE |= UCRXIE; // Enable RX interrupt
    TA1CTL = TASSEL_2 + MC_2; // ACLK, upmode, clear TAR

    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 < 28) // >28C?
    P1OUT &= ~0x01; // No, P1.0 = 0
    else
    P1OUT |= 0x01; // Yes, P1.0 = 1
    __disable_interrupt();

    TA1CCTL0 = CCIE;
    __bis_SR_register(CPUOFF + GIE); // Enter LPM0, enable interrupts TA1CCTL0 &= ~CCIE; // Remain in LPM0 until TACCR0
    // interrupt occurs
    TA1CCTL0&= ~CCIE;
    }
    }
    
    
    // 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 = USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    {
    switch(__even_in_range(UCB0IV,12))
    {
    case 0: break; // Vector 0: No interrupts
    case 2: break; // Vector 2: ALIFG
    case 4: break; // Vector 4: NACKIFG
    case 6: // Vector 6: STTIFG
    UCB0IFG &= ~UCSTTIFG;
    break;
    case 8: // Vector 8: STPIFG
    UCB0IFG &= ~UCSTPIFG;
    // if (RXByteCtr) // Check RX byte counter
    // __bic_SR_register_on_exit(LPM0_bits);
    break;
    case 10: // Vector 10: RXIFG
    RxByteCtr--; // Decrement RX byte counter
    if (RxByteCtr)
    {
    RxWord = (unsigned int)UCB0RXBUF << 8; // Get RX'd byte into buffer
    if (RxByteCtr == 1) // Only one byte left?
    UCB0CTL1 |= UCTXSTP; // Generate I2C stop condition

    else
    {
    RxWord = (unsigned int)UCB0RXBUF;
    }
    }



    break;
    case 12: break; // Vector 12: TXIFG
    default: break;
    }
    }
    */
    // 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 = USCI_B0_VECTOR
    __interrupt void USCI_B0_ISR(void)
    {
    RxByteCtr--; // Decrement RX byte counter
    if (RxByteCtr)
    {
    RxWord = (unsigned long)UCB0RXBUF; // 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
    }
    }
    // Timer A0 interrupt service routine
    #pragma vector=TIMER1_A0_VECTOR
    __interrupt void TIMER1_A0_ISR(void)
    {
    __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
    }

**Attention** This is a public forum