Other Parts Discussed in Thread: EK-TM4C123GXL
Tool/software: Code Composer Studio
Hello everyone, I'm trying to program I2C between 2 TM4C123GH6PM, I used module I2C0 and 1K pull-up resistors. The idea is UART received data, then trigger the I2C Master send character 'R' to I2C Slave, the Slave after receive and detect 'R' will send back data for Master . The data has been transferred correctly. But there are 2 problems I cannot figure it out by myself.
- When Master send data to Slave, there is a character 'y' (121) go after. I wonder whether it's the frame ACK or not because the data receive is correct and ACK's value in ASCII is different.
- I can only read data once. After that, the Master's program is stuck in while(!I2CMasterBusy()). I don't know how to change it.
Master:
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/i2c.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#define SLAVE_ADDRESS 0x3C
unsigned char B[10];
unsigned char data[21];
unsigned char *ptr;
unsigned char a,b,c,d;
uint8_t i = 0;
uint8_t j = 0;
float x;
static void I2C0MasterIntHandler(void)
{
// Clear the I2C0 interrupt flag.
I2CMasterIntClear(I2C0_BASE);
// Read the data from the slave.
data[j] = I2CMasterDataGet(I2C0_BASE);
I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, true);
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
j++;
if(j > 21)
{
j = 0;
}
}
static void UARTISR(void)
{
UARTIntClear(UART0_BASE,UARTIntStatus(UART0_BASE,true));
while (UARTCharsAvail(UART0_BASE))
{
B[i]=UARTCharGetNonBlocking(UART0_BASE);
i++;
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_PIN_1);
SysCtlDelay(1000000);
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0);
SysCtlDelay(1000000);
};
i = 0;
if(B[i] == 'R')
{
I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, false);
I2CMasterDataPut(I2C0_BASE, B[i]);
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
while(I2CMasterBusy(I2C0_BASE));
I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, true);
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
// while(I2CMasterBusBusy(I2C0_BASE)); // check MasterBusBusy vs MasterBusy
}
}
int main(void)
{
x = 11.7;
ptr = (unsigned char *)&x;
a = *ptr;
b = *(ptr + 1);
c = *(ptr + 2);
d = *(ptr + 3);
//System clock set
SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
//Enable UART and GPIO peripherals
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);
//Enable the appropriate GPIO port for the UART0 or UART1 Tx and Rx pins
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); //Configure the UART0 or UART1 GPIO pins for UART operation
//Set the pins to be peripheral controlled
UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 9600,(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_EVEN));
UARTIntEnable(UART0_BASE, UART_INT_RX|UART_INT_RT);
UARTEnable(UART0_BASE);
UARTIntRegister(UART0_BASE,&UARTISR);
//enable GPIO peripheral that contains I2C 0
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB));
//enable I2C module 0
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
//reset module
SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0);
// Configure the pin muxing for I2C0 functions on port B2 and B3.
GPIOPinConfigure(GPIO_PB2_I2C0SCL);
GPIOPinConfigure(GPIO_PB3_I2C0SDA);
// Select the I2C function for these pins.
GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
// Enable and initialize 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.
I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet(), false);
I2CMasterIntEnableEx(I2C0_BASE, I2C_MASTER_INT_DATA);
I2CIntRegister(I2C0_BASE, &I2C0MasterIntHandler);
while(1)
{
}
}
Slave:
#include <stdint.h>
#include <stdbool.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"
#define SLAVE_ADDRESS 0x3C
unsigned char result = 'V';
volatile unsigned char data[21];
void I2C0_Slave_Init(void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
SysCtlPeripheralReset(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);
I2CSlaveEnable(I2C0_BASE);
I2CSlaveInit(I2C0_BASE, SLAVE_ADDRESS);
}
void I2C0SlaveIntHandler(void)
{
uint8_t i;
// Clear the I2C0 interrupt flag.
I2CSlaveIntClear(I2C0_BASE);
// Read the data from the slave.
result = I2CSlaveDataGet(I2C0_BASE);
if(result == 'R')
{
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0x02);
SysCtlDelay(SysCtlClockGet()/50);
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0);
SysCtlDelay(SysCtlClockGet()/50);
for(i = 0; i < 21; i++)
{
I2CSlaveDataPut(I2C0_BASE, data[i]);
SysCtlDelay(1200);
}
}
}
int main(void)
{
data[0] = 'a';
uint8_t i;
for(i = 0; i < 21; i++)
{
data[i] = data[0] + i;
}
SysCtlClockSet(SYSCTL_SYSDIV_1| SYSCTL_USE_OSC| SYSCTL_OSC_MAIN| SYSCTL_XTAL_16MHZ);
I2C0_Slave_Init();
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
I2CSlaveIntEnableEx(I2C0_BASE, I2C_SLAVE_INT_DATA);
I2CIntRegister(I2C0_BASE,&I2C0SlaveIntHandler);
while(1)
{
}
}
Thank you.