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.

[参考译文] TMS570LS3137:间歇性 I2C 模块总线繁忙问题

Guru**** 2391845 points
Other Parts Discussed in Thread: TCA6424A

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/997814/tms570ls3137-intermittent-i2c-module-bus-busy-problem

器件型号:TMS570LS3137
主题中讨论的其他器件:TCA6424A

大家好、

我们已设置 MCU I2C 模块为主模式、400kbps、Rm=0、并连接到 TI TCA6424A I/O 扩展器器件。 总线信号很完美、我们的设置也很好、除了在多小时运行期间、状态寄存器中的 BB 位不希望在大约0.5%至0.6%的时间内从忙状态中释放。

在确认 BB=1是一个问题之前、有一个2ms 的超时、这是非常长的。 当 BB 不想自行释放时、我们执行 I2CMDR_BIT.NIR = 0;然后 I2CMDR_BIT.NIR = 1;我们很乐意再次访问、直至下一次出现为止、之后始终释放总线、这意味着 BB=1永远不会连续发生。  

只是为了了解访问次数、每次启动新的写入或读取操作时、对 BB 位的校验都会执行3次、每50ms (20Hz)。

对器件进行读取或写入时都会发生这种情况。 下面是每个写入或读取操作之前被调用的函数:

void SetTxMode(u8 count)
{
        I2CCNT = count;

//method 1: working fine except bus busy problem
        I2CMDR_bit.MST  = 1;        // master mode
        I2CMDR_bit.TRX  = 1;        // transmit mode
        I2CMDR_bit.STT  = 1;        // send START condition + slave address + TRX state
        I2CMDR_bit.STP  = 1;        // send STOP condition once I2CCNT reaches 0
}


void SetRxMode(u8 count)
{
        I2CCNT = count;

//method 1: working fine except bus busy problem
        I2CMDR_bit.MST  = 1;        // master mode
        I2CMDR_bit.TRX  = 0;        // receive mode
        I2CMDR_bit.STT  = 1;        // send START condition + slave address + TRX state
        I2CMDR_bit.STP  = 1;        // send STOP condition once I2CCNT reaches 0
}

我们现在已经有很多个月了。 有人可以帮帮我吗?

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

    在一个 START 条件之后并且在一个后续 STOP 条件之前、I2C 总线被视为忙、 并且 I2CSTR 的总线忙(BB)位为1。 在一个停止条件和下一个启动条件之间、总线 被认为是空闲的、BB 为0。  在接收到一个停止条件后、BB 被清零。

    当 BB=1发生时、STR 寄存器中其它位的值是什么、例如 SCD 位、AL 位?  您是否通过探测总线来了解此问题发生时波形是什么样的?

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

    您好 QJ、

    我没有探测总线信号、但 MCU I2C 模块专用于  个 I/O 扩展器、因此没有其他人共享总线、TX 仅为1个50ms 的寄存器字节/周期、对 BB 进行1次检查、 RX 为2字节/周期、在写入操作码之前对 BB 进行1次检查、在发送2字节数据之前对 BB 进行1次检查、每50ms 对 BB 进行3次检查。  

    另一个注意事项:虽然发生的情况从未连续发生,但当发生时,它往往在短时间内发生多次...

    发生这种情况时、SCD=1和 AL=0。 下面是 I2CSTR 寄存器的内容。

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

    SCD 为1、表示产生停止条件。  

    当 MCU 是主器件接收器时、主器件在最后一个字节从器件(TCA6424A)输出时钟后发送 NACK。  TCA6424A 释放数据线路、从而允许主器件(MCU)生成一个停止条件。

    我不知道在发生错误时捕获 I2C 波形有多困难。 SCL 和 SDA 的样子会有所帮助:如果 SDA 被释放、 或者 I2C SCL 线路上有一个毛刺脉冲、或者 如果针对 NACK 位和 STOP 正确生成了 SCL。

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

    您好 QJ、

    感谢您的建议。 我已经解决了 BB 的问题、这肯定是一个很难找到的问题。 让我解释一下。

    I2CMDR_bit.STT = 1; // send START condition + slave address + TRX state
    I2CMDR_bit.STP = 1; // send STOP condition once I2CCNT reaches 0

    当 CPU 在中间被一个 FIQ/IRQ 中断并且 I2C 模块有时间执行它的任务(通过发送起始条件+地址并将 STT=0)时、这个问题就在这两行代码(位域写入)之间。 但 CPU 从 ISR 返回、并假设 STT 保持为1、因此在当前操作结束时(停止条件之后)触发新的启动条件

    详细说明如下:

    在软件写入 I2CMDR_BIT.STT 和写入 I2CMDR_BIT.STP 之间、应存在延迟或检查、以确保在写入 STP=1之前已执行 START 条件、使 STT=0。 否则、如果 MCU 在这两条线路之间被 FIQ/IRQ 中断、I2C 将有时间执行 START 条件并在 I2C 模块的内部 I2CMDR 寄存器中设置 STT=0、 但是、使用 IAR 创建的位字段结构对 STP=1进行位字段写入没有机会回读当前的 I2CMDR 值、因此它强制第二次写入 STT=1 (而内部 I2C STT=0)。 行为是、当当前 I2C 总线写入结束(STP 位将被清零)时、会产生另一个启动条件、任何人都不会将其停止、从而导致 I2C 总线挂起(BBB=1)。

    再次感谢您!

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

    很好的拍摄 谢谢 Chuck。 但我不明白 I2CMDR_BIT.STP= 1为什么可以设置 STT 位。  

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

    这是因为不支持对 TI MCU I2CMDR 寄存器进行位写操作。 IAR 的编译器必须为这两条指令写入两倍相同的寄存器、方法是对之前的寄存器内容进行或运算。

    在这种情况下、当 STP 被写入时、之前的寄存器内容仍然具有 STT=1、因此第二个起始条件的问题。

    希望这会有所帮助。

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

    明白了,谢谢 Chuck!