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/TM4C123GH6PM: how to interfacing I2C of GY-80 with TM4C123GH6PM with ccs v7

Part Number: TM4C123GH6PM

Tool/software: Code Composer Studio

Hi everybody, it is first time to write a post here.

Recently I've working on reading GY-80 accel data through Tivaware.

here are my Questions.

Q1. Is it okay if I write ctrl register through following process?

     I2CMasterDataPut(I2C0_BASE,0x2D); // power control register for ADX345
     I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
     I2CMasterDataPut(I2C0_BASE,0x08); // write ctrl reg as measurement mode
     I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
Q2. please take a look for my code below.
I can only see "0 0 0\n 0 0 0\n 0 0 0 ..." or "255 255 255\n 255 255 255\n 255 255 255 ..." on serial monitor.
/*
 * main.c
 */
/*---------------------------------------------
  GPIO_Pin     Pin_Function     Device
    PF4            GPIO          SW1
    PF0            GPIO          SW2
    PF1            GPIO      RGB LED(Red)
    PF2            GPIO      RGB LED(Blue)
    PF3            GPIO      RGB LED(Green)
    PC4            PWM         SERVO0
    PC5            PWM         SERVO1
    PB7            PWM         SERVO2
    PD0            DOUT
    PD1            DOUT
    PD2            DOUT
    PE1            DIN
    PE2            DIN
    PE3            DIN
    PB2            I2C           SCL
    PB3            I2C           SDA
 -----------------------------------------------*/

//--------------include header------------------//
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "inc/hw_gpio.h"
#include "inc/hw_types.h"
#include "inc/hw_i2c.h"
#include "driverlib/pin_map.h"

#include "driverlib/gpio.h"
#include "driverlib/pwm.h"
#include "driverlib/i2c.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"

#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/rom.h"
//----------------------------------------------//


//--------------define macro--------------------//
#define SERVO0 0  //PC4
#define SERVO1 1  //PC5
#define SERVO2 2  //PB7
#define PD0 0
#define PD1 1
#define PD2 2
#define PE1 3
#define PE2 4
#define PE3 5
#define HIGH 0x01
#define LOW  0x0
#define ACCEL_SLAVE_ADDR 0x53
#define ACCEL_X_DATA 0x32
#define ACCEL_Y_DATA 0x34
#define ACCEL_Z_DATA 0x36
#define NUM_I2C_DATA 3
//----------------------------------------------//


//---------- TivaWare driver initialize function--------------//
void sys_init();
void clk_set();
void gpio_init();
void pwm_init();
void i2c_init();
//------------------------------------------------------------//


//------------User Interface Function-------------------------//
void Servo_write(int SERVO_N, int DUTY_CYCLE);
void digitalWrite(int PIN_N, int STATE);
int32_t digitalRead(int PIN_N);
int8_t ReadAccel(uint8_t reg);
uint32_t I2CRead(uint32_t slave_addr, uint8_t reg);
void ConfigureUART(void);

//------------------------------------------------------------//

#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

int main(void) {

    sys_init();
    ConfigureUART();
    uint8_t Ax, Ay, Az=32;
    //int32_t temp=0;
    UARTprintf("Start I2C Communication!\n");

    while (1)
    {
        Ax = ReadAccel(ACCEL_X_DATA);
        Ay = ReadAccel(ACCEL_Y_DATA);
        Az = ReadAccel(ACCEL_Z_DATA);
        UARTprintf("%d %d %d\n", Ax, Ay, Az);

    };
      
    //return 0;
}

void sys_init()
{
    clk_set();
    gpio_init();
    pwm_init();
    i2c_init();
}

void clk_set()
{
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
}

void gpio_init()
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD));
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOE));

    GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2);
    GPIOPinTypeGPIOInput(GPIO_PORTE_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
}

