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.

TM4C123GH6PM: [Tiva C Launchpad] I2C master can't read data sent from slave, stucks in I2CMasterBusy() function

Part Number: TM4C123GH6PM

Hello all,

I am doing some basic I2C transactions between 2 Tiva-C launchpad kits(TM4C123GH6PM). One Tiva launchpad is master, the one is slave. They connect to each other using I2C0 module with 4.7k pull up resister connect to 3.3V from the launchpad.

I can send data from Master to slave and slave can receive it. But when I send the received data back to master, the master can not read it. The Master software get into wihle(I2CMasterBusy()) so it can not do the command I2CMasterDataGet().  

I read some post (e2e.ti.com/.../378268) which have the same issue with me and Amit Ashara suggests to

replace wihle(I2CMasterBusy()) with 

while (!(I2CMasterBusy(I2C0_BASE))); //Wait till end of transaction
// SysCtlDelay(100);

while (I2CMasterBusy(I2C0_BASE)); //Wait till end of transaction.

But it not work for me :(.

Here is my code for Tiva-Master which stuck in while loop:

#include <stdint.h>
#include <stdbool.h>
#include "inc/tm4c123gh6pm.h"
#include "inc/hw_ints.h"
#include "inc/hw_i2c.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"

#include "driverlib/interrupt.h"
#include "driverlib/i2c.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
#include "utils/uartstdio.c"

#define SLAVE_ADDRESS 0x3C
volatile uint32_t read;
volatile uint32_t receive;

void InitConsole(void)
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    UARTStdioConfig(0, 115200, 16000000);
}

void I2C0_Master_Init(void)
{
//    Enable GPIO Pin for I2C0
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB));
//    Reset and enable I2C module
    SysCtlPeripheralDisable(SYSCTL_PERIPH_I2C0);
    SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);

//    Config pin muxing for I2C
    GPIOPinConfigure(GPIO_PB2_I2C0SCL);
    GPIOPinConfigure(GPIO_PB3_I2C0SDA);
//    Select I2C function for these pin
    GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
    GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);

//    Enable and initialize the I2C master module
//    flase: set clock 400kHz
    I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet() , false);

}

int main()
{
    uint32_t ui32DataTx;

    SysCtlClockSet(SYSCTL_SYSDIV_1| SYSCTL_USE_OSC| SYSCTL_OSC_MAIN| SYSCTL_XTAL_16MHZ);
    InitConsole();
    I2C0_Master_Init();
//    Enale I2C Master block
    I2CMasterEnable(I2C0_BASE);
// Interrupt config to receives data from slave

    UARTprintf("I2C Master send data Example ->");
    UARTprintf("\n  Module = I2C0");
    UARTprintf("\n  Mode = Receive interrupt on the Slave module");
    UARTprintf("\n  Rate = 100kbps\n\n"); \
    while(1)
    {
/*        prepare SEND data for Master send data to Slave*/

        ui32DataTx = UARTCharGet(UART0_BASE);
        UARTprintf("Transferring from: Master -> Slave\n");
        UARTprintf("  Sending: '%c'\n", ui32DataTx);
//        select SLAVE_ADDRESS to transfer
        I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, false);
//        put data to I2C data register
        I2CMasterDataPut(I2C0_BASE, ui32DataTx);
//        Initiate sned data character
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
//        Delay until transmission completes
        while(I2CMasterBusBusy(I2C0_BASE));

/*        prepare RECEIVE data from salve*/
        UARTprintf("Prepare receives data again\n");
        I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, true);
        I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
        SysCtlDelay(100);
//====>>>>> The code stuck here
while (I2CMasterBusy(I2C0_BASE)); //Wait till end of transaction ui32DataTx = I2CMasterDataGet(I2C0_BASE); UARTprintf("Data receive again: %d\n", ui32DataTx); } }

Here is my slave code, after it recives it will send back to master

#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"
#include "utils/uartstdio.c"

#define SLAVE_ADDRESS 0x3C

//global variable to receive data
static volatile uint32_t g_ui32DataRx;

void InitConsole(void)
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    UARTStdioConfig(0, 115200, 16000000);
}

void I2C0_Init(void)
{
//    Enable GPIO_PORTB
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB));

   SysCtlPeripheralDisable(SYSCTL_PERIPH_I2C0);
   SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0);
   SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);

   GPIOPinConfigure(GPIO_PB2_I2C0SCL);
   GPIOPinConfigure(GPIO_PB3_I2C0SDA);
   GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
   GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);

}

int main(void)
{
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
            SYSCTL_XTAL_16MHZ);
    I2C0_Init();
//    Init slave
    I2CSlaveInit(I2C0_BASE, SLAVE_ADDRESS);
//    enable I2C slave block
    I2CSlaveEnable(I2C0_BASE);
    InitConsole();
    UARTprintf("Slave waiting I2C Data\n");

    uint32_t i2cMasterData;

    while(1)
    {
//        receive data from Master
        while (!(I2CSlaveStatus(I2C0_BASE) & I2C_SLAVE_ACT_RREQ))
        {

        }
        i2cMasterData = I2CSlaveDataGet(I2C0_BASE);
        UARTprintf("Received data from Master: %c\n", i2cMasterData);
//        send data again to Master
        I2CSlaveDataPut(I2C0_BASE, i2cMasterData);
SysCtlDelay(100); UARTprintf("Send data to Master again: %c\n", i2cMasterData); } }