🎄⛄❄️🎁 It's beginning to look a lot like ADABOX-mas! The next ADABOX from Adafruit ships soon! Get yours now, or give as a gift! 🎄⛄❄️🎁
0

MSP430 interfacing with MCP9808
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

MSP430 interfacing with MCP9808

by rajatshetty on Thu Jan 24, 2019 10:15 am

Microcontroller: MSP430FR4133
Tool/software: IAR Embedded

Hello,
I'm a beginner, and need some help with a project of mine.
Project- To interface an external temperature sensor MCP9808 through I2C communication with MSP430FR4133 to get temperature value.
Connections
SDA- pin 5.2
SCL- pin 5.3
GND-GND
VDD- 3.3V
I have interfaced a temperature sensor MCP9808 with MSP430FR4133 through i2c communication. I am using the following code to read the temperature value from the sensor. I couldn't find the required results to get temperature value.I am facing problem to get the desired results.
In MCP9808 data sheet in CONFIG Register part where I have to write Addressbyte(0x30),Configuration pointer (0x01), MSB(0x00), LSB (0x08) and read out Addressbyte(0x31), (0x00), (0x08) as a desired result but I am reading out Addressbyte(0x31), (0x00), (0x18), (0x01).

I have attached results below which are taken by logic analyzer. Any guidance to help me understand where I am doing mistake will be appreciated.


Code: Select all | TOGGLE FULL SIZE
#define I2C__MSP430FR4133_H_

#include <MSP430.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "usci.h"

#define AMBIENT_TEMPERATURE      0x05
//#define Configuration_Reg      0x01
#define DEVICE_ID_REGISTER        0x04
#define MANUFACTURE_ID_REGISTER           0x0054
//#define AdressByte                    0x30


 uint16_t tlen = 0;
 uint16_t rlen = 0;
 int *tx = NULL;
 int *rx = NULL;
 uint8_t addr = 0x18;
// void *tx =(void *)0x01;
// void *rx =(void *)0x00;

 
 
volatile unsigned char RXData;
volatile unsigned char TXData;

long Temperature;
void Stop_WD (void);
uint16_t I2C_TempRead(void);
uint16_t I2C_readMode(void);
void delay_tick(uint16_t);


unsigned char Adressbyte[10];
unsigned char Transmit [10];
unsigned char Meas_Receive [10];


int main(void)
{
 
  Stop_WD();
   
// Disable the GPIO power-on default high-impedance mode to activate
// previously configured port settings
PM5CTL0 &= ~LOCKLPM5;
Set_I2C();
//Transmit [0] =0x30 & 0xFE;
Transmit [0] = 0x02;
Transmit [1] = 0x05;
Transmit [2]=  0xA0;

Meas_Receive [0] = 0x07;


__bis_SR_register(GIE);

I2C_write(&Transmit[0],3,addr);

delay_tick(5);

Set_I2C();


I2C_write_read (&Transmit[0],1,&Meas_Receive [0],3,addr);
//I2C_write(&Transmit[0],1,addr);
//I2C_read(&Meas_Receive [0],2,addr);

I2C_readMode();
I2C_TempRead();

    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
    }
}



#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B0_VECTOR
__interrupt void USCIB0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCIB0_ISR (void)
#else
#error Compiler not supported!
#endif
{
  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;                  // resend start I2C start condition
      break;
    case USCI_I2C_UCSTTIFG:  break;         // Vector 6: STTIFG
    case USCI_I2C_UCSTPIFG:          // Vector 8: STPIFG
//     TXData = 0;
//     UCB0IFG &= ~UCSTPIFG;                 // Clear stop condition int flag
     break;
    case USCI_I2C_UCRXIFG3:  break;         // Vector 10: RXIFG3
    case USCI_I2C_UCTXIFG3:  break;         // Vector 14: TXIFG3
    case USCI_I2C_UCRXIFG2:  break;         // Vector 16: RXIFG2
    case USCI_I2C_UCTXIFG2:  break;         // Vector 18: TXIFG2
    case USCI_I2C_UCRXIFG1:  break;         // Vector 20: RXIFG1
    case USCI_I2C_UCTXIFG1:           // Vector 22: TXIFG1
//      UCB0TXBUF = TXData++;
      break;
    case USCI_I2C_UCRXIFG0:                 // Vector 24: RXIFG0
      RXData = UCB0RXBUF;                   // Get RX data
      __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
      break;
    case USCI_I2C_UCTXIFG0:  break;         // Vector 26: TXIFG0
    case USCI_I2C_UCBCNTIFG: break;         // Vector 28: BCNTIFG
    case USCI_I2C_UCCLTOIFG: break;         // Vector 30: clock low timeout
    case USCI_I2C_UCBIT9IFG: break;         // Vector 32: 9th bit
    default: break;
  }
}

void Stop_WD (void)
 {
   WDTCTL = WDTPW | WDTHOLD;                                    // Stop WDT
 }