void pwm_init()
{
    //Configure PWM Clock to match system
    SysCtlPWMClockSet(SYSCTL_PWMDIV_64);

    //Enable the PWM0 peripheral
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);

    //Wait for the PWM0 module to be ready.
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_PWM0));

    //HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    //HWREG(GPIO_PORTF_BASE + GPIO_O_CR) |= 0x01;

    GPIOPinConfigure(GPIO_PB7_M0PWM1);
    GPIOPinConfigure(GPIO_PC4_M0PWM6);
    GPIOPinConfigure(GPIO_PC5_M0PWM7);
    GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_7);
    GPIOPinTypePWM(GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5);
    //GPIOPinTypePWM(GPIO_PORTC_BASE, GPIO_PIN_5);
    //Configure the PWM generator for count down mode with immediate
    //updates to the parameters.
    PWMGenConfigure(PWM0_BASE, PWM_GEN_0, PWM_GEN_MODE_DOWN|PWM_GEN_MODE_NO_SYNC);
    PWMGenConfigure(PWM0_BASE, PWM_GEN_3, PWM_GEN_MODE_DOWN|PWM_GEN_MODE_NO_SYNC);

    //These settings are specifically designed to run servo motors
    //which expect 20mS period with between 1ms and 2ms high time

    //System clock is 16MHz with PWM divider of 64
    // 16000000/64 = 250000/50 = 5000  ### 1S/50 = 20mS thats where divisor comes from

    // Set high time to 2mS
    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, 5000);
    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_3, 5000);

    // Set the pulse width of PWM1 for a 10% duty cycle.
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, 500); //PB7 M0PWM1

    // Set the pulse width of PWM6 for a 10% duty cycle.
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_6, 500); //PC4 M0PWM6

    // Set the pulse width of PWM7 for a 20% duty cycle.
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_7, 1000); //PC5 M0PWM7

    // Start the timers in generator 3.
    PWMGenEnable(PWM0_BASE, PWM_GEN_0);
    PWMGenEnable(PWM0_BASE, PWM_GEN_3);

    // Enable the outputs.
    PWMOutputState(PWM0_BASE, (PWM_OUT_1_BIT | PWM_OUT_6_BIT | PWM_OUT_7_BIT), true);

    //DataSheet
    //Table 20-1. PWM Signals (64LQFP) --> pwm module , generator , pin number
}

void i2c_init()
{

     // Enable the I2C0 peripheral
     SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);

     // Wait for the I2C0 module to be ready.
     while(!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C0));

     //reset module
     SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0);
     //GPIO port B needs to be enabled so these pins can be used.
     SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

     // Configure the pin muxing for I2C0 functions on port B2 and B3.
     GPIOPinConfigure(GPIO_PB2_I2C0SCL);
     GPIOPinConfigure(GPIO_PB3_I2C0SDA);

     // Configures pin for use as SDA by the I2C peripheral.GPIO_PB3_I2C0SDA
     GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
     // Configures pin for use as SCL by the I2C peripheral.GPIO_PB2_I2C0SCL
     GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);

     //  Don't know HOW TO USE --JW
     I2CMasterEnable(I2C0_BASE);

     // Initialize Master and Slave
     // it will sets the bus speed and enables the master module.
     I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet(), true);

     //I2CSlaveEnable(I2C0_BASE);
     //I2CSlaveInit(I2C0_BASE, ACCEL_SLAVE_ADDR);

     // Specify slave address
     // first data, define master send or recive
     // true -> master is initiating a read from the slave
     // false -> the addr indicates that the I2C master is initiating a write to slave.
     I2CMasterSlaveAddrSet(I2C0_BASE, ACCEL_SLAVE_ADDR, false); //0x3B

     // set power register as measurement mode
     I2CMasterDataPut(I2C0_BASE,0x2D);
     I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
     I2CMasterDataPut(I2C0_BASE,0x08);
     I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);

     // set data format register as full resolution
     I2CMasterDataPut(I2C0_BASE,0x31);
     I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
     I2CMasterDataPut(I2C0_BASE,0x08);
     I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);



     // clear I2C FIFO
     //HWREG(I2C0_BASE + I2C_O_FIFOCTL) = 80008000;

}

void ConfigureUART(void)
{

    // Enable the GPIO Peripheral used by the UART.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);


    // Enable UART0
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);


    // Configure GPIO Pins for UART mode.
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

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

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

