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.

DK-TM4C129X: TMP100 access inconsitant values when using tiva C series I2C read

Part Number: DK-TM4C129X

Hi,

I am trying to read temperature values form TM100 temp sensor available in the Tiva C series evaluation board....

When I try to single step through code I get correct values for temp(3....when I try to run the code I get inconsistent values (even negative temp values) ..... What is the reason for this....

I am attaching the C code...

//*****************************************************************************
//
// slave_receive_int.c - Example demonstrating a simple I2C master message
//                       transmission using a slave interrupt when data is
//                       received.
//
// Copyright (c) 2010-2013 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
//
//   Redistribution and use in source and binary forms, with or without
//   modification, are permitted provided that the following conditions
//   are met:
//
//   Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
//
//   Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the
//   distribution.
//
//   Neither the name of Texas Instruments Incorporated nor the names of
//   its contributors may be used to endorse or promote products derived
//   from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// This is part of revision 2.0.1.11577 of the Tiva Firmware Development Package.
//
//*****************************************************************************
#define TARGET_IS_SNOWFLAKE_RA0 // part no specifies 3 added to define silicon version
// DID0 reg value is 0x100A0002, signifies Snow flake class device version
//Die revision is A2 part revision 3
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_i2c.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"

//*****************************************************************************
//
//! \addtogroup i2c_examples_list
//! <h1>Slave Receive Interrupt (slave_receive_int)</h1>
//!
//! This example shows how to configure a receive interrupt on the slave
//! module.  This includes setting up the I2C0 module for loopback mode as well
//! as configuring the master and slave modules.  Loopback mode internally
//! connects the master and slave data and clock lines together.  The address
//! of the slave module is set to a value so it can receive data from the
//! master.
//!
//! This example uses the following peripherals and I/O signals.  You must
//! review these and change as needed for your own board:
//! - I2C0 peripheral
//! - GPIO Port B peripheral (for I2C0 pins)
//! - I2C0SCL - PB2
//! - I2C0SDA - PB3
//!
//! The following UART signals are configured only for displaying console
//! messages for this example.  These are not required for operation of I2C.
//! - UART0 peripheral
//! - GPIO Port A peripheral (for UART0 pins)
//! - UART0RX - PA0
//! - UART0TX - PA1
//!
//! This example uses the following interrupt handlers.  To use this example
//! in your own application you must add these interrupt handlers to your
//! vector table.
//! - INT_I2C0 - I2C0SlaveIntHandler
//
//*****************************************************************************
#define TempSensor_SlaveAddr 0x4A
#define Config_Reg 0x01
#define Temp_reg 0x00
#define SD_Configreg 0x01
//*****************************************************************************
//
// Set the address for slave module. This is a 7-bit address sent in the
// following format:
//                      [A6:A5:A4:A3:A2:A1:A0:RS]
//
// A zero in the R/S position of the first byte means that the master
// transmits (sends) data to the selected slave, and a one in this position
// means that the master receives data from the slave.
//
//*****************************************************************************
#define SLAVE_ADDRESS 0x4A // slave addr for temp sensor

//*****************************************************************************
//
// Global variable to hold the I2C data that has been received.
//
//*****************************************************************************
static uint32_t g_ui32DataRx;

//*****************************************************************************
//
// This is a flag that gets set in the interrupt handler to indicate that an
// interrupt occurred.
//
//*****************************************************************************
static bool g_bIntFlag = false;

//*****************************************************************************
//
// This function sets up UART0 to be used for a console to display information
// as the example is running.
//
//*****************************************************************************
void
InitConsole(void)
{
    //
    // Enable GPIO port A which is used for UART0 pins.
    // TODO: change this to whichever GPIO port you are using.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Configure the pin muxing for UART0 functions on port A0 and A1.
    // This step is not necessary if your part does not support pin muxing.
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);

    //
    // Enable UART0 so that we can configure the clock.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    //
    // Use the internal 16MHz oscillator as the UART clock source.
    //
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);

    //
    // Select the alternate (UART) function for these pins.
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Initialize the UART for console I/O.
    //
    UARTStdioConfig(0, 115200, 16000000);
}

