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.

MSP430FR5969: Master I2C to UART

Part Number: MSP430FR5969


Hi,

I'm trying to read data from the TM117 temperature sensor connected to the MSP430FR5969 MCU via I2C protocol, and then want to transmit the data to a CPU (running PuTTY) over UART. I've followed the code provided in [1]  and modified it for the MSP430FR5969 MCU but it is not working. I've attached the code below and please let me know what's wrong with it. Thank you.

//******************************************************************************
//   MSP430FR59xx Demo - eUSCI_B0, I2C Master multiple byte TX/RX
//
//   Description: I2C master communicates to I2C slave sending and receiving
//   3 different messages of different length. I2C master will enter LPM0 mode
//   while waiting for the messages to be sent/receiving using I2C interrupt.
//   ACLK = NA, MCLK = SMCLK = DCO 16MHz.
//
//                                     /|\ /|\
//                   MSP430FR5969      4.7k |
//                 -----------------    |  4.7k
//            /|\ |             P1.7|---+---|-- I2C Clock (UCB0SCL)
//             |  |                 |       |
//             ---|RST          P1.6|-------+-- I2C Data (UCB0SDA)
//                |                 |
//                |                 |
//                |                 |
//                |                 |
//                |                 |
//                |                 |
//
//   Nima Eskandari
//   Texas Instruments Inc.
//   April 2017
//   Built with CCS V7.0
//******************************************************************************

#include <stdio.h>
#include <msp430.h>
#include <stdint.h>
#include <stdbool.h>

void convert(int i2c_byte, int index);              // convert each i2c byte to string
void load_uart(int index);                          // Load string into uart buffer

unsigned char *PRxData;                             // Pointer to RX data
unsigned char RXByteCtr;                            // Initialized line 73
volatile unsigned char RxBuffer[128];               // Allocate 128 byte of RAM
volatile unsigned char i2c_storage[128];            // Allocate 128
volatile unsigned char uart_storage[6][6];          // Each data will have 'xxxxx' values
volatile unsigned int ii = 0, slaveBytes = 0;

#define SLAVE_ADDR  0x48
#define TMP117_TEMP_REG  0x00
#define TMP117_CONFIG_REG  0x01
#define TMP117_RESOLUTION 0.0078125f

#define MAX_BUFFER_SIZE     20
#define CONVERSION_READY  0x10

int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;                  // Stop watchdog timer

    // Configure GPIO
    P1OUT   &= ~BIT0;                             // Clear P1.0 output latch
    P1DIR   |= BIT0;                              // For LED
    P1SEL1  |= BIT6 | BIT7;                      // I2C pins
    P2SEL1  |= BIT0 | BIT1;                      // USCI_A0 UART operation
    P2SEL0  &= ~(BIT0 | BIT1);
    PM5CTL0 &= ~LOCKLPM5;                       // Disable the GPIO power-on default high-impedance mode to activate
                                                    // previously configured port settings

    // Configure one FRAM waitstate as required by the device datasheet for MCLK
    // operation beyond 8MHz _before_ configuring the clock system.
    FRCTL0 = FRCTLPW | NWAITS_1;
    // Clock System Setup
    CSCTL0_H = CSKEY >> 8;                                  // Unlock CS registers
    CSCTL1 = DCORSEL | DCOFSEL_4;                           // Set DCO to 16MHz
    CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK;
    CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1;                   // Set all dividers
    CSCTL0_H = 0;

    // Configure USCI_A0 for UART mode
    UCA0CTLW0 = UCSWRST;                            // Put eUSCI in reset
    UCA0CTLW0 |= UCSSEL__SMCLK;                     // CLK = SMCLK
    UCB0BRW = 160;                                  // fSCL = SMCLK/160 = ~100kHz
    UCA0MCTLW |= UCOS16 | UCBRF_1;
    UCA0CTLW0 &= ~UCSWRST;                          // Initialize eUSCI
    //UCA0IE |= UCRXIE;                             // Enable USCI_A0 RX interrupt

    // Configure USCI_B0 for I2C mode
    UCB0CTLW0  |= UCSWRST;                          // Software reset enabled
    UCB0CTLW0  |= UCMODE_3 | UCMST | UCSYNC;        // I2C mode, Master mode, sync
    UCB0CTLW1  |= UCSSEL_2;                         // Automatic stop generated
    UCB0BRW   = 0x0008;                             // baudrate = SMCLK / 8
    UCB0TBCNT = 0x0002;                             // number of bytes to be received
    UCB0I2CSA = 0x0048;                             // Slave address
    UCB0CTLW0  &= ~UCSWRST;

    UCA0IE |= UCRXIE;                               // Enable USCI_A0 RX interrupt
    UCB0IE |= UCRXIE | UCNACKIE | UCBCNTIE;         // Enable USCI_B0 RX interrupt

  __bis_SR_register(LPM0_bits | GIE);             // Enter LPM0 w/ interrupts

    while (1)
    {
       __delay_cycles(2000);
       while (UCB0CTL1 & UCTXSTP);                   // Ensure stop condition got sent
       UCB0CTL1 |= UCTXSTT;                          // I2C start condition

       __bis_SR_register(LPM0_bits | GIE);            // Enter LPM0 w/ interrupt
       __no_operation();

     }
}

