【发布时间】:2014-07-17 12:41:39
【问题描述】:
在 Tiva(Texas Instruments Cortex M4F ARM)TM4C129XNCZAD 上,I2C 接口有另一个问题。我在 I2C 模块 4 到端口 K 上使用了一个主机,在 I2C 模块 6 到端口 B 上使用了一个从机。我已经互连了两个 I2C 模块。使用德州仪器驱动程序库,主机在“主机发送”模式下向从机发送 3 个字节作为请求,然后主机切换到“主机接收”模式,主机从从机接收 3 个字节。到目前为止,一切看起来都很好,但是有一个问题。主机从从机接收数据后,尽管主机在 I2C MCS 寄存器中设置了一个 STOP 位,但主机模块仍保持在“主机接收”模式,并且 I2C MCS 寄存器轮询指示 I2C 总线繁忙。因此,无法设置新的从机地址并进入新的周期。有人知道如何解决这个问题吗?
这是我的代码:
#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));
}
}
【问题讨论】: