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: failed to initialize I2C (EK-TM4C 123GXL)

Tool/software: Code Composer Studio

Hello,

i am working with the TIVA EK-TM4C 123GXL Launch pad and want to connect some sensors via I2C.
But I don't unterstand why it doens't work.

Below the Code for I2C.

/*
 * main.c
 */
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_ints.h"
//#include "inc/hw_i2c.h"           // not used?
//#include "inc/hw_sysctl.h"        // not used?
//#include "inc/hw_types.h"         // not used?
#include "driverlib/gpio.h"
//#include "driverlib/interrupt.h"    // not used?
#include "driverlib/sysctl.h"
#include "driverlib/pwm.h"
#include "driverlib/pin_map.h"
#include "driverlib/uart.h"
#include "driverlib/i2c.h"
#include "utils/uartstdio.h"
#include "elmarlib/common.h"
#include "elmarlib/eeprom.h"
#include "elmarlib/misc.h"
#include "elmarlib/tof.h"
#include "elmarlib/lcd.h"
#include "sensorlib/hw_mpu9150.h"

void main(void) {
    uint32_t slave_addr = 0x69;
/*Port Init */
    // set 16 MHz crystal as main oscillator, use 400 MHZ PLL divided by 12.5 = 16 MHz system clock
    SysCtlClockSet(SYSCTL_SYSDIV_12_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);

    // let all external components some time to boot up
    SysCtlDelay(sleep_1ms * 20);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);                        // enable the GPIO port that is used for the I2C-Bus
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA)){}
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);                         // enable the I2C peripheral for MPU sensor on PD0 = SCL, PD1 = SDA
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C1)){}

    GPIOPinConfigure(GPIO_PA6_I2C1SCL);                                 // configure the pin muxing for I2C3 functions
    GPIOPinConfigure(GPIO_PA7_I2C1SDA);a
    GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);                     // select the I2C function for these pins.
    GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);
               // check if the peripheral access is enabled
                  // wait for the I2C module to be ready
    I2CMasterInitExpClk(SYSCTL_PERIPH_I2C1, SysCtlClockGet(), false);  //initialize master and slave
                                                                   // fast mode would be possible

    I2CMasterSlaveAddrSet(I2C1_BASE, slave_addr, false);               //reg = I2CMDR;
                                                                  //read specified register on slave device
                                                                       //specify that we are writing (a register address) to the
                                                                       //slave device
/*I2C Init */
    //uint8_t Test = 1;

    I2CMasterDataPut(slave_addr, 0x75);                                //specify register to be read
                                                       //Annahme: reg=i2cmdr, HWREG(ui32Base + I2C_O_MDR) = ui8Data;

    I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_SINGLE_SEND);           //send control byte and register address byte to slave device

    while(I2CMasterBusy(I2C1_BASE));                                   //wait for MCU to finish transaction
                                                                       // Returns true if the I2C bus is busy; otherwise, returns false.

    I2CMasterErr(I2C1_BASE);                                           //Returns the error status, as one of I2C_MASTER_ERR_NONE,
                                                                       //I2C_MASTER_ERR_ADDR_ACK, I2C_MASTER_ERR_DATA_ACK, or
                                                                       //I2C_MASTER_ERR_ARB_LOST.


    //I2CMasterSlaveAddrSet(I2C3_BASE, slave_addr, true);              //specify that we are going to read from slave device

    //I2CMasterControl(I2C3_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);      //send control byte and read from the register we specified

    //while(I2CMasterBusy(I2C3_BASE));                                 //wait for MCU to finish transaction

    I2CMasterDataGet(I2C1_BASE);                                       //return data pulled from the specified register
                                                                       //evtl so schreiben: return I2CMasterDataGet(I2C3_BASE);


    }


Thanks and best regards.