void Servo_write(int SERVO_N, int DUTY_CYCLE)
{
    //0~180 --> duty cycle : 3%~12% (in arduino)
    DUTY_CYCLE = 150+(DUTY_CYCLE*2.5); //convert integer to degree

    switch (SERVO_N)
    {
        case 0: //PC4
            PWMPulseWidthSet(PWM0_BASE, PWM_OUT_6, DUTY_CYCLE); //PC4 M0PWM6
            break;
        case 1: //PC5
            PWMPulseWidthSet(PWM0_BASE, PWM_OUT_7, DUTY_CYCLE); //PC5 M0PWM6
            break;
        case 2: //PB7
            PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, DUTY_CYCLE); //PB7 M0PWM1
            break;
        default:
            break;
    }
}

void digitalWrite(int PIN_N, int STATE) //테스트 필요
{
    switch (PIN_N)
    {
        case 0:
            if(STATE == LOW)
                GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 0x0);
            else
                GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, GPIO_PIN_0);
            break;
        case 1:
            if(STATE == LOW)
                GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_1, 0x0);
            else
                GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_1, GPIO_PIN_1);
            break;
        case 2:
            if(STATE == LOW)
                GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_2, 0x0);
            else
                GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_2, GPIO_PIN_2);
            break;
        default:
            break;
    }
}

int32_t digitalRead(int PIN_N)
{
    switch (PIN_N)
    {
        case 3: //PE1
            return GPIOPinRead(GPIO_PORTE_BASE,GPIO_PIN_1);
        case 4:
            return GPIOPinRead(GPIO_PORTE_BASE,GPIO_PIN_2);
        case 5:
            return GPIOPinRead(GPIO_PORTE_BASE,GPIO_PIN_3);
        default:
            return 0;
    }
}

int8_t ReadAccel(uint8_t reg) //reading accel data 
{
    uint8_t accelData = I2CRead(ACCEL_SLAVE_ADDR, reg);

    return accelData;
}

uint32_t I2CRead(uint32_t slave_addr, uint8_t reg) // for test. receiving sensor data
{

    I2CMasterSlaveAddrSet(I2C0_BASE, slave_addr, false);

    //specify register to be read
    I2CMasterDataPut(I2C0_BASE, reg);

    //send ctrl byte and reg addr byte to slave device
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);

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

    I2CMasterSlaveAddrSet(I2C0_BASE, slave_addr, true);

    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);

    //wait
    while(I2CMasterBusy(I2C0_BASE));

    //data return
    return I2CMasterDataGet(I2C0_BASE);

}

For  I2CRead user function, I've also tried this before.
/* Trial 1

   //I2CMasterSlaveAddrSet(I2C0_BASE, slave_addr, false);

    //I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE);

    //wait
    //while(I2CMasterBusy(I2C0_BASE));

    I2CMasterSlaveAddrSet(I2C0_BASE, slave_addr, true);

    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);

    //wait
    //while(I2CMasterBusy(I2C0_BASE));

    //data return
    return I2CMasterDataGet(I2C0_BASE);
*/





