重中断负载下的 I2C 读/写失败

电器工程 i2c
2022-01-23 03:56:19

在我的系统中,我正在使用 I2C,并且我意识到在重中断负载(来自其他来源)下,I2C 通信很容易中断。这是 I2C 的预期行为吗?尽管有中断负载,我还是会预料到,它仍然可以,因为 I2C 并不完全是一个时间关键接口,时钟提供了数据。

更新:

处理器是STM32。中断是由于 ADC 造成的,我无法在读取事件期间禁用中断,因此我必须找到一种解决方案,使 i2c 通信更加稳定。STM32 是主机,从机是另一个设备(加速度计)。

更新2:

当我用一根小飞线将逻辑分析仪连接到时钟时,问题就消失了。有趣的是,没有中断负载,读写效果很好,当有中断负载时,它们就不行了。但是,如果我将探针连接到时钟,读写也可以在中断负载下工作。我认为,某处存在电容问题。

4个回答

这是一个软件问题,您花费了太多时间来处理中断并且您的 I2C 例程无法处理它(所以这是不正确的两件事)。我经历过好几次类似的情况。

第一:你需要在中断中做尽可能少的事情,只读取和存储数据,不要做任何你可以在 ISR 之外做的处理,数学会占用很多 CPU 周期,而 CPU 不能做任何其他事情在那个中断中。

第二:研究 DMA 以使事情自动化,因此您的中断几乎成为后台自动化进程。

第三:如果 I2C 很重要,也将其放入中断中,但请确保确定优先级!

第四:找出您的 I2C 例程失败的原因,I2C 本身可以承受非常间歇性的计时、暂停和等待等,因此您的例程可能需要修改以允许这样做。

第五:看看你是否可以“链接”中断,你可能会发现你可以更有效地为 ADC 读取提供服务,或者将 ADC 置于不同的模式,在中断之前它可以为你做更多的工作(EG 等待所有读数可用,然后一次读取全部,而不是 8 个单独的中断用于 8 个单独的 ADC 通道读取)。

第六:使用示波器或逻辑分析仪,以及板上的备用 IO 引脚,跟踪您在每一位代码中花费了多少时间,看看您是否可以加快速度。(进入功能/ISR 时将引脚设置为高电平,退出时再次将其设置为低电平)。

第七:决定你是否真的需要这么多地阅读 ADC,放慢速度会让事情变得更糟吗?这是违反直觉的,但有时运行速度较慢实际上会产生更好的结果,为您平均信号并减少可能导致问题或需要额外处理才能消除的尖峰/瞬变。我们通过简单地以 1/4 的速度运行它来改进电机控制 PID 例程,从而在此过程中释放大量 CPU 时间。

忙于其他事情的总线从站有能力延长时钟以争取时间,直到它能够继续通信结束。它通过不立即发送 ACK / NACK 时钟脉冲来做到这一点,将通信保持在中间状态,直到它准备好回答。

时钟延长是处理这种情况的适当方法。一个不伸展并且做其他坏事的设备(总线挂起/重新启动,NACKs 一个有效的地址或命令等)可能是有问题的,并且会给主机带来额外的负担以保持事情的整理(它必须重复命令,跟踪 NACK 等)

根据 STM32 的功能(我从未使用过),您可以尝试以下方法之一。如果您可以提供有关您正在尝试做的事情的更多细节,并有一个令人信服的论据来说明为什么每个中断都以您现在拥有的形式是必要的,那么可能会考虑一个更具体的答案。但是,特别是在您的情况下,I2C 的速度足够慢,因此编写良好的中断例程不会成为问题。

  • 通常可以禁用任何事物的中断。在任何常用的控制器中最多有一个或两个不可屏蔽中断,其中一个被重置。如果您不需要某些东西(ADC 或 I2C,在您的情况下)进行中断驱动控制,则将该外围代码转换为不使用中断的代码,然后禁用中断。

  • 中断处理程序不应该很长。尝试从中断向量本身做尽可能少的事情。最简单的中断方法是在中断处理程序例程中简单地设置一个标志,并让主循环从那里开始执行所有繁重的工作。您的特定应用程序和固件架构所需的可能并不像那个,但是确实值得努力看看在中断中真正需要做多少事情。

  • 如果您有外设 DMA,请使用它而不是在每个字节处中断。通常,将 ADC 放在 DMA 上比 I2C 更容易,但不同的芯片有不同的实现。如果也有一种干净的方式将 I2C 交换与 DMA 分离,我不会感到惊讶。DMA 允许您减少中断次数,并使您的处理器内核不必处理每个数据块。

  • 尝试确定您看到数据损坏的特定实例,以及发生数据损坏的机制。这很难做到,但是通过创造性地使用现代示波器/逻辑分析仪,您可能会发现一些问题。具体来说,确保问题与时间有关,而不是内存(这可能与糟糕的代码和自由编译器的组合有关)

编辑:关于这个问题实例的一些具体说明,来自您对问题的评论:

  • 使用 80% 的 CPU 来读取 ADC 通常是不值得的事情。如果您无法对数据采取行动,甚至无法保存数据,那么收集数据将毫无用处。
  • 即使您以某种方式收集(有用地)大量数据,ADC 中断也不应该长到完全抑制 I2C 外设足够长的时间以使其丢失数据。I2C 最多以 100/400KHz 运行。您需要一个非常非常长的中断来中断足够长的时间,使其看起来比 I2C 上的时钟抖动更严重。

在给定的系统中,可能会有噪声进入时钟和数据总线。您的逻辑分析器消除了问题的事实表明了这一点。对于实际和最快的实施,只需按照您的观察给出的提示即可。在 400kbits/sec 实现的 i2c 总线上,基于类似的观察,我将 2M 与 12pf 从时钟和数据点并联到地,发现问题已解决。这可以去除/过滤特定 i2c 通信所需的感兴趣频带之外的噪声。请尝试和建议。