在Tiva(德州仪器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));
}
}
答案 0 :(得分:0)
@MarcoPolo
我查看你的代码,我很难跟上这个流程。但是我能够在TIVA Launchpad TM4C123GH6PM上运行I2C。我使用了Tivaware库。我创建了3个函数,init,read和write。这是功能。
初始化
void initI2C0(void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
//reset I2C module
SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0);
//enable GPIO peripheral that contains I2C
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
// 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);
//clear I2C FIFOs
HWREG(I2C0_BASE + I2C_O_FIFOCTL) = 80008000;
}
I2C读取功能
uint8_t readI2C0(uint16_t device_address, uint16_t device_register)
{
//specify that we want to communicate to device address with an intended write to bus
I2CMasterSlaveAddrSet(I2C0_BASE, device_address, false);
//the register to be read
I2CMasterDataPut(I2C0_BASE, device_register);
//send control byte and register address byte to slave device
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
//wait for MCU to complete send transaction
while(I2CMasterBusy(I2C0_BASE));
//read from the specified slave device
I2CMasterSlaveAddrSet(I2C0_BASE, device_address, true);
//send control byte and read from the register from the MCU
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
//wait while checking for MCU to complete the transaction
while(I2CMasterBusy(I2C0_BASE));
//Get the data from the MCU register and return to caller
return( I2CMasterDataGet(I2C0_BASE));
}
I2C写入功能
void writeI2C0(uint16_t device_address, uint16_t device_register, uint8_t device_data)
{
//specify that we want to communicate to device address with an intended write to bus
I2CMasterSlaveAddrSet(I2C0_BASE, device_address, false);
//register to be read
I2CMasterDataPut(I2C0_BASE, device_register);
//send control byte and register address byte to slave device
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);
//wait for MCU to finish transaction
while(I2CMasterBusy(I2C0_BASE));
I2CMasterSlaveAddrSet(I2C0_BASE, device_address, true);
//specify data to be written to the above mentioned device_register
I2CMasterDataPut(I2C0_BASE, device_data);
//wait while checking for MCU to complete the transaction
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
//wait for MCU & device to complete transaction
while(I2CMasterBusy(I2C0_BASE));
}
我将在线发布完整的代码,以帮助理解该应用程序。
更新: 可以找到TIVA + I2C的完整代码here。
<强>参考强>
答案 1 :(得分:0)
仅供参考... I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDR, false);
是你要写的时候,I2CMasterSlaveAddrSet(I2C2_BASE, SLAVE_ADDR, true);
是你想要从I2C总线上读的时候。