/*  Trial 2
 *
 *
    //0926
    uint32_t pui32DataTx[NUM_I2C_DATA];
    uint32_t pui32DataRx[NUM_I2C_DATA];
    uint32_t ui32Index;

    I2CMasterSlaveAddrSet(I2C0_BASE, slave_addr, true);
    //I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
    //while(!(I2CSlaveStatus(I2C0_BASE) & I2C_SLAVE_ACT_TREQ))
    //   {
    //   }
    // Initalize the receive buffer.
    //
    for(ui32Index = 0; ui32Index < NUM_I2C_DATA; ui32Index++)
    {
        pui32DataRx[ui32Index] = 0;
    }+

    I2CSlaveDataPut(I2C0_BASE, pui32DataTx[ui32Index]);
//    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
//    while(!(I2CSlaveStatus(I2C0_BASE) & I2C_SLAVE_ACT_TREQ))
//    {
//    }
    pui32DataRx[ui32Index] = I2CMasterDataGet(I2C0_BASE);

    return pui32DataRx[ui32Index];

    // Reset receive buffer.
    //for(ui32Index = 0; ui32Index < NUM_I2C_DATA; ui32Index++)
    //{
    //   pui32DataRx[ui32Index] = 0;
    //}

 *
 *
 */

  • Hi Ryu,
    Please confirm if you have proper pullup resistors on the SCL and SDA bus. Please also refer to the I2C app note at www.ti.com/.../spma073.pdf which includes some I2C examples for you to reference.
  • Greetings - you are to be congratulated for:

    • Creating a clear & communicating "Subject Line" - which "draws readers" to your post.   (unlike the mindless: "TM4cxyx: TM4cxyz" - a byproduct of the recent forum downgrade)
    • Presenting your code in the preferred, "Syntax Highlighter" manner

    Most always it is advised that, "Mastery of a "new to you" MCU's Peripheral is best achieved via "KISS" (use of the simplest, specific (most focused), and monitored technique!)     The "complexity" of the external, I2C device you've chosen - is a clear violation of KISS!    (your external device is far too complex to be used as a "starting point" - most always will "over-whelm you w/issues" - your arrival here thus, "IS as expected!"

    Mastery of I2C is (instead), "Speeded, Eased, Enhanced" by your use of a small capacity, I2C based EEProm!     Such small EEProm is inexpensive - and is "Sure to see use" in your present - and likely in most all of your future projects - as well.    Due to its "lack of (unwanted) complexity" - your understanding will grow quickly - your "struggles" greatly reduced!     That's ideal - is it not?

    In contrast - "Where can you (even) begin to analyze your plight (failure) right now?"     Note too that skilled vendor agent "Charles" confines (his) diagnosis to "external pull-up resistors" - he too knows, "Not where to begin!"    (as your violation of KISS presents, "Too many unknowns" to enable a logical, systematic diagnosis to be formed!)

    Vendor's (so strange/mistaken) refusal to, "Promote KISS" is directly responsible for, "So many - just like you" - arriving here on a daily basis - with (needless) "unsolvable problems" - brought on by lack of (proper) poster guidance!     (i.e. "KISS" - practiced @ MIT, Cal Tech, UW-Madison, UA-Huntsville (last 2 NASA cert. schools) - yet (apparently) "banned here" - w/out explanation...)

  • First of all, Thankx for reply.

    However, I'm afraid that I already tried pullup resistors before.

    Is there any code error?

    thank you again, Ryu
  • Hi Ryu,
    When you said you tried pullup resistors before, do you still have the resistors "now" or you had removed them? You must have the pullup resistor. Please add the below line after the I2CMasterControl() like below. Also you are running at 400kps. I will suggest you start with lower speed like 100kps. Once everything works, you can increase your I2C speed. Use the scope to see the bus activities. Are you getting the expected ACK from the external slave device?

    I2CMasterDataPut(I2C0_BASE,0x2D); // power control register for ADX345
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
    while( I2CMasterBusy(I2C0_BASE));
    I2CMasterDataPut(I2C0_BASE,0x08); // write ctrl reg as measurement mode
    I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
    while( I2CMasterBusy(I2C0_BASE));
  • May we note the following:

    • poster's code consumes 371 & 62 lines
    • unstated is the "experience level" w/I2C
    • when one must be advised to "Probe w/a scope" - does that insure that "prober" will understand (and exploit) captured results?
    • targeted device is sufficiently sophisticated to DEMAND the more complex, "Start & Re-Start I2C Sequence"

    There has been ONLY ONE suggestion to, "Simplify - to Start w/a far more basic device - so that "understanding builds in an eased, more comfortable & controllable manner!"

    Advanced college courses - most always - demand satisfactory completion of "Pre-Requisite" courses - prior to, "Entry to the more challenging!"   That's been "kicked to the curb here" - how is that justified - and (how) does it "best serve" this poster?

  • Dear Charles,

    Yes, I meant I already set pullup resistors. as your advice, I tried to set 100kps, and have 4.7k Ohm resistors each.

    Q1....But I'm not sure that I set the speed. How can I do that?

    I set 100kbps by

    I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet(), flase);



    and I revised my code as you advised to me.

    However, I couldn't success I2CMasterDataPut API function.

    If you have some time, plz take a look for my upper reply.


    Thank you soooo much,

    I really had hard time in my country study alone.

    I don't know how to thank you.



    Ryu

    *Attached* 

    I debugged with many breakpoints,

    I found that I2CMasterDataPut API function didn't show any pulse.

    Only I can see is I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND); line pulse.

    details are upper reply. Thank you