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);
}
}