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.

[参考译文] TM4C129ENCPDT:I2C 接口在发送数据之前似乎需要延迟。

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/595096/tm4c129encpdt-i2c-interface-seems-to-need-a-delay-before-sending-data

器件型号:TM4C129ENCPDT

您好!

通过 i2c 总线发送数据时、似乎需要在各个通信之间实现短延迟。

例如、i2c 接口忙于发送数据。 i2c 接口完成传输后立即执行

(最后一个字节已发送且接口空闲)新通信开始。 现在、需要短延迟

i2c 接口之前。 否则、i2c 接口会卡住并停止工作。 对接口进行软复位没有任何帮助。

然后需要对接口进行硬复位。 延迟时间约为2毫秒。

这是我在向从器件发送数据时所做的操作。

[...]

///等待主器件准备就绪。
DRV_i2c2_WAIT_BUSY ();

//主设备从现在开始处于忙状态。
BO_BUSY = true;

//插入延迟时间。 否则主器件会卡住。
DRV_i2c2_delay (com_delay_loops);

//设置工作变量。
ui8_len = ui8_len;
pu8_data = pu8_data;
ui32_action = I2C_MASTER_CMD_SINGLE_SEND;
ui8_MODE = SINGLE_SEND;

//如果只有一个参数使用单发送命令。
if (ui8_len > 1)
{
///设置操作。
ui32_action = I2C_MASTER_CMD_BURST_SEND_START;
ui8_mode = burse_send;
}

//启用中断。
ROM_IntEnable (INT_I2C2);
ROM_I2CMasterIntEnableEx (I2C2_base、I2C_MASTER_INT_DATA);

//向主器件告知从器件地址以及我们要写入的数据。
ROM_I2CMasterSlaveAddrSet (I2C2_base、u8_addr、false);

//交出第一个字节。
ROM_I2CMasterDataPut (I2C2_base、*(pu8_data++));

//开始发送数据。
ROM_I2CMasterControl (I2C2_base、ui32_action);

//等待主机完成数据发送。
///注:发送数据在 ISR 中完成。
DRV_i2c2_WAIT_BUSY ();

//返回
(I2C_ERR_NONE);
} 

数据的发送在中断服务例程中完成。 标志指示主器件是忙还是空闲。 传输时的延迟。 标志在新传输开始时置1、在发送/接收完最后一个字节后清零。

微控制器以120MHz 的频率运行。 i2c 接口以400kHz 的快速模式运行、总线上有一个主器件和三个从器件。

是否有什么想法会导致上述行为?

此致

Marco

 

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

    您好、Marco、

    代码上的一个棘手点是调用 drv_i2c2_wait_businy ()、根据您的描述、该调用只需等待设置标志(并且该标志被告知在 ISR 内部设置)。 基本上、如果确实如此、您实际上并不是在使用中断让 MCU 在数据传输到总线时执行其他操作、 但是、如果您只是内联等待总线空闲、那么代码更易于管理和调试、而不是以等待状态循环。

    这是一段经过测试的代码、作为一种灵感-我甚至不记得导致其中附加错误验证的详细信息...

    while (!goodtransfer)
    {
    while (I2CMasterBusy (AT24_I2C_base));
    I2CMasterSlaveAddrSet (AT24_I2C_base、AT24_EEPROM_ADD、I2C_WRITE);
    while (I2CMasterBusy (AT24_I2C_base)));
    I2CMasterDataPut (AT24_I2C_base、pageaddress);
    I2CMasterControl (AT24_I2C_base、I2C_MASTER_CMD_BURST_SEND_START);
    if (!(I2CMasterErr (AT24_I2C_base)& I2C_MASTER_ERR_ADDR_ACK)
    )) goodtransfer = true;
    }
    

    这个特定的接口硬件使用更多字节、这只是第一个字节的部分。

    此致

    布鲁诺

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

    尊敬的 Marco:
    除了 Bruno 的评论之外、请查看此 I2C 应用手册、其中包括一些 I2C 高速代码示例。  

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

    您好 Bruno、

    是的、你是对的。 通信在 中断服务例程中完成、但在数据传输时、中断确实不用于让 MCU 执行其他操作。

    您发布的代码确实很有趣。 内联等待总线释放是一个有趣的主意。 在 I2C 驱动程序的第一个版本中、我以与您类似的方式处理 I2C 通信。 但由于 I2C 接口的特殊特性、它失败了。 根据 MCU 的器件勘误表、发出事务命令后、需要"设置繁忙状态位大约需要 I2C 时钟周期的60%"。  因此、如果一个传输在另一个传输之后立即开始、BUSY 位可能还没有被置位、尽管 I2C 总线已经忙了。 因此、我决定介绍在中断服务例程中处理的自己的忙位。

    此致

    Marco