//
//
//void Device_ID(uint8_t device_reg)
//{
//
//}
//
//void Manufacture_ID(uint8_t manufacture_reg)
//{
// 
//}
//
//void Ambient_Temp(uint8_t ambient_temp_reg)
//{
// 
//}                                                                                                                                                                           



uint16_t I2C_readMode(void)
{
  uint8_t UpperByte = 0;
  uint8_t LowerByte = 0;
  uint16_t data = 0;
 
//  UpperByte = i2c_read(); // READ 8 bits
////and Send ACK bit
//LowerByte = i2c_read(); // READ 8 bits
////and Send NAK bit
 
 data = UpperByte<<8|LowerByte;
 return data;
}

uint16_t I2C_TempRead(void)
{
 uint8_t UpperByte = 0;
 uint8_t LowerByte = 0;
 uint16_t Temperature = 0;
 
 
 //Convert the temperature data
//First Check flag bits
if ((UpperByte & 0x80) == 0x80)
{                                                       //TA ³ TCRIT
}
if ((UpperByte & 0x40) == 0x40)
{                                                       //TA > TUPPER
}
if ((UpperByte & 0x20) == 0x20)
{                                                       //TA < TLOWER
}
UpperByte = UpperByte & 0x1F;                           //Clear flag bits

if ((UpperByte & 0x10) == 0x10)
{                                                       //TA < 0°C
UpperByte = UpperByte & 0x0F;                           //Clear SIGN
Temperature = 256 - (UpperByte * 16 + LowerByte / 16);
}
else
{                                                       //TA ³ 0°C
Temperature = (UpperByte * 16 + LowerByte / 16);
                                                        //Temperature = Ambient Temperature (°C)
}
return Temperature;
}

void delay_tick(uint16_t tick)
{
  for (uint16_t i=0;i<tick; i++);
}



Code: Select all | TOGGLE FULL SIZE
//----------------------------------------------I2C--------------------------------//

void Set_I2C(void)
{
  P5SEL0 |= BIT2 | BIT3;                  // I2C pins
 // Configure USCI_B0 for I2C mode
  UCB0CTLW0 |= UCSWRST;                   // Software reset enabled
  UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC; // I2C mode, Master mode, sync
  UCB0CTLW1 |= UCASTP_2;                  // Automatic stop generated

  UCB0BRW = 0x0008;                         // baudrate = SMCLK / 8
  UCB0TBCNT = 0x07;                       // number of bytes to be received
  UCB0I2CSA = 0x18;                       // Slave address is 0x18
  UCB0CTL1 &= ~UCSWRST;
  UCB0IE |= UCRXIE | UCNACKIE | UCBCNTIE ;
 
 
}



//------------------I2C_Master_write-------------------------------------------------//

uint32_t I2C_write(unsigned char* tx, uint32_t tlen,uint8_t addr)

{
  uint32_t r_val = 0;
 
  UCB0I2CSA = addr;                             // Assing slave address
 
  while ((UCB0IFG & UCSTPIFG));                 // Check if Stop condition on
  UCB0CTL1 |= UCTR + UCTXSTT;                   // Start writing through I2C
  while (!(UCB0IFG & UCTXIFG));                 // Wait until TX buffer ready
  for(uint32_t i = 0; i < tlen; i++)
  {           
    UCB0TXBUF = *((uint8_t*)tx + i);            // Write string in  TX buffer of I2C       
    while (!(UCB0IFG & UCTXIFG));               // Wait until TX buffer ready
    if( i == tlen - 1)
    {                                           // If only one byte left to write
      UCB0CTL1 |= UCTXSTP;                      // I2C stop condition
      UCB0IFG &= ~UCTXIFG;                      // Clear USCI_B0 TX int flag
    }
    r_val++;                                    // Increment return value
  }

  return r_val;
}

//----------------I2C_MASTER_READ--------------------------------------------------------//

uint32_t I2C_read(unsigned char* rx, uint32_t rlen, uint8_t addr)

{
  UCB0IFG &= ~UCSTPIFG;
  uint32_t r_val = 0;
 
  UCB0I2CSA = addr;                               // Assing slave address
  if (rlen != 0)
  {
    while ((UCB0CTL1 & UCTXSTP));                 // Check if Stop condition on
    UCB0CTL1 &= ~UCTR;                            // Set writing bit in register to 0
    UCB0CTL1 |= UCTXSTT;                          // Start reading through I2C
    while (!(UCB0CTL1 & UCTXSTT));                // start condition is not sent
    // only one byte
    if (rlen == 1)
    {
      while (!(UCB0IFG & UCRXIFG))                // wait until start condition is sent
      {
        if((UCB0CTL1 & UCTXSTT)==0)
          UCB0CTL1 |= UCTXSTP;                    // generate stop condition
      }
      while (UCB0CTL1 & UCTXSTP);                 // Ensure stop condition got sent
      *((uint8_t*)rx) = UCB0RXBUF;
      return 1;
    }
    // multiple bytes
    for (uint8_t i = 0; i < rlen-1; i++)
    {
      while (!(UCB0IFG & UCRXIFG));                // Wait until new data was written into RX buffer
      *((uint8_t*)rx + i) = UCB0RXBUF;              // Read RX buffer
      r_val ++;                                     // Increment return value     
    }
    UCB0CTL1 |= UCTXSTP;                            // Generate Stop condition 
    while (UCB0CTL1 & UCTXSTP);                     // Wait untill its generated
    *((uint8_t*)rx+rlen-1) = UCB0RXBUF;             // Read last byte
  }
  return r_val++;
}

