This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] EK-TM4C1294XL:I2C 主从通信问题

Guru**** 2524460 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1242466/ek-tm4c1294xl-i2c-master-and-slave-communication-issues

器件型号:EK-TM4C1294XL

您好!

我无法通过 I2C 将我的两个 LaunchPad 连接在一起。 我正在尝试将3个字节从主器件传递到从器件、然后从器件将它们输出到终端。

我的问题是、从器件在向终端输出任何数据包之前需要发送两个数据包、但是输出是两个数据包的组合。 例如、当我在一个数据包中发送值10、20、30、在另一个数据包中发送值40、50、60时。 从器件将输出20、30、50 (忽略每个数据包的第一个字节)。

以下是用于 I2C 从设备和 ISR 初始化的代码:

#define buffer_size 3 // I2C 接收缓冲区的大小 

#define I2C_SLAVE_BASE I2C0_BASE
#define I2C_SLAVE_GPIO GPIO_PORTB_BASE
#define I2C_SLAVE_SDA GPIO_PIN_3
#define I2C_SLAVE_SCL GPIO_PIN_2

uint8_t i2c_rx_buffer [buffer_size]
volatile uint8_t i2c_rx_buffer_index = 0
Volatile bool i2c_buffer_full = false;

void I2C0_IRQHandler (void)// ISR
void init_i2C() 
{
//启用 I2C0外设
SysCtlPeripheralEnable (SYSCTL_Periph_I2C0)

//启用 GPIOB 外设
SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB)

//将 PB2和 PB3配置为 I2C 引脚
GPIOPinConfigure (GPIO_PB2_I2C0SCL)
GPIOPinConfigure (GPIO_PB3_I2C0SDA)
GPIOPinTypeI2CSCL (I2C_SLAVE_GPIO、I2C_SLAVE_SCL)
GPIOPinTypeI2C (I2C_SLAVE_GPIOI2C_SLAVE_SDA)

//启用 I2C0中断
IntEnable (INT_I2C0)

//启用 I2C 从机接收中断
// I2CSlaveIntEnableEx (I2C0_BASE、I2C_SLAVE_INT_DATA);//当从器件接收到数据时中断

//初始化 I2C 从设备
I2CSlaveInit (I2C0_BASE0x3C)//从器件地址为0x3C
I2CSlaveAddressSet (I2C0_BASE0、0x3C)

I2CSlaveEnable (I2C0_BASE)//启用 I2C 从设备

I2CSlaveIntEnable (I2C0_BASE)//启用 I2C 从机中断
//设置中断矢量
IntRegister (INT_I2C0I2C0_IRQHandler)

//清除接收缓冲区
memset (i2c_rx_Buffer0x00buffer_size)


// I2C0中断服务例程

void I2C0_IRQHandler (void)
{
uart_puts ("I2C0_IRQHandler")

uint32_t status = I2CSlaveStatus (I2C_SLAVE_BASE)//获取 I2C 中断状态
//获取 INT 状态

//如果启动条件中断发生

//检查是否发生数据接收中断
if (status &(I2C_SLAVE_ACT_RREQ | I2C_SLAVE_ACT_RREQ_FBR))//检查是否接收到数据
{
I2C_Rx_BUFFER[i2c_Rx_BUFFER_index]= I2CSlaveDataGet (I2C_SLAVE_BASE)//从 I2C 数据寄存器获取数据
如果(i2c_rx_Buffer_index == buffer_size - 1)
{
I2C_BUFFER_FULL = true;
I2C_RX_BUFFER_INDEX = 0//重置缓冲区索引

否则
{
I2C_Rx_Buffer_index++



I2CSlaveIntClearEx (I2C_SLAVE_BASESTATUS)//清除 I2C 中断状态


下面是 我的主程序编写的函数:

void I2C_MasterWrite (uint8_t slaveAddressuint8_t * datauint8_t len) 
{
I2CMasterSlaveAddrSet (I2C_MASTER_BASE、slaveAddress、false);// false =写入模式
I2CMasterDataPut (I2C_MASTER_BASEdata[0])//将要发送的第一个字节放置在 DATA 寄存器中
I2CMasterControl (I2C_MASTER_BASEI2C_MASTER_CMD_BURST_SEND_START)//第一个字节的启动条件
while (I2CMasterBusy (I2C_MASTER_BASE)//等待直到当前字节传输完毕
//_delay_cycles (1000);//延迟以允许从器件处理数据
对于(uint8_t i = 1;i < len;i++)
{

if (i == len - 1)
{
I2CMasterDataPut (I2C_MASTER_BASEdata[i])//发送当前字节
I2CMasterControl (I2C_MASTER_BASEI2C_MASTER_CMD_BURST_SEND_FINISH)//完成条件
while (I2CMasterBusy (I2C_MASTER_BASE))//等待直到当前字节传输完毕
//_delay_cycles (1000);//延迟以允许从器件处理数据

否则
{
I2CMasterDataPut (I2C_MASTER_BASEdata[i])//发送当前字节
I2CMasterControl (I2C_MASTER_BASEI2C_MASTER_CMD_BURST_SEND_CONT)//继续条件
while (I2CMasterBusy (I2C_MASTER_BASE))//等待直到当前字节传输完毕
//_delay_cycles (1000);//延迟以允许从器件处理数据



如果您需要其他信息、请告诉我。

谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

     首先进行以下更改、然后查看是否有差异。 代码中的任意位置、显示如下行:

    while (I2CMasterBusy (I2C_MASTER_BASE)); 

    替换为:

    while (!I2CMasterBusy (I2C_MASTER_BASE)); 
    while (I2CMasterBusy (I2C_MASTER_BASE)); 
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Charles:

    是的、这已经解决了我的问题!

    非常感谢您的帮助