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.

CCS/MSP432P401R: Need simple code to read TMP007 temps through I2C

Part Number: MSP432P401R

Tool/software: Code Composer Studio

Hi,

Does anyone have a single file of SIMPLE code to run to get temperatures from the TMP007 using the MSP430 or MSP432? I don't want the SimpleLink MSP432P4 TI drivers example, that project references far too many outside files. Just one single file that's easy to implement into my own design. The code below is something similar to what I'm looking for, except it was written for a different sensor.

#include "msp.h"
#include <stdint.h>
#include "string.h"
#include "stdlib.h"
#include "stdio.h"
#include "LCD.h"

#define TCN_ADDRESS 0x48

void InitTCN(uint8_t DeviceAddress);
void ConfigTCN(uint8_t MemAddress, uint8_t MemByte);
void itoa(long unsigned int value, char* result, int base);
void reverse(char s[]);
uint16_t ReadTCN(uint8_t MemAddress);

void decomposition(int num);

uint16_t TransmitFlag = 0;

uint16_t ReceiveByte;
uint16_t test;
int six;
int five;
int four;
int three;
int two;
int one;
int main(void)
{
    uint32_t i;
    float Celsius;
    float Farenheit;
    float cel;
    float faren;
    char outputC[6];
    char outputF[6];
    char temp[] = "Temperature: " ;


    WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD;       // Stop watchdog timer

    __enable_irq();                             // Enable global interrupt

    P2->SEL1 &= ~(BIT5 | BIT6 | BIT7 | BIT3);   // sets port 2 as GPIO (red LED, green LED, blue LED, and switch respectively)
    P2->SEL0 &= ~(BIT5 | BIT6 | BIT7 | BIT3);
    P2->DIR |= BIT5 | BIT6 | BIT7;              // sets as output pin
    P2->DIR &= ~BIT3;                           // sets as input pin
    P2->REN |= BIT3;                            // enable pullup resistor
    P2->OUT |= BIT3;                            // set out for read

    LCD_init();                                 // initialize LCD

    InitTCN(TCN_ADDRESS);                       // sets the bus address of PMOD device


    ConfigTCN(0x01, 0xE3);                      // sets PMOD for one shot mode, 12 bit data, and power off
    for (i = 500; i > 0; i--);                  // Delay for TCN write cycle

while(1){
    ReadTCN(0x00);                              // Read value from TCN
    Celsius = (ReceiveByte) * 0.0625;           // Equation from TCN75A datasheet to convert binary output to decimal in Celsius
    cel = 10000 * Celsius;                      // shifting Celsius to preserve the digits after the decimal value
    Farenheit = (Celsius * 1.8) + 32;           // converts Celsius to Farenheit
    faren = 10000 * Farenheit;                  // shifting Farenheit to preserve the digits after the decimal value

    decomposition(faren);                       // preserve values of farenheit
    Clear_LCD();                                // clear LCD screen
    for (i = 50000; i > 0; i--);    // Delay for TCN write cycle (5 ms)

    itoa(cel, outputC, 10);                     // integer to array in Farenheit
    itoa(faren, outputF, 10);                   // integer to array in Celsius

    LCD_write(temp);                            // write "Temperature: " to LCD

    if(Farenheit >= 85){                        // checks for temperature read from TCN
        P2->OUT |= BIT5;                        // sets the red LED on
        P2->OUT &= ~(BIT6 | BIT7);              // turns off other LEDs
    }
    if(Farenheit < 85 && Farenheit > 50){       // checks for temperature read from the TCN
        P2->OUT |= BIT6;                        // turns the green LED on
        P2->OUT &= ~(BIT5 | BIT7);              // turns off other LEDs
    }

    if(Farenheit <= 50){                        // checks for temperature read from the TCN
        P2->OUT |= BIT7;                        // turns the blue LED on
        P2->OUT &= ~(BIT5 | BIT6);              // turns off other LEDs
    }

    if(P2IN & BIT3){                            // checks if the switch position is low

        LCD_command(0x80);                      // sets the cursor to the beginning
        for (i = 50000; i > 0; i--);            // Delay for TCN write cycle
        LCD_command(0xC0);                      // writes on the second line
        for (i = 50000; i > 0; i--);            // Delay for TCN write cycle
        LCD_data(outputC[0]);                   //writes the value for Celsius
        LCD_data(outputC[1]);
        LCD_data('.');
        LCD_data(outputC[2]);
        LCD_data(outputC[3]);
        LCD_data(outputC[4]);
        LCD_data(outputC[5]);
        LCD_data(0xDF);
        LCD_data('C');
    }

    else {
       LCD_command(0x80);                       // sets the cursor to the beginning
       for (i = 50000; i > 0; i--);             // Delay for TCN write cycle (5 ms)
       LCD_command(0xC0);                       // writes on the second line of the LCD
       for (i = 50000; i > 0; i--);             // Delay for TCN write cycle (5 ms)
       LCD_data(outputF[0]);                    // writes the value for Farenheit
       LCD_data(outputF[1]);
       LCD_data('.');
       LCD_data(outputF[2]);
       LCD_data(outputF[3]);
       LCD_data(outputF[4]);
       LCD_data(outputF[5]);
       LCD_data(0xDF);
       LCD_data('F');
    }
//    __sleep();      // go to lower power mode
    }
}
////////////////////////////////////////////////////////////////////////////////
//
// Initialize I2C bus for communicating with TCN75A.
//
////////////////////////////////////////////////////////////////////////////////
void InitTCN(uint8_t DeviceAddress)
{

  P1->SEL0 |= BIT6 | BIT7;                // Set I2C pins of eUSCI_B0

  // Enable eUSCIB0 interrupt in NVIC module
  NVIC->ISER[0] = 1 << ((EUSCIB0_IRQn) & 31);

  // Configure USCI_B0 for I2C mode
  EUSCI_B0->CTLW0 |= EUSCI_A_CTLW0_SWRST;   // Software reset enabled
  EUSCI_B0->CTLW0 = EUSCI_A_CTLW0_SWRST |   // Remain eUSCI in reset mode
          EUSCI_B_CTLW0_MODE_3 |            // I2C mode
          EUSCI_B_CTLW0_MST |               // Master mode
          EUSCI_B_CTLW0_SYNC |              // Sync mode
          EUSCI_B_CTLW0_UCSSEL_3;        // SMCLK

  EUSCI_B0->BRW = 30;                       // baudrate = SMCLK / 30 = 100kHz
  EUSCI_B0->I2CSA = DeviceAddress;          // Slave address
  EUSCI_B0->CTLW0 &= ~EUSCI_A_CTLW0_SWRST;  // Release eUSCI from reset

  EUSCI_B0->IE |= EUSCI_A_IE_RXIE |         // Enable receive interrupt
                  EUSCI_A_IE_TXIE;
}

