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/MSP430FR5969: Problem to read temperature in TMP102 using I2C USCI_B

Part Number: MSP430FR5969
Other Parts Discussed in Thread: TMP102

Tool/software: Code Composer Studio

Hey everyone!

I`m trying to finish my implementation of I2C using Drivelib to read and configure the TMP102 but without success in read mode. 

After set the register 0x00 ( Temperature register ) as showed below :  I2C TMP102 address (0x48) in transmition data ( 0x90 write mode / 0x91 read mode ) 

to Set it I used the code: 

EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, TMP102_I2C_ADDRESS); // Set TMP102 address
EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_MODE); //Set in transmit mode
EUSCI_B_I2C_masterSendMultiByteStartWithTimeout(EUSCI_B0_BASE,0x00,Timeout_I2C);//init the transmition with
EUSCI_B_I2C_masterSendMultiByteFinishWithTimeout(EUSCI_B0_BASE,0x00,Timeout_I2C);

while ((EUSCI_B_I2C_isBusBusy(EUSCI_B0_BASE))&& --Timeoutcounter);

After set the register I need start to receive the data. The TMP102 send 2 bytes ( MSB and LSB ) 

In accordance with with the examples I code it:  

( I2C with out interrupt mode) 

EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, TMP102_I2C_ADDRESS); // Set TMP102 address
EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_MODE);

// Send start
EUSCI_B_I2C_masterReceiveStart(EUSCI_B0_BASE);
while (EUSCI_B_I2C_isBusBusy(EUSCI_B0_BASE)) ;

// Receive first byte
Temp_Word[2] = EUSCI_B_I2C_masterReceiveMultiByteNext(EUSCI_B0_BASE);
while (EUSCI_B_I2C_isBusBusy(EUSCI_B0_BASE)) ;

// Receive second byte
Temp_Word[1]= EUSCI_B_I2C_masterReceiveMultiByteFinish(EUSCI_B0_BASE);
while (EUSCI_B_I2C_isBusBusy(EUSCI_B0_BASE)) ;

// Disable I2C Module
EUSCI_B_I2C_disable(EUSCI_B0_BASE);

Temp_Word_out = Temp_Word[0]<<8;
Temp_Word_out = Temp_Word_out + Temp_Word[1];
return Temp_Word_out ;

The I2C receive the first byte (0x16) that is compatible with the temperature now, but stop after it as show in figure below

Someone can help me understand where is the problem and what shall I do to solve it?

1- why the transmission stop after the first byte received? 

2 When I send the command to configure the TMP register I need send twice the command (EUSCI_B_I2C_masterSendMultiByteFinishWithTimeout(EUSCI_B0_BASE,0x00,Timeout_I2C);) if I put only one command the I2C send only the slave address. Why does this happen?

Thank you and best regards 

 

  • Hey Carlos,

    UCBBUSY is set after a START and cleared after a STOP, therefore you are getting forever trapped inside of the while loop. Instead of checking UCBBUSY You should poll UCRXIFG0 to see if data is ready or use the EUSCI_B_I2CmasterReceiveSingle function, which does this automatically.

    Regards,
    Ryan
  • Hey Ryan, thank you for your time and attention. 

    I did some modifications in code and I detect ed some strange fails. 

     My first routine is setup the TMP102 , I configured this temperature sensor with 0x60A0

    unsigned char TMP102_config(void)
    {
    unsigned char HighByte;
    unsigned char LowByte;
    unsigned long Timeoutcounter=Timeout_I2C;
    unsigned char status_transmition = 1;

    HighByte = config_sensor>>8;
    LowByte = config_sensor&0x00FF;

    EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, TMP102_I2C_ADDRESS); // Set TMP102 address
    EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_MODE); //Set in transmit mode
    EUSCI_B_I2C_masterSendMultiByteStartWithTimeout(EUSCI_B0_BASE,Conf_Reg,Timeout_I2C);//init the transmition with
    EUSCI_B_I2C_masterSendMultiByteNextWithTimeout(EUSCI_B0_BASE,HighByte, Timeout_I2C);
    EUSCI_B_I2C_masterSendMultiByteFinishWithTimeout(EUSCI_B0_BASE,LowByte,Timeout_I2C);

    while ((EUSCI_B_I2C_isBusBusy(EUSCI_B0_BASE))&& --Timeoutcounter);
    {
    ;
    }

    //Check if transfer timed out
    if(Timeoutcounter == 0)
    {
    status_transmition = 0;
    }
    return status_transmition;
    }

    After this routine I sent command to read the TMP102 with the modifications I have this waveform 

     with correct data in I2C read variables. 

    The code used was 

    unsigned int TMP102_Read_Temp(void)
    {
    unsigned char HighByte;
    unsigned char LowByte;
    unsigned char Temp_Word[2];
    unsigned int Temp_Word_out;
    unsigned long Timeoutcounter=Timeout_I2C;

    EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, TMP102_I2C_ADDRESS); // Set TMP102 address
    EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_MODE); //Set in transmit mode
    EUSCI_B_I2C_masterSendMultiByteStartWithTimeout(EUSCI_B0_BASE,0x00,Timeout_I2C);//init the transmition with
    EUSCI_B_I2C_masterSendMultiByteFinishWithTimeout(EUSCI_B0_BASE,0x00,Timeout_I2C);

    while ((EUSCI_B_I2C_isBusBusy(EUSCI_B0_BASE))&& --Timeoutcounter);
    {
    ;
    }

    EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, TMP102_I2C_ADDRESS); // Set TMP102 address
    EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_MODE);


    // Send start
    EUSCI_B_I2C_masterReceiveStart(EUSCI_B0_BASE);
    while (EUSCI_B_I2C_isBusBusy(EUSCI_B0_BASE)) ;
    Temp_Word[1] = EUSCI_B_I2C_masterReceiveSingle(EUSCI_B0_BASE);
    Temp_Word[0] = EUSCI_B_I2C_masterReceiveSingle(EUSCI_B0_BASE);
    // Disable I2C Module
    EUSCI_B_I2C_disable(EUSCI_B0_BASE);

    Temp_Word_out = Temp_Word[1]<<8;
    Temp_Word_out = Temp_Word_out + Temp_Word[0];
    return Temp_Word_out>>4 ;
    }

    But after this first loop the code stop work after the function uint8_t EUSCI_B_I2C_masterReceiveSingle(uint16_t baseAddress) be called. This function is DriverLib 


     

    May you help understand what is happening?  Thank you and best regards 

     

  • You probably need to be sending a stop command after reading the last byte and re-starting a read sequence, using EUSCI_B_I2C_masterReceiveMultiByteStop before disabling the communication or EUSCI_B_I2C_masterReceiveMultiByteFinish on the last byte instead of EUSCI_B_I2C_masterReceiveSingle.

    Regards,
    Ryan
  • Hey Ryan!

    Your answer help me, but I have some problems. In fact this I2C driverlib explanations are very bad.

    But ok go to try solve my problem.

    I fixed the problem in my I2C data transmittion, but work only when I send one byte.

    I created this function:

    unsigned char I2C_ADDR_DATA_TX(unsigned char addr, unsigned char data)

    {

    unsigned long Timeoutcounter=Timeout_I2C;

    unsigned char status_transmition = 1;  //set the transmission status as 1 = transmission ok

    EUSCI_B_I2C_enable(EUSCI_B0_BASE);   // enable I2C interface

    EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, addr); // Set TMP102 address

    EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_MODE); //Set in transmit mode

    EUSCI_B_I2C_masterSendSingleByteWithTimeout(EUSCI_B0_BASE, data, Timeout_I2C);//transmit the data

    EUSCI_B_I2C_masterIsStopSent(EUSCI_B0_BASE);

       while ((EUSCI_B_I2C_isBusBusy(EUSCI_B0_BASE))&& --Timeoutcounter);

       //Check if transfer timed out

       if(Timeoutcounter == 0)

       {

        status_transmition = 0;

       }

       return status_transmition;

    }

     

    When I run this function in my main loop  the result is 

    while (1)
    {

    __delay_cycles(15000);
    LED_Pilot_Heart_Bit_Toggle ();
    I2C_ADDR_DATA_TX (0x48, 0x55)

    }

     


    I2C sending single byte - OK. 

     

    In my case I need send 1 or 2 bytes. 

    Following the idea and short explanations of driverlib manual I change the function 

    EUSCI_B_I2C_masterSendSingleByteWithTimeout(EUSCI_B0_BASE, data, Timeout_I2C);//transmit the data single byte 

    for function able to send multiple bytes. I need to start the communication send multiple bytes and finish the communication. 

    unsigned char I2C_ADDR_DATA_WORD_TXX(unsigned char addr, unsigned char data_a, unsigned char data_b)
    {


    unsigned long Timeoutcounter=Timeout_I2C;
    unsigned char status_transmition = 1; //set the transmission status as 1 = transmission ok
    EUSCI_B_I2C_enable(EUSCI_B0_BASE); // enable I2C interface
    EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, addr); // Set TMP102 address
    EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_MODE); //Set in transmit mode
    EUSCI_B_I2C_masterSendMultiByteStartWithTimeout(EUSCI_B0_BASE, data_a,Timeout_I2C);       <<<< send first byte 
    EUSCI_B_I2C_masterSendMultiByteFinishWithTimeout(EUSCI_B0_BASE, data_b,Timeout_I2C);     <<<< send second byte
    //EUSCI_B_I2C_masterIsStopSent(EUSCI_B0_BASE);
    while ((EUSCI_B_I2C_isBusBusy(EUSCI_B0_BASE))&& --Timeoutcounter);
    //Check if transfer timed out
    if(Timeoutcounter == 0)
    {
    status_transmition = 0;
    }
    return status_transmition;

    }

    //Main Loop

    while (1)
    {

    __delay_cycles(150);
    LED_Pilot_Heart_Bit_Toggle ();
    I2C_ADDR_DATA_WORD_TXX(0x48, 0x55, 0xAA);


    }

    The first I2C transmission  works perfectly  ( 0x48 = 0X90(I2C ADDR) 0x55 and 0xAA), but after the first transmission the MCU stop to send the first byte 0x55. 

    What it is wrong in my code? 

     

    Now when I go to receive the data of TMP102

    unsigned int I2C_ADDR_RX(unsigned char addr)
    {


    unsigned long Timeoutcounter=Timeout_I2C;
    unsigned char status_transmition = 1; //set the transmission status as 1 = transmission ok
    unsigned char Temp_Word[2];
    unsigned int Temp_Word_out;


    I2C_ADDR_DATA_TX(0x48,0x00);  //<< Here I configure the register that I want to read 
    EUSCI_B_I2C_enable(EUSCI_B0_BASE); // enable I2C interface
    EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, addr); // Set TMP102 address
    EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_MODE);
    EUSCI_B_I2C_masterReceiveStart(EUSCI_B0_BASE);
    Temp_Word[1] = EUSCI_B_I2C_masterReceiveSingleByte(EUSCI_B0_BASE);   //< Here I receive the  
    EUSCI_B_I2C_masterIsStopSent(EUSCI_B0_BASE);
    while ((EUSCI_B_I2C_isBusBusy(EUSCI_B0_BASE))&& --Timeoutcounter);
    Temp_Word_out = Temp_Word[1]<<8;
    Temp_Word_out = Temp_Word_out + Temp_Word[0];
    return Temp_Word_out>>4 ;

    }

     

     


     

    When I include in code the reading of second byte: 

     

    unsigned int I2C_ADDR_RX_WORD(unsigned char addr)
    {
    unsigned long Timeoutcounter=Timeout_I2C;
    unsigned char status_transmition = 1; //set the transmission status as 1 = transmission ok
    unsigned char Temp_Word[2];
    unsigned int Temp_Word_out;
    EUSCI_B_I2C_enable(EUSCI_B0_BASE); // enable I2C interface
    EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, addr); // Set TMP102 address
    EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_MODE);
    EUSCI_B_I2C_masterReceiveStart(EUSCI_B0_BASE);
    Temp_Word[1] = EUSCI_B_I2C_masterReceiveMultiByteNext(EUSCI_B0_BASE);
    Temp_Word[0] = EUSCI_B_I2C_masterReceiveMultiByteFinish(EUSCI_B0_BASE);
    EUSCI_B_I2C_masterReceiveMultiByteStop(EUSCI_B0_BASE);
    while ((EUSCI_B_I2C_isBusBusy(EUSCI_B0_BASE))&& --Timeoutcounter);
    Temp_Word_out = Temp_Word[1]<<8;
    Temp_Word_out = Temp_Word_out + Temp_Word[0];
    return Temp_Word_out>>4 ;

    }

     


     

    Only the first byte arrive . What is the problem ? 

     

    Thank you for your attention and best regards. 

     

  • Hey Carlos,

    For the transmission issue, have you tried using a longer delay (1 ms) in-between transmissions or used EUSCI_B_I2C_masterSendMultiByteNext followed with EUSCI_B_I2C_masterSendMultiByteStop?

    For the reception issue, have you tried using EUSCI_B_I2C_masterReceiveSingle twice followed with EUSCI_B_I2C_masterReceiveMultiByteStop and a long delay (2 ms) between sequences? Or perhaps EUSCI_B_I2C_masterReceiveSingle and EUSCI_B_I2C_masterReceiveMultiByteFinish along with a delay?

    Regards,
    Ryan
  • Now the I2C work. The tip about data reception was right, I put the code of TX and RX I2C below.  The tip for transmission didn't work I changed the code again and function EUSCI_B_I2C_masterSendMultiByteFinishWithTimeout and EUSCI_B_I2C_masterSendMultiByteStartWithTimeout didn't work properly.

    Thank you and now  work with SPI. 

     

    unsigned char I2C_ADDR_DATA_WORD_TXX(unsigned char addr, unsigned char data_a, unsigned char data_b)
    {


    unsigned long Timeoutcounter=Timeout_I2C;
    unsigned char status_transmition = 1; //set the transmission status as 1 = transmission ok
    EUSCI_B_I2C_enable(EUSCI_B0_BASE); // enable I2C interface
    EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, addr); // Set TMP102 address
    EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_MODE); //Set in transmit mode
    EUSCI_B_I2C_masterSendStart(EUSCI_B0_BASE);
    EUSCI_B_I2C_masterSendMultiByteNextWithTimeout(EUSCI_B0_BASE, data_a,Timeout_I2C);
    EUSCI_B_I2C_masterSendMultiByteNextWithTimeout(EUSCI_B0_BASE, data_b,Timeout_I2C);
    EUSCI_B_I2C_masterSendMultiByteStop(EUSCI_B0_BASE);
    while ((EUSCI_B_I2C_isBusBusy(EUSCI_B0_BASE))&& --Timeoutcounter);
    //Check if transfer timed out
    if(Timeoutcounter == 0)
         {
                     status_transmition = 0;
         }
    return status_transmition;

    }

    unsigned int I2C_ADDR_RX_WORD(unsigned char addr)
    {


    unsigned long Timeoutcounter=Timeout_I2C;
    unsigned char status_transmition = 1; //set the transmission status as 1 = transmission ok
    unsigned char Temp_Word[2];
    unsigned int Temp_Word_out;
    EUSCI_B_I2C_enable(EUSCI_B0_BASE); // enable I2C interface
    EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, addr); // Set TMP102 address
    EUSCI_B_I2C_setMode(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_MODE);
    EUSCI_B_I2C_masterReceiveStart(EUSCI_B0_BASE);
    Temp_Word[1] = EUSCI_B_I2C_masterReceiveSingle(EUSCI_B0_BASE);
    Temp_Word[0] = EUSCI_B_I2C_masterReceiveSingle(EUSCI_B0_BASE);
    EUSCI_B_I2C_masterReceiveMultiByteStop(EUSCI_B0_BASE);
    while ((EUSCI_B_I2C_isBusBusy(EUSCI_B0_BASE))&& --Timeoutcounter);
    Temp_Word_out = Temp_Word[1]<<8;
    Temp_Word_out = Temp_Word_out + Temp_Word[0];
    return Temp_Word_out>>4 ;

    }

     



**Attention** This is a public forum