//*****************************************************************************
//
// The interrupt handler for the for I2C0 data slave interrupt.
//
//*****************************************************************************
void
I2C6MasterIntHandler(void)
{
    //
    // Clear the I2C0 interrupt flag.
    //
	I2CMasterIntClear(I2C6_BASE);

    //
    // Read the data from the slave.
    //
    g_ui32DataRx = I2CMasterDataGet(I2C6_BASE);

    //
    // Set a flag to indicate that the interrupt occurred.
    //
    g_bIntFlag = true;
}

//*****************************************************************************
//
// Configure the I2C0 master and slave and connect them using loopback mode.
//
//*****************************************************************************
int
main(void)
{
    uint32_t ui32DataTx;
    volatile uint32_t pui32DataRx;

    uint32_t g_ui32SysClock; // acquire sysclk value
    bool busyFlag = false;
       //
       
       g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_OSC_MAIN | SYSCTL_XTAL_25MHZ | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480),
           		120000000);// changing to 25Mhz external crystal // Sysclk defined for 120Mhz
   

    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C6);

   
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

   
    GPIOPinConfigure(GPIO_PB6_I2C6SCL); // pin mux
    GPIOPinConfigure(GPIO_PB7_I2C6SDA); // pin mux

    
    GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_7);//    Configures pin for use as SDA
    GPIOPinTypeI2CSCL (GPIO_PORTB_BASE, GPIO_PIN_6);//    Configures pin for use as SCL
    
    I2CMasterInitExpClk(I2C6_BASE, g_ui32SysClock, true); // 400kbps   
    I2CMasterEnable(I2C6_BASE);
    I2CMasterSlaveAddrSet(I2C6_BASE, TempSensor_SlaveAddr, false); //write

    
    //
    InitConsole(); // UART initialization    
    UARTprintf("I2C Mater Interrupt Example ->");   
    // Place the data to be sent in the data register.    
    I2CMasterDataPut(I2C6_BASE, Config_Reg);
    I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_SINGLE_SEND); // send pointer addr
    while(I2CMasterBusy(I2C6_BASE))     continue;
 //Print
    UARTprintf("\n  Send Control reg addr!\n");


    // read config reg
    I2CMasterSlaveAddrSet(I2C6_BASE, TempSensor_SlaveAddr, true); // Config for read
    I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
    while(I2CMasterBusy(I2C6_BASE))     continue;
    pui32DataRx = I2CMasterDataGet(I2C6_BASE); 

	// write to pointer reg for temp reg
    I2CMasterSlaveAddrSet(I2C6_BASE, TempSensor_SlaveAddr, false); //Config for write
    I2CMasterDataPut(I2C6_BASE, Temp_reg);
    I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_SINGLE_SEND); // points to temp register
    while(I2CMasterBusy(I2C6_BASE))     continue;

	//read ist byte
    I2CMasterSlaveAddrSet(I2C6_BASE, TempSensor_SlaveAddr, true); // Config for read
    I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
    while(I2CMasterBusy(I2C6_BASE))     continue;
    pui32DataRx = I2CMasterDataGet(I2C6_BASE);
    pui32DataRx = pui32DataRx <<8;
	// read second byte
    I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    while(I2CMasterBusy(I2C6_BASE))     continue;
    pui32DataRx |= I2CMasterDataGet(I2C6_BASE);
    pui32DataRx = pui32DataRx >>4;
   

    UARTprintf("  1st Reading :'%d' \n\n", pui32DataRx); // ist temperaure read
		//
 //   I2CMasterSlaveAddrSet(I2C6_BASE, TempSensor_SlaveAddr, true); // Config for read
        I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
        while(I2CMasterBusy(I2C6_BASE))     continue;
        pui32DataRx = I2CMasterDataGet(I2C6_BASE);
        pui32DataRx = pui32DataRx <<8;

        I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
        while(I2CMasterBusy(I2C6_BASE))     continue;
        pui32DataRx |= I2CMasterDataGet(I2C6_BASE);
        pui32DataRx = pui32DataRx >>4;

   /* while(!(I2CMasterBusy(I2C6_BASE)))
    {}*/
        UARTprintf(" 2nd  Reading:'%d' \n\n", pui32DataRx); // 2nd temp read
    //
    // Loop forever.
    //
    while(1)
    {
    }
}

  • You might check out this post. e2e.ti.com/.../376872
  • After a fair bit of debugging using oscilloscope I realize that the issue could be due to the process in which I try to rerun the code in debugger.....
    I use CCS 7 the process i adopt
    1. reset core applying "core reset""
    2. restart using restart button

    ïs this correct??
  • I have followed  code structure as elaborated in the link provided.....Still the issue persists..... I have added delays as suggested....

    modified c code  ....

    //*****************************************************************************
    //
    // slave_receive_int.c - Example demonstrating a simple I2C master message
    //                       transmission using a slave interrupt when data is
    //                       received.
    //
    // Copyright (c) 2010-2013 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    //
    //   Redistribution and use in source and binary forms, with or without
    //   modification, are permitted provided that the following conditions
    //   are met:
    //
    //   Redistributions of source code must retain the above copyright
    //   notice, this list of conditions and the following disclaimer.
    //
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the
    //   documentation and/or other materials provided with the
    //   distribution.
    //
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    //
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    //
    // This is part of revision 2.0.1.11577 of the Tiva Firmware Development Package.
    //
    //*****************************************************************************
    //#define TARGET_IS_SNOWFLAKE_RA0 // part no specifies 3 added to define silicon version
    // DID0 reg value is 0x100A0002, signifies Snow flake class device version
    //Die revision is A2 part revision 3
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_i2c.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/i2c.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    
    
    //*****************************************************************************
    //
    //! \addtogroup i2c_examples_list
    //! <h1>Slave Receive Interrupt (slave_receive_int)</h1>
    //!
    //! This example shows how to configure a receive interrupt on the slave
    //! module.  This includes setting up the I2C0 module for loopback mode as well
    //! as configuring the master and slave modules.  Loopback mode internally
    //! connects the master and slave data and clock lines together.  The address
    //! of the slave module is set to a value so it can receive data from the
    //! master.
    //!
    //! This example uses the following peripherals and I/O signals.  You must
    //! review these and change as needed for your own board:
    //! - I2C0 peripheral
    //! - GPIO Port B peripheral (for I2C0 pins)
    //! - I2C0SCL - PB2
    //! - I2C0SDA - PB3
    //!
    //! The following UART signals are configured only for displaying console
    //! messages for this example.  These are not required for operation of I2C.
    //! - UART0 peripheral
    //! - GPIO Port A peripheral (for UART0 pins)
    //! - UART0RX - PA0
    //! - UART0TX - PA1
    //!
    //! This example uses the following interrupt handlers.  To use this example
    //! in your own application you must add these interrupt handlers to your
    //! vector table.
    //! - INT_I2C0 - I2C0SlaveIntHandler
    //
    //*****************************************************************************
    #define TempSensor_SlaveAddr 0x4A
    #define Config_Reg 0x01
    #define Temp_reg 0x00
    #define SD_Configreg 0x01
    //*****************************************************************************
    //
    // Set the address for slave module. This is a 7-bit address sent in the
    // following format:
    //                      [A6:A5:A4:A3:A2:A1:A0:RS]
    //
    // A zero in the R/S position of the first byte means that the master
    // transmits (sends) data to the selected slave, and a one in this position
    // means that the master receives data from the slave.
    //
    //*****************************************************************************
    #define SLAVE_ADDRESS 0x4A // slave addr for temp sensor
    
    //*****************************************************************************
    //
    // Global variable to hold the I2C data that has been received.
    //
    //*****************************************************************************
    static uint32_t g_ui32DataRx;
    
    //*****************************************************************************
    //
    // This is a flag that gets set in the interrupt handler to indicate that an
    // interrupt occurred.
    //
    //*****************************************************************************
    static bool g_bIntFlag = false;
    
    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    /*void
    InitConsole(void)
    {
        //
        // Enable GPIO port A which is used for UART0 pins.
        // TODO: change this to whichever GPIO port you are using.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Configure the pin muxing for UART0 functions on port A0 and A1.
        // This step is not necessary if your part does not support pin muxing.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
    
        //
        // Enable UART0 so that we can configure the clock.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
        //
        // Use the internal 16MHz oscillator as the UART clock source.
        //
        UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    
        //
        // Select the alternate (UART) function for these pins.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Initialize the UART for console I/O.
        //
        UARTStdioConfig(0, 115200, 16000000);
    }*/
    
    //*****************************************************************************
    //
    // The interrupt handler for the for I2C0 data slave interrupt.
    //
    //*****************************************************************************
    /*void
    I2C6MasterIntHandler(void)
    {
        //
        // Clear the I2C0 interrupt flag.
        //
        I2CMasterIntClear(I2C6_BASE);
    
        //
        // Read the data from the slave.
        //
        g_ui32DataRx = I2CMasterDataGet(I2C6_BASE);
    
        //
        // Set a flag to indicate that the interrupt occurred.
        //
        g_bIntFlag = true;
    }*/
    
    //*****************************************************************************
    //
    // Configure the I2C0 master and slave and connect them using loopback mode.
    //
    //*****************************************************************************
    int
    main(void)
    {
        uint32_t ui32DataTx,error;
        volatile uint32_t pui32DataRx,pui32Configdata = 0;
    
        uint32_t g_ui32SysClock; // acquire sysclk value
        bool busyFlag = false;
        g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_OSC_MAIN | SYSCTL_XTAL_25MHZ | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480),
                    120000000);// changing to 25Mhz external crystal // Sysclk defined for 120Mhz
        SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C6);
        while(!(SysCtlPeripheralReady(SYSCTL_PERIPH_I2C6)));
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
        while(!(SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB)));
    
        GPIOPinConfigure(GPIO_PB6_I2C6SCL); // pin mux
        GPIOPinConfigure(GPIO_PB7_I2C6SDA); // pin mux
    
        GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_7);//    Configures pin for use as SDA
        GPIOPinTypeI2CSCL (GPIO_PORTB_BASE, GPIO_PIN_6);//    Configures pin for use as SCL
    
        I2CMasterInitExpClk(I2C6_BASE, g_ui32SysClock,false);// 100kbps //true); // 400kbps
        I2CMasterSlaveAddrSet(I2C6_BASE, TempSensor_SlaveAddr, false); //write slave address )0x4A
    
        I2CMasterEnable(I2C6_BASE); // enable master mode
    
    
    
        //InitConsole(); //uart init
    
    
        // read config reg
        I2CMasterSlaveAddrSet(I2C6_BASE, TempSensor_SlaveAddr, false); //write slave address )0x4A
        I2CMasterDataPut(I2C6_BASE, Config_Reg); // pointer addr config reg
        I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_SINGLE_SEND); // send pointer addr
        while(I2CMasterBusy(I2C6_BASE));
        error = I2CMasterErr(I2C6_BASE);
            if (I2CMasterErr(I2C6_BASE) != I2C_MASTER_ERR_NONE)
            {
                I2CMasterIntClear(I2C6_BASE);   // clear the interrupts if any occured.
                return false;
            }
            SysCtlDelay(50);
        SysCtlDelay(50);
    
    
        I2CMasterSlaveAddrSet(I2C6_BASE, TempSensor_SlaveAddr, true); // Config for read
        I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
        while(I2CMasterBusy(I2C6_BASE));
        SysCtlDelay(50);
        pui32Configdata = I2CMasterDataGet(I2C6_BASE);
        // end config reg read
    
    
    
        // read temp register
    
        I2CMasterSlaveAddrSet(I2C6_BASE, TempSensor_SlaveAddr, false); //write
        I2CMasterDataPut(I2C6_BASE, Temp_reg);
        I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_SINGLE_SEND); // points to temp register
        while(I2CMasterBusy(I2C6_BASE));
        SysCtlDelay(50);
    
    
        I2CMasterSlaveAddrSet(I2C6_BASE, TempSensor_SlaveAddr, true); // Config for read
        I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
        while(I2CMasterBusy(I2C6_BASE));
        SysCtlDelay(50);
        pui32DataRx = I2CMasterDataGet(I2C6_BASE); // data high
        pui32DataRx = pui32DataRx <<8;
    
        I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
        while(I2CMasterBusy(I2C6_BASE))     continue;
        SysCtlDelay(50);
        pui32DataRx |= I2CMasterDataGet(I2C6_BASE); // data lower
        pui32DataRx = pui32DataRx >>4;
       // end temp read pui32DataRx has temp data
    
    
    
     //   read again temp data
            I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
            while(I2CMasterBusy(I2C6_BASE));
            SysCtlDelay(50);
            pui32DataRx = I2CMasterDataGet(I2C6_BASE);
            pui32DataRx = pui32DataRx <<8;
    
            I2CMasterControl(I2C6_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
            while(I2CMasterBusy(I2C6_BASE));
            SysCtlDelay(50);
            pui32DataRx |= I2CMasterDataGet(I2C6_BASE);
            pui32DataRx = pui32DataRx >>4;
    
    
    
        //
        // Loop forever.
        //
        while(1)
        {
        }
    }