////////////////////////////////////////////////////////////////////////////////
//
//  Function that configures the PMOD by writing to the configuration register.
//  The pointer register 0x01 is the register for the configuration.
//
//  Address  -    1 byte address specifies the address in the PMOD memory
//  MemByte     - 1 byte value that is stored in the PMOD
//
//  Procedure :
//      start
//      transmit address+W (control+0)     -> ACK (from PMOD)
//      transmit data      (address)       -> ACK (from PMOD)
//      transmit data      (data)          -> ACK (from PMOD)
//      stop
//
////////////////////////////////////////////////////////////////////////////////
void ConfigTCN(uint8_t MemAddress, uint8_t MemByte)
{

  EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TR;          // Set transmit mode (write)
  EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTT;       // I2C start condition

  while (!TransmitFlag);            // Wait for the transmit to complete
  TransmitFlag = 0;

  EUSCI_B0 -> TXBUF = MemAddress;    // Send the byte of the memory address

  while (!TransmitFlag);            // Wait for the transmit to complete
  TransmitFlag = 0;

  EUSCI_B0 -> TXBUF = MemByte;      // Send the byte to store in EEPROM

  while (!TransmitFlag);            // Wait for the transmit to complete
  TransmitFlag = 0;

  EUSCI_B0 -> CTLW0 |= EUSCI_B_CTLW0_TXSTP;   // I2C stop condition
}

