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.

TIva C Series TM4C123G I2C Problems

Other Parts Discussed in Thread: ENERGIA

Greetings, 

I'm currently trying to interface my Tiva C Series with a Sparkfun Breakout Board, IMU Digital Combo Board - 6 Degrees of Freedom ITG3200/ADXL345 and I'm having trouble with the I2C interface. 

currently this is my code:

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"

uint8_t SLAVE_ADDRESS = 0x68;

uint32_t first_byte, second_byte, temperature, result;

void i2c_setup(void) {


//Enable the I2C Module
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C2);

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

//Wait at least 5 clock cycles
SysCtlDelay(2);

//Configure SDA and SCL
GPIOPinConfigure(GPIO_PE4_I2C2SCL);

GPIOPinConfigure(GPIO_PE5_I2C2SDA);

//Wait at least 5 clock cycles
SysCtlDelay(2);

//Set PE4 as SCL
GPIOPinTypeI2CSCL(GPIO_PORTE_BASE, GPIO_PIN_4);

//Set PE5 as SDA
GPIOPinTypeI2C(GPIO_PORTE_BASE, GPIO_PIN_5);

//Configure Master,
I2CMasterInitExpClk(I2C2_BASE, SysCtlClockGet(), false);

}

uint32_t i2c_read() {

I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS, false);

I2CMasterDataPut(I2C2_BASE, 0x1A);

I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_SINGLE_SEND);

while(I2CMasterBusBusy(I2C2_BASE)); //Loop until the bus is no longer busy

I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDRESS, true );

I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);

while(I2CMasterBusBusy(I2C2_BASE)); //Loop until the bus is no longer busy

first_byte = I2CMasterDataGet(I2C2_BASE);

return first_byte;

}

void setup()
{
Serial.begin(9600);
i2c_setup();
}

void loop()
{

int test = i2c_read();
Serial.println(test);
delay(1000);
}

I'm using Energia to test my program, and when I try to read from the specified register, I get the same result, no matter which register I choose, the result is always decimal 229 (this is the Accelerometer's Device Address).

Can somebody point me in the right direction, I've been looking at my code for quite some time and still don't know whats wrong...