Thomas

  • I did not see anything obvious in the software. Have you checked your hardware? Do you have the pull-up resistors on SCL and SDA? What slave are you talking to? Is 0x69 the correct address? Do you see proper I2C signals when you look at SDA and SCL with a scope? Do you get an acknowledge from the slave.
  • Now it works. Seems like there was more than one error.
    Besides using "analog" pullup-resistors, i changed the code a bit.
    -->Getting the right signals with scope as with logic analizer.
    /*
    * main.c
    */
    #include <stdint.h>
    #include <stdbool.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_gpio.h"
    #include "inc/hw_ints.h"
    //#include "inc/hw_i2c.h" // not used?
    //#include "inc/hw_sysctl.h" // not used?
    //#include "inc/hw_types.h" // not used?
    #include "driverlib/gpio.h"
    //#include "driverlib/interrupt.h" // not used?
    #include "driverlib/sysctl.h"
    #include "driverlib/pwm.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/uart.h"
    #include "driverlib/i2c.h"
    #include "utils/uartstdio.h"
    #include "elmarlib/common.h"
    #include "elmarlib/eeprom.h"
    #include "elmarlib/misc.h"
    #include "elmarlib/tof.h"
    #include "elmarlib/lcd.h"
    #include "sensorlib/hw_mpu9150.h"


    uint32_t I2CReceive(uint32_t slave_addr, uint8_t reg)
    {
    I2CMasterSlaveAddrSet(I2C2_BASE, slave_addr, false); //reg = I2CMDR;
    //read specified register on slave device
    //specify that we are writing (a register address) to the
    //slave device


    I2CMasterDataPut(slave_addr, reg); //specify register to be read
    //Annahme: reg=i2cmdr, HWREG(ui32Base + I2C_O_MDR) = ui8Data;

    I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_SEND_START); //send control byte and register address byte to slave device

    while(I2CMasterBusy(I2C2_BASE)); //wait for MCU to finish transaction
    I2CMasterErr(I2C2_BASE); //Returns the error status, as one of I2C_MASTER_ERR_NONE,
    //I2C_MASTER_ERR_ADDR_ACK, I2C_MASTER_ERR_DATA_ACK, or
    //I2C_MASTER_ERR_ARB_LOST.


    I2CMasterSlaveAddrSet(I2C2_BASE, slave_addr, true); //specify that we are going to read from slave device

    I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE); //send control byte and read from the register we specified
    while(I2CMasterBusy(I2C2_BASE)); //wait for MCU to finish transaction

    return I2CMasterDataGet(I2C2_BASE); // Returns true if the I2C bus is busy; otherwise, returns false.
    }

    //uint8_t ReadAccel(uint8_t reg)
    //{
    //uint8_t accelData = I2CReceive(ACCEL_SLAVE_ADDR, reg);

    //return accelData;
    //}

    void main(void) {
    uint32_t slave_addr = 0x69;
    uint32_t data_unser;
    /*Port Init */
    // set 16 MHz crystal as main oscillator, use 400 MHZ PLL divided by 12.5 = 16 MHz system clock
    SysCtlClockSet(SYSCTL_SYSDIV_12_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);

    //SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
    //SYSCTL_XTAL_16MHZ);
    // let all external components some time to boot up
    //SysCtlDelay(sleep_1ms * 20);


    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C2); // enable the I2C peripheral for MPU sensor on PD0 = SCL, PD1 = SDA
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C2)){}
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); // enable the GPIO port that is used for the I2C-Bus
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOE)){}

    GPIOPinConfigure(GPIO_PE4_I2C2SCL); // configure the pin muxing for I2C3 functions
    GPIOPinConfigure(GPIO_PE5_I2C2SDA);
    GPIOPinTypeI2CSCL(GPIO_PORTE_BASE, GPIO_PIN_4); // select the I2C function for these pins.
    GPIOPinTypeI2C(GPIO_PORTE_BASE, GPIO_PIN_5);
    // check if the peripheral access is enabled
    // wait for the I2C module to be ready
    I2CMasterInitExpClk(I2C2_BASE, SysCtlClockGet(), false); //initialize master and slave
    // fast mode would be possible
    while (1){
    I2CReceive(slave_addr, 0x75);
    data_unser = I2CReceive(slave_addr, 0x75);
    }


    }

    Thanks for the help
    Thomas
  • Thomas Metzger85 said:
    Now it works.

    it is noted that you've "switched from" I2C1 to I2C2 - a "proper" fix is more satisfying if it succeeds across (all) candidate Ports.    Might you detail your switch to another I2C channel?

    I2C1 - if memory serves - "defaults" into I2C mode - which usually aids user success.     Both your posting - and recent contact from one of our clients - note "difficulty" w/I2C1 - which proves curious.

    You wrote of "analog" pull-up resistors - did you mean "external resistors" - or an independent current source (used in that role).     The pull-down capacity of both your MCU & I2C Slaves are limited - perhaps I2C1 became damaged - necessitating your "switch to another I2C channel..."

    Glad that you are, "up/running."