////////////////////////////////////////////////////////////////////////////////
//
//  Function that reads a single byte from the PMOD.
//
//  Address  -    1 byte address specifies the address in the PMOD memory
//  ReceiveByte - 1 byte value that is received from the PMOD
//
//  Procedure :
//      start
//      transmit address+W (control+0)    -> ACK (from PMOD)
//      transmit data      (address)      -> ACK (from PMOD)
//      start
//      transmit address+R (control+1)    -> ACK (from PMOD)
//      transmit data      (data)         -> NACK (from MSP432)
//      stop
//
////////////////////////////////////////////////////////////////////////////////
uint16_t ReadTCN(uint8_t MemAddress)
{

  uint16_t ReceiveHiByte;
  uint16_t ReceiveLoByte;

  EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TR;      // Set transmit mode (write)
  EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTT;   // I2C start condition


  while (!TransmitFlag);            // Wait for the transmit to complete
  TransmitFlag = 0;

  EUSCI_B0 -> TXBUF = MemAddress;    // Send the byte of the memory address

  while (!TransmitFlag);            // Wait for the transmit to complete
  TransmitFlag = 0;

  EUSCI_B0->CTLW0 &= ~EUSCI_B_CTLW0_TR;   // Set receive mode (read)
  EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTT; // I2C start condition (restart)

  // Wait for start to be transmitted
  while ((EUSCI_B0->CTLW0 & EUSCI_B_CTLW0_TXSTT));

  while (!TransmitFlag);            // Wait to receive a byte
  TransmitFlag = 0;

  EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTP;

  ReceiveHiByte = EUSCI_B0->RXBUF;    // Read byte from the buffer

  while (!TransmitFlag);            // Wait to receive a byte
    TransmitFlag = 0;

    // set stop bit to trigger after second data byte
  EUSCI_B0->CTLW0 |= EUSCI_B_CTLW0_TXSTP;

    ReceiveLoByte = EUSCI_B0->RXBUF;    // Read byte from the buffer

    ReceiveByte = ((ReceiveHiByte << 8) | ReceiveLoByte) >> 4;


  return (ReceiveByte);
}

////////////////////////////////////////////////////////////////////////////////
//
// I2C Interrupt Service Routine
//
////////////////////////////////////////////////////////////////////////////////
void EUSCIB0_IRQHandler(void)
{
    if (EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG0)     // Check if transmit complete
    {
        EUSCI_B0->IFG &= ~ EUSCI_B_IFG_TXIFG0;  // Clear interrupt flag
        TransmitFlag = 1;                       // Set global flag
    }

    if (EUSCI_B0->IFG & EUSCI_B_IFG_RXIFG0)     // Check if receive complete
    {
        EUSCI_B0->IFG &= ~ EUSCI_B_IFG_RXIFG0;  // Clear interrupt flag
        TransmitFlag = 1;                       // Set global flag
    }
}

///////////////////////////////////////////////////////////////////////////////
//
// function to convert a number into an array value
//
///////////////////////////////////////////////////////////////////////////////

void itoa(long unsigned int value, char* result, int base)
    {
      // check that the base if valid
      if (base < 2 || base > 36) { *result = '\0';}

      char* ptr = result, *ptr1 = result, tmp_char;
      int tmp_value;

      do {
        tmp_value = value;
        value /= base;
        *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
      } while ( value );

      // Apply negative sign
      if (tmp_value < 0) *ptr++ = '-';
      *ptr-- = '\0';
      while(ptr1 < ptr) {
        tmp_char = *ptr;
        *ptr--= *ptr1;
        *ptr1++ = tmp_char;
      }

    }

////////////////////////////////////////////////////////////////////////////
//
//    Function to break up and preserve the data once it has been converted
//    and multiplied by 10000.
//
////////////////////////////////////////////////////////////////////////////
void decomposition(int num){
    one = num % 10;
    two = (num/10) %10;
    three = (num/100) %10;
    four = (num/1000) %10;
    five = (num/10000) %10;
    six = (num/100000) %10;
}

Thanks!

  • Nadir,

     What issue are you experiencing when using "far too many outside files"? Is there an issue with the compiler or your IDE? (which is CCS or another?)  My recommendation would be to at least use driverlib-based code rather than the register-level code you are now using- it's far easier to read and more portable. Unfortunately we don't have a driverlib example for TMP007 directly, but from lines 98-104 of i2ctmp007.c in the TI Drivers example, you can see what values are being sent to the sensor and how to read back. You can then fold that information into the TI driverlib example i2c_master_rw_repeated_start-master_code.

    Hope that helps.

    Regards,

      - Bob L.

**Attention** This is a public forum