Thanks! 

  • Hi Cesar,

        Here below is the appropriate forum for your question. 

        http://e2e.ti.com/support/microcontrollers/tiva_arm/default.aspx

    -kel

  • hello 

    I am using LM3S microcontroller.i had used this code for i2c connection please read this,its working with my board.

    //*****************************************************************************************************
    // Global Variables
    //*****************************************************************************************************
    
    unsigned long	ulI2CBase = I2C0_MASTER_BASE;				///BASE address of i2c device
    unsigned char ucSlaveAdress = SLAVE_ADDRESS;					//slave address (address of EEPROM).
    
    void Configure_I2C(void)
    {
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0) ;
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB) ;
    
    	GPIOPinConfigure(GPIO_PB2_I2C0SCL);
    	GPIOPinConfigure(GPIO_PB3_I2C0SDA);
    	GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_2 | GPIO_PIN_3) ;
    
    	GPIODirModeSet(GPIO_PORTB_BASE, GPIO_PIN_3, GPIO_DIR_MODE_HW);
    	GPIODirModeSet(GPIO_PORTB_BASE, GPIO_PIN_2, GPIO_DIR_MODE_HW);
    	    // Enable and initialise the I2C0 master module.  Use the system clock for
    	    // the I2C0 module.  The last parameter sets the I2C data transfer rate.
    	    // If false the data rate is set to 100kbps and if true the data rate will
    	    // be set to 400kbps.  For this example we will use a data rate of 100kbps.
    
    	I2CMasterInitExpClk(I2C0_MASTER_BASE, SysCtlClockGet(), 1);  // 400kbps if 3rd args is 0 them 100Khz and if 1 then 400KHz
    	I2CMasterEnable(I2C0_MASTER_BASE);
    }
    
    
    
    //*****************************************************************************
    //
    //! Probes the selected I2C bus for available slave devices
    //!
    //! \param ulI2CBase is the base for the I2C module.
    //!
    //! This function scans the selected I2C bus for available I2C slave device.
    //! The ulI2CBase parameter is the I2C modules master base address.
    //! \e ulI2CBase parameter can be one of the following values:
    //!
    //! - \b I2C0_MASTER_BASE
    //! - \b I2C1_MASTER_BASE
    //! - \b I2C2_MASTER_BASE
    //! - \b I2C3_MASTER_BASE
    //!
    //! \return 0 if there was an error or 1 if there was not.
    //
    //*****************************************************************************
    unsigned long
    I2CBusScan(unsigned long ulI2CBase)
    {
    	unsigned char ucProbeAdress;
    	unsigned long ucerrorstate;
    
    
    
    	//
    	// Wait until master module is done transferring.
    	//
    	while(I2CMasterBusy(ulI2CBase))
    	{
    	};
    
    	//
    	// I2C Addresses are 7-bit values
    	// probe the address range of 0 to 127 to find I2C slave devices on the bus
    	//
    	for (ucProbeAdress = 0; ucProbeAdress < 127; ucProbeAdress++)
    	{
    	    //
    	    // Tell the master module what address it will place on the bus when
    	    // writing to the slave.
    	    //
    		I2CMasterSlaveAddrSet(ulI2CBase, ucProbeAdress, false);
    	    SysCtlDelay(TIMER_1_MS);
    
    	    //
    	    // Place the command to be sent in the data register.
    	    //
    	    I2CMasterDataPut(ulI2CBase, 0x00);
    
    	    //
    	    // Initiate send of data from the master.
    	    //
    	    I2CMasterControl(ulI2CBase, I2C_MASTER_CMD_BURST_SEND_START);
    
    	    //
    	    // Make some delay
    	    //
    	    SysCtlDelay(TIMER_1_MS);
    
    	    //
    	    // Read the I2C Master Control/Status (I2CMCS) Register to a local
    	    // variable
    	    //
    	    ucerrorstate = I2CMasterErr(ulI2CBase);
    
    	    //
    	    // Examining the content I2C Master Control/Status (I2CMCS) Register
    	    // to see if the ADRACK-Bit (Acknowledge Address) is TRUE (1)
    	    // ( 1: The transmitted address was not acknowledged by the slave)
    	    //
    	    if(ucerrorstate & I2C_MASTER_ERR_ADDR_ACK)
    	    {
    	    	//
    	    	// device at selected address did not acknowledge --> there's no device
    	    	// with this address present on the I2C bus
    	    	//
    	        //
    	        // Print a message to Stdio
    	        //
    	    	//UARTprintf("Address not found: 0x%2x - %3d\n",ucProbeAdress,ucProbeAdress);
    		    //
    		    // Make some delay
    		    //
    	    	//ROM_SysCtlDelay(1500000);
    	    }
    
    	    //
    	    // ( 0: The transmitted address was acknowledged by the slave)
    	    //
    	    else
    	    {
    	    	//
    	    	// device at selected address acknowledged --> there is a device
    	    	// with this address present on the I2C bus
    	    	//
    	        //
    	        // Print a message to Stdio
    	        //
    	    	UARTprintf("Address found: 0x%2x - %3d\n\r",ucProbeAdress,ucProbeAdress);
    
    		    //
    		    // Make some delay
    		    //
    	    	SysCtlDelay(TIMER_1_MS);
    	    }
    	}
    
    	//
    	// End transfer of data from the master.
    	//
    	I2CMasterControl(ulI2CBase, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    
        //
        // Print a message to Stdio
        //
    	UARTprintf("I2C Bus-Scan done...\n");
    
        //
        // Return 1 if there is no error.
        //
        return TRUE;
    }
    
    
    
    
    
    
    
    
    //*****************************************************************************
    //
    //! Reads one/multiple bytes of data from an I2C slave device.
    //!
    //! \param ulI2CBase is the base for the I2C module.
    //! \param ucSlaveAdress is the 7-bit address of the slave to be addressed.
    //! \param ucReg is the register to start reading from.
    //! \param cReadData is a pointer to the array to store the data.
    //! \param uiSize is the number of bytes to read from the slave.
    //!
    //! This function reads one/multiple bytes of data from an I2C slave device.
    //! The ulI2CBase parameter is the I2C modules master base address.
    //! \e ulI2CBase parameter can be one of the following values:
    //!
    //! - \b I2C0_MASTER_BASE
    //! - \b I2C1_MASTER_BASE
    //! - \b I2C2_MASTER_BASE
    //! - \b I2C3_MASTER_BASE
    //!
    //! \return 0 if there was an error or 1 if there was not.
    //
    //*****************************************************************************
    unsigned long
    I2CReadData(unsigned long ulI2CBase, unsigned char ucSlaveAdress,
    		unsigned char ucReg, char* cReadData, unsigned int uiSize)
    {
    	unsigned int uibytecount;		// local variable used for byte counting/state determination
    	int MasterOptionCommand;		// used to assign the commands for ROM_I2CMasterControl() function
    
        //
        // Tell the master module what address it will place on the bus when
        // writing to the slave.
        //
        I2CMasterSlaveAddrSet(ulI2CBase, ucSlaveAdress, 0);
    
        //
        // Place the command to be sent in the data register.
        //
        I2CMasterDataPut(ulI2CBase, ucReg);
    
        //
        // Initiate send of data from the master.
        //
        I2CMasterControl(ulI2CBase, I2C_MASTER_CMD_SINGLE_SEND);
    
        //
        // Wait until master module is done transferring.
        //
        while(I2CMasterBusy(ulI2CBase))
        {
        };
    
        //
        // Check for errors.
        //
        if(I2CMasterErr(ulI2CBase) != I2C_MASTER_ERR_NONE)
        {
            return 0;
        }
    
    
    	//
    	// Tell the master module what address it will place on the bus when
    	// reading from the slave.
    	//
    	I2CMasterSlaveAddrSet(ulI2CBase, ucSlaveAdress, true);
    
    	//
    	// Start with BURST with more than one byte to write
    	//
    	MasterOptionCommand = I2C_MASTER_CMD_BURST_RECEIVE_START;
    
    
    	for(uibytecount = 0; uibytecount < uiSize; uibytecount++)
    	{
    		//
    		// The second and intermittent byte has to be read with CONTINUE control word
    		//
    		if(uibytecount == 1)
    			MasterOptionCommand = I2C_MASTER_CMD_BURST_RECEIVE_CONT;
    
    		//
    		// The last byte has to be send with FINISH control word
    		//
    		if(uibytecount == uiSize - 1)
    			MasterOptionCommand = I2C_MASTER_CMD_BURST_RECEIVE_FINISH;
    
    		//
    		// Re-configure to SINGLE if there is only one byte to read
    		//
    		if(uiSize == 1)
    			MasterOptionCommand = I2C_MASTER_CMD_SINGLE_RECEIVE;
    
    		//
    		// Initiate read of data from the slave.
    		//
    		I2CMasterControl(ulI2CBase, MasterOptionCommand);
    
    		//
    		// Wait until master module is done reading.
    		//
    		while(I2CMasterBusy(ulI2CBase))
    		{
    		};
    
    		//
            // Check for errors.
            //
            if(I2CMasterErr(ulI2CBase) != I2C_MASTER_ERR_NONE)
            {
                return 0;
            }
    
            //
            // Move byte from register
            //
    		cReadData[uibytecount] = I2CMasterDataGet(ulI2CBase);
    		UARTprintf("%c",cReadData[uibytecount]);
    	}
    	UARTprintf("\n\r EEPROM Read completed \n\r");
    	// send number of received bytes
    	return uibytecount;
    }
    
    
    
    
    
    //*****************************************************************************
    //
    //! Writes one/multiple bytes of data to an I2C slave device.
    //! Ensure to use auto-increment options on some devices
    //! (Control Registers, refer to data sheet).
    //! I.e. store related command in the first position of your data array.
    //!
    //! \param ulI2CBase is the base for the I2C module.
    //! \param ucSlaveAdress is the 7-bit address of the slave to be addressed.
    //! \param ucReg is the register to start writing to.
    //! \param cSendData is a pointer to the array to be send.
    //! \param uiSize is the number of bytes to send from array cSendData[].
    //!
    //! This function writes multiple bytes of data an I2C slave device.
    //! The ulI2CBase parameter is the I2C modules master base address.
    //! \e ulI2CBase parameter can be one of the following values:
    //!
    //! - \b I2C0_MASTER_BASE
    //! - \b I2C1_MASTER_BASE
    //! - \b I2C2_MASTER_BASE
    //! - \b I2C3_MASTER_BASE
    //!
    //! \return 0 if there was an error or 1 if there was not.
    //
    //*****************************************************************************
    unsigned long
    I2CWriteData(unsigned long ulI2CBase, unsigned char ucSlaveAdress,
    		unsigned char ucReg, char* cSendData, unsigned int uiSize)
    {
    	unsigned int uibytecount;		// local variable used for byte counting/state determination
    	int MasterOptionCommand;		// used to assign the commands for I2CMasterControl() function
    
    
    
        //
        // Tell the master module what address it will place on the bus when
        // writing to the slave.
        //
        I2CMasterSlaveAddrSet(ulI2CBase, ucSlaveAdress, false);
    
        //
        // Place the value to be sent in the data register.
        //
        I2CMasterDataPut(ulI2CBase, ucReg);
    
        //
        // Initiate send of data from the master.
        //
        I2CMasterControl(ulI2CBase, I2C_MASTER_CMD_BURST_SEND_START);
    
        //
        // Wait until master module is done transferring.
        //
        while(I2CMasterBusy(ulI2CBase))
        {
        };
    
        //
        // Check for errors.
        //
        if(I2CMasterErr(ulI2CBase) != I2C_MASTER_ERR_NONE)
        {
            return 0;
        }
    
    	//
    	// Start with CONT for more than one byte to write
    	//
    	MasterOptionCommand = I2C_MASTER_CMD_BURST_SEND_CONT;
    
    
    	for(uibytecount = 0; uibytecount < uiSize; uibytecount++)
    	{
    		//
    		// The second and intermittent byte has to be send with CONTINUE control word
    		//
    		if(uibytecount == 1)
    			MasterOptionCommand = I2C_MASTER_CMD_BURST_SEND_CONT;
    
    		//
    		// The last byte has to be send with FINISH control word
    		//
    		if(uibytecount == uiSize - 1)
    			MasterOptionCommand = I2C_MASTER_CMD_BURST_SEND_FINISH;
    
    		//
    		// Re-configure to SINGLE if there is only one byte to write
    		//
    		if(uiSize == 1)
    			MasterOptionCommand = I2C_MASTER_CMD_SINGLE_SEND;
    
    		//
    		// Send data byte
    		//
    		UARTprintf("%c",cSendData[uibytecount]);
    		I2CMasterDataPut(ulI2CBase, cSendData[uibytecount]);
    
    		//
    		// Initiate send of data from the master.
    		//
    		I2CMasterControl(ulI2CBase, MasterOptionCommand);
    
    		//
    		// Wait until master module is done transferring.
    		//
    		while(I2CMasterBusy(ulI2CBase))
    		{
    		};
    
    		//
            // Check for errors.
            //
            if(I2CMasterErr(ulI2CBase) != I2C_MASTER_ERR_NONE)
            {
                return 0;
            }
    	}
    	UARTprintf("\n\rEEPROM write Completed \n\r");
    
        //
        // Return 1 if there is no error.
        //
        return 1;
    }
    
    
    
    unsigned long
    I2CRegRead(unsigned long ulI2CBase, unsigned char ucSlaveAdress, unsigned char ucReg)
    {
    unsigned long ulRegValue = 0;
    
    
        // Tell the master module what address it will place on the bus when
        // writing to the slave.
        //
        I2CMasterSlaveAddrSet(ulI2CBase, ucSlaveAdress, 0);
    
        //
        // Place the command to be sent in the data register.
        //
        I2CMasterDataPut(ulI2CBase, ucReg);
    
        //
        // Initiate send of data from the master.
        //
        I2CMasterControl(ulI2CBase, I2C_MASTER_CMD_SINGLE_SEND);
    
        //
        // Wait until master module is done transferring.
        //
        while(I2CMasterBusy(ulI2CBase))
        {
        };
    
        //
        // Check for errors.
        //
        if(I2CMasterErr(ulI2CBase) != I2C_MASTER_ERR_NONE)
        {
    //    	UARTprintf("1 ");
            return 0;
        }
    
        //
        // Tell the master module what address it will place on the bus when
        // reading from the slave.
        //
        I2CMasterSlaveAddrSet(ulI2CBase, ucSlaveAdress, 1);
    //    UARTprintf("4 ");
        //
        // Tell the master to read data.
        //
        I2CMasterControl(ulI2CBase, I2C_MASTER_CMD_SINGLE_RECEIVE);
    //    UARTprintf("2 ");
        //
        // Wait until master module is done receiving.
        //
        while(I2CMasterBusy(ulI2CBase))
        {
        };
    
        //
        // Check for errors.
        //
        if(I2CMasterErr(ulI2CBase) != I2C_MASTER_ERR_NONE)
        {
    //    	UARTprintf("3 ");
            return 0;
        }
    
        //
        // Read the data from the master.
        //
        ulRegValue = I2CMasterDataGet(ulI2CBase);
        UARTprintf(" read: %d \n\r",ulRegValue);
        //
        // Return the register value.
        //
        return (unsigned int)ulRegValue;
    }
    
    //*****************************************************************************
    //
    //! Writes to the specified I2C slave register.
    //!
    //! \param ulI2CBase is the base for the I2C module.
    //! \param ucSlaveAdress is the 7-bit address of the slave to be addressed.
    //! \param ucReg is the register to write data to.
    //! \param ucValue is the 8-bit data to be written.
    //!
    //! This function initiates a read from the I2C slave device.
    //! The ulI2CBase parameter is the I2C modules master base address.
    //! \e ulI2CBase parameter can be one of the following values:
    //!
    //! - \b I2C0_MASTER_BASE
    //! - \b I2C1_MASTER_BASE
    //! - \b I2C2_MASTER_BASE
    //! - \b I2C3_MASTER_BASE
    //!
    //! \return Register value in an unsigned long format.  Note that 0 will be
    //! returned if there is ever an error, 1 if there was not.
    //
    //*****************************************************************************
    unsigned long
    I2CRegWrite(unsigned long ulI2CBase, unsigned char ucSlaveAdress,
    		 unsigned char ucReg, unsigned char ucValue)
    {
    
    
        // Tell the master module what address it will place on the bus when
        // writing to the slave.
        //
        I2CMasterSlaveAddrSet(ulI2CBase, ucSlaveAdress, 0);
    
        //
        // Place the command to be sent in the data register.
        //
       I2CMasterDataPut(ulI2CBase, ucReg);
    
        //
        // Initiate send of data from the master.
        //
      I2CMasterControl(ulI2CBase, I2C_MASTER_CMD_BURST_SEND_START);
    
        //
        // Wait until master module is done transferring.
        //
        while(I2CMasterBusy(ulI2CBase))
        {
        };
    
        //
        // Check for errors.
        //
        if(I2CMasterErr(ulI2CBase) != I2C_MASTER_ERR_NONE)
        {
            return 0;
        }
    
        //
        // Place the value to be sent in the data register.
        //
        I2CMasterDataPut(ulI2CBase, ucValue);
    
        //
        // Initiate send of data from the master.
        //
        I2CMasterControl(ulI2CBase, I2C_MASTER_CMD_BURST_SEND_CONT);
    
        //
        // Wait until master module is done transferring.
        //
        while(I2CMasterBusy(ulI2CBase))
        {
        };
    
        //
        // Check for errors.
        //
        if(I2CMasterErr(ulI2CBase) != I2C_MASTER_ERR_NONE)
        {
            return 0;
        }
    
        //
        // Initiate send of data from the master.
        //
        I2CMasterControl(ulI2CBase, I2C_MASTER_CMD_BURST_SEND_FINISH);
    
        //
        // Wait until master module is done transferring.
        //
        while(I2CMasterBusy(ulI2CBase))
        {
        };
    
        //
        // Check for errors.
        //
        if(I2CMasterErr(ulI2CBase) != I2C_MASTER_ERR_NONE)
        {
            return 0;
        }
    
        //
        // Return 1 if there is no error.
        //
        return 1;
    }
    

  • Hello Sagar

    Please replace the following

    I2CMasterBusBusy

    With

    I2CMasterBusy

    Regards

    Amit

  • Cesar Cruz said:
    the result is always decimal 229 (this is the Accelerometer's Device Address).

    Believe your returning that data is clearly a good sign.  (usually users report 0x00 or 0xFF as their data harvest)

    Might it be that you're reading an incorrect register - or that one register bit must toggle in the opposite direction for your desired data to properly return?  I'd read/re-read slave spec - sometimes they're not crystal clear.