/*******************/

uint32_t I2C_write_read (unsigned char* tx,uint32_t tlen,unsigned char* rx, uint32_t rlen,uint8_t addr)
{
 
  uint32_t r_val = 0;
 
  UCB0I2CSA = addr;                             // Assing slave address
 
  while ((UCB0IFG & UCSTPIFG));                 // Check if Stop condition on
  UCB0CTL1 |= UCTR + UCTXSTT;                   // Start writing through I2C
  while (!(UCB0IFG & UCTXIFG));                 // Wait until TX buffer ready
  for(uint32_t i = 0; i < tlen; i++)
  {           
    UCB0TXBUF = *((uint8_t*)tx + i);            // Write string in  TX buffer of I2C       
    while (!(UCB0IFG & UCTXIFG));               // Wait until TX buffer ready
    if( i == tlen - 1)
    {                                           // If only one byte left to write
      UCB0CTL1 |= UCTXSTP;                      // I2C stop condition
      UCB0IFG &= ~UCTXIFG;                      // Clear USCI_B0 TX int flag
    }
    r_val++;                                    // Increment return value
  }
 
r_val = 0;
 
  if (rlen != 0)
  {
    while ((UCB0CTL1 & UCTXSTP));                 // Check if Stop condition on
    UCB0CTL1 &= ~UCTR;                            // Set writing bit in register to 0
    UCB0CTL1 |= UCTXSTT;                          // Start reading through I2C
    while (!(UCB0CTL1 & UCTXSTT));                // start condition is not sent
    // only one byte
    if (rlen == 1)
    {
      while (!(UCB0IFG & UCRXIFG))                // wait until start condition is sent
      {
        if((UCB0CTL1 & UCTXSTT)==0)
          UCB0CTL1 |= UCTXSTP;                    // generate stop condition
      }
      while (UCB0CTL1 & UCTXSTP);                 // Ensure stop condition got sent
      *((uint8_t*)rx) = UCB0RXBUF;
      return 1;
    }
    // multiple bytes
    for (uint8_t i = 0; i < rlen-1; i++)
    {
      while (!(UCB0IFG & UCRXIFG));                // Wait until new data was written into RX buffer
      *((uint8_t*)rx + i) = UCB0RXBUF;              // Read RX buffer
      r_val ++;                                     // Increment return value     
    }
    UCB0CTL1 |= UCTXSTP;                            // Generate Stop condition 
    while (UCB0CTL1 & UCTXSTP);                     // Wait untill its generated
    *((uint8_t*)rx+rlen-1) = UCB0RXBUF;             // Read last byte
  }
 
  return r_val++;
}


Best Regards,
Shetty
Student
Attachments
signal.PNG
Results taken by logic analyzer for MCP9808
signal.PNG (96.56 KiB) Viewed 97 times

rajatshetty
 
Posts: 1
Joined: Thu Jan 24, 2019 9:50 am

Re: MSP430 interfacing with MCP9808

by adafruit_support_mike on Fri Jan 25, 2019 2:10 am

The contents of the temperature register are explained on page 24 of the datasheet:

https://cdn-shop.adafruit.com/datasheets/MCP9808.pdf

If you combine the two temperature register bytes into a single 16-bit integer, the temperature value is stored in the lowest 12 bits using twos-complement notation. The numeric value is 16 times the actual temperature reading. The function to do the conversion would look like this:

Code: Select all | TOGGLE FULL SIZE
float convert ( unsigned int bytes ) {
   float sign;
   
   if ( bytes & 0x1000 ) {
      bytes ^= 0x0fff;
      bytes &= 0x0fff;
      sign = -1.0;
   } else {
      sign = 1.0;
   }
   return( sign * ( float )( bytes ) / 16.0 );
}

int main(int argc, char *argv[]) {
   unsigned int reg = 0x001f;
   
   printf( "%.5f\n", convert( reg ) );
   printf( "%.5f\n", convert( reg ^ 0xffff ) );
}

adafruit_support_mike
 
Posts: 59487
Joined: Thu Feb 11, 2010 2:51 pm

Please be positive and constructive with your questions and comments.