On a Tiva (Texas Instruments Cortex M4F ARM) TM4C129XNCZAD I have another problem with I2C interface. I have employed both a master on I2C module 4 thru port K and a slave on I2C module 6 thru port B. I have interconnected both I2C modules. Using Texas Instruments driver library the master sends 3 bytes to the slave within "Master Send" mode as a request and then the master switches into "Master Receive" mode and the master receives 3 bytes from the slave. Till now everything looks to be OKay, but there is an issue. After the master receives data from the slave, in spite of the master sets a STOP bit within an I2C MCS register, the master module persists in the "Master Receive" mode and the I2C MCS register polling indicates the I2C bus is busy. Because of that there is impossible to set a new slave address and to enter to new cycle. Has anybody any idea how to fix this issue?
There is my code:
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_i2c.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/i2c.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "inc/tm4c129xnczad.h"
#define SLAVE_ADDRESS 0x2C
#define NUM_I2C_DATA 3
#define RUN 1
#define START 2
#define STOP 4
#define ACK 8
#define QCCMD 0x20
#define BURST 0x40
uint32_t ui32Index;
uint32_t pui32DataRx[NUM_I2C_DATA];
uint32_t pui32DataTx[NUM_I2C_DATA];
int test(void)
{
while(1)
{
for(ui32Index = 0; ui32Index < NUM_I2C_DATA; ui32Index++)
{
pui32DataRx[ui32Index] = 0;
pui32DataTx[ui32Index] = 0;
}
while(I2CMasterBusBusy(I2C4_BASE));
I2CMasterSlaveAddrSet(I2C4_BASE, SLAVE_ADDRESS, false);
/*-------------------------------------------------------------*/
I2CMasterDataPut(I2C4_BASE, '1');
I2CMasterControl(I2C4_BASE, START | RUN); // I2C_MASTER_CMD_BURST_SEND_START);
while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_RREQ)); // Wait until the slave has received and acknowledged the data.
pui32DataRx[0] = I2CSlaveDataGet(I2C6_BASE); // Read the data from the slave.
while(I2CMasterBusy(I2C4_BASE));
/*-------------------------------------------------------------*/
I2CMasterDataPut(I2C4_BASE, '2');
I2CMasterControl(I2C4_BASE, RUN); // I2C_MASTER_CMD_BURST_SEND_CONT);
while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_RREQ));
pui32DataRx[1] = I2CSlaveDataGet(I2C6_BASE);
while(I2CMasterBusy(I2C4_BASE));
/*-------------------------------------------------------------*/
I2CMasterDataPut(I2C4_BASE, '3');
I2CMasterControl(I2C4_BASE, STOP | RUN); //I2C_MASTER_CMD_BURST_SEND_FINISH);
while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_RREQ));
pui32DataRx[2] = I2CSlaveDataGet(I2C6_BASE);
while(I2CMasterBusy(I2C4_BASE));
/*-------------------------------------------------------------*/
I2CMasterSlaveAddrSet(I2C4_BASE, SLAVE_ADDRESS, true);
/*-------------------------------------------------------------*/
I2CMasterControl(I2C4_BASE, RUN | START | ACK); // I2C_MASTER_CMD_BURST_RECEIVE_START);
while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_TREQ));
I2CSlaveDataPut(I2C6_BASE, 'A');
while(I2CMasterBusy(I2C4_BASE));
pui32DataTx[0] = I2CMasterDataGet(I2C4_BASE);
/*-------------------------------------------------------------*/
I2CSlaveDataPut(I2C6_BASE, 'B');
I2CMasterControl(I2C4_BASE, RUN | ACK);//I2C_MASTER_CMD_BURST_RECEIVE_CONT);
while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_TREQ));
while(I2CMasterBusy(I2C4_BASE));
pui32DataTx[1] = I2CMasterDataGet(I2C4_BASE);
/*-------------------------------------------------------------*/
I2CSlaveDataPut(I2C6_BASE, 'C');
I2CMasterControl(I2C4_BASE, RUN | ACK); // I2C_MASTER_CMD_BURST_RECEIVE_CONT);
// Missing an ACK causing I2CSlaveStatus stays clear.
while(!(I2CSlaveStatus(I2C6_BASE) & I2C_SLAVE_ACT_TREQ));
while(I2CMasterBusy(I2C4_BASE));
pui32DataTx[2] = I2CMasterDataGet(I2C4_BASE);
/*
When the I2C module operates in Master receiver mode, the ACK bit is normally
set, causing the I2C bus controller to transmit an acknowledge automatically after each byte. This
bit must be cleared when the I2C bus controller requires no further data to be transmitted from the
slave transmitter.
b. In Master Receive mode, a STOP condition should be generated only after a Data Negative Acknowledge executed by
the master or an Address Negative Acknowledge executed by the slave.
*/
I2CMasterControl(I2C4_BASE, STOP); // I2C_MASTER_CMD_BURST_SEND_STOP);
while(I2CMasterBusy(I2C4_BASE));
}
}