// Convert each byte to ASCII Char Values so it can be sent via UART
void convert(int i2c_val, int ii)
{
    volatile unsigned int jj = 0, temp = 0, bit_position = 10000;
    for (jj = 0; jj<slaveBytes; jj++)
    {
        temp = i2c_val/bit_position;
        i2c_val -= temp*bit_position;
        bit_position /= 10;
        temp += 0x30;
        uart_storage[ii][jj] = temp;
    }
}

//Load data onto UART
void load_uart(int ii)
{
    volatile unsigned int jj = 0;
    for(jj = 0; jj<slaveBytes; jj++)
    {
        while (!(UCA0IFG&UCTXIFG0));                 // UART TX buffer ready?
        UCA0TXBUF = uart_storage[ii][jj];           // load buffer one character at a time
    }                                               // Load buffer character by character
}

#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
{
  switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG))
  {
    case USCI_NONE:          break;         // Vector 0: No interrupts
    case USCI_I2C_UCALIFG:   break;         // Vector 2: ALIFG
    case USCI_I2C_UCNACKIFG:                // Vector 4: NACKIFG
      UCB0CTL1 |= UCTXSTT;                  // I2C start condition
      break;
    case USCI_I2C_UCSTTIFG:  break;         // Vector 6: STTIFG
    case USCI_I2C_UCSTPIFG:  break;         // Vector 8: STPIFG
    case USCI_I2C_UCRXIFG3:  break;         // Vector 10: RXIFG3
    case USCI_I2C_UCTXIFG3:  break;         // Vector 12: TXIFG3
    case USCI_I2C_UCRXIFG2:  break;         // Vector 14: RXIFG2
    case USCI_I2C_UCTXIFG2:  break;         // Vector 16: TXIFG2
    case USCI_I2C_UCRXIFG1:  break;         // Vector 18: RXIFG1
    case USCI_I2C_UCTXIFG1:  break;         // Vector 20: TXIFG1
    case USCI_I2C_UCRXIFG0:                 // Vector 22: RXIFG0
     // RXData = UCB0RXBUF;                   // Get RX data
      RXByteCtr--;                                    // Initialized on line 73
       if (RXByteCtr)
       {
           if (ii == 0)
           {
               slaveBytes = UCB0RXBUF;                 // Byte# fits 1st Slave Byte
               RXByteCtr = slaveBytes-1;
           }

           i2c_storage[ii] = UCB0RXBUF;                // Move each I2C byte to storage
           convert(i2c_storage[ii],ii);                // Convert byte to string
           load_uart(ii);
           //      while (!(IFG2&UCA0TXIFG));          // UART TX buffer ready?
           //      UCA0TXBUF = 'x';                    // Test Buffer
           ii++;
       }

       else
       {
           ii = slaveBytes-1;                          // Unclear to team, why necessary
           i2c_storage[ii] = UCB0RXBUF;                // Move final RX data to PRxData
           convert(i2c_storage[ii],ii);
           load_uart(ii);

                   while (!(UCA0IFG&UCTXIFG));         // USCI_A0 TX buffer ready?
                   UCA0TXBUF ='\n';                    // format easier reading
                   UCB0CTL1 & UCTXSTP;                 // Generate I2C stop condition
           ii = 0;

           __bic_SR_register_on_exit(CPUOFF);          // Exit LPM0
       }

      //__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
      break;
    case USCI_I2C_UCTXIFG0:  break;         // Vector 24: TXIFG0
    case USCI_I2C_UCBCNTIFG:                // Vector 26: BCNTIFG
      P1OUT ^= BIT0;                        // Toggle LED on P1.0
      break;
    case USCI_I2C_UCCLTOIFG: break;         // Vector 28: clock low timeout
    case USCI_I2C_UCBIT9IFG: break;         // Vector 30: 9th bit
    default: break;
  }
}

  • Exactly how is it not working?

  • Hi David,

    Thank you for the reply. The code runs without any error but I can't see any transmitted value on the PuTTY terminal. I also have checked the waveform I2C signals on a oscilloscope, but there is no clock and data on the CLK and SDA lines.

  • There would be no I2C activity because you don't do anything. After setting up the hardware and just before your main loop you enter LPM0. Since there isn't anything to wake it up, that is the end.

    Oh, the UART receive interrupt could maybe do the job. Except that while you enable that interrupt, I don't see an ISR.

    Fixing this should be easy. Start simple and build from there. The first thing would be to verify that the UART can transmit data. You also have a debugger you can use to trace program flow and see what it is doing. Learn to use it.

  • Hi David,

    Thank you for the reply. I remove the LPM0, and now I can see values in the USCI B0 Receive Buffer and USCI A0 Transmit Buffer. But on the PuTTY, I can see only bracket symbols as shown below. I'm not sure how to fix this issue. 

    if I remove the "convert(i2c_storage[ii],ii); // Convert byte to string " function then I get the following charaters. 

**Attention** This is a public forum