发 帖  
原厂入驻New
[文章]

STM32 I2C 接口进入 Busy 状态不能退出问题解决分享~

2021-1-27 11:04:55  3894 单片机 STM32
分享
1
问题<span]该问题由某客户提出,发生在 STM32F103VDT6 器件上。据其工程师讲述:在其产品设计中,使用了STM32 的一个 I2 C 接口与一个 EEPROM 通信。在系统靠性测试中发现,经过长时间运行后,STM32 会出现不能读写 EEPROM 的现象。通过 NRST 管脚对 STM32 进行复位,复位后该现象依旧存在。关掉电源,然后重新上电,现象消失。通过进一步测试发现,如果对 STM32 反复做复位操作,会很容易复现这一现象。
调研
修改软件,通过打印监控 I2C 通信程序的流程,及 I2C 接口的各个寄存器的状态。当出现上述现象时,I2C 接口的状态寄存器 SR2 中的 Busy 位置‘1’,状态寄存器 SR1 中的ARLO 位置‘1’。用示波器观察 I2C 总线,发现其 SCL 为高电平,SDA 为低电平。将 STM32的复位脚拉到地,SCL 及 SDA 的状态不变。检查原理图,确认 I2C 总线上只有 STM32 和EEPROM 两颗器件。
结论
EEPROM 驱动 I2C 总线进入了非空闲状态,使得 STM32 在接管总线时发生总线仲裁失败,进而失去对总线的控制,无法启动数据的传输。EEPROM 的这种状态可能是通信被意外中断造成的。通过对 STM32进行复位而重现这一现象,在一定程度上吻合了这种猜测。但没有实验和理论依据证实一定是该原因导致了这一问题,是否还有其它原因在起作用,不得而知。
处理
修改软件,加入对 I2 C 总线修复的功能。在每次发送起始条件之前首先检测 SR2 中 Busy 位,如果为‘1’,则说明总线上有异常。此时,可由 GPIO 的 OD 模式代替 I
2 C 通信口接管 SCL 及 SDA 两个管脚。通过翻转 GPIO,向 SCL 信号线上发高电平脉冲,脉冲宽度及间隔匀为 10uS。每发出一个脉冲之后,检测 SDA 信号是否为高电平。若 SDA 信号为已高电平,则将 SCL 拉高,然后向 SDA 信号线发出一个 10uS 宽的低电平脉冲。然后将 SCL 及 SDA 两个管脚交还给 I2 C 接口,并通过将 CR1 中的SWRST 位置‘1’后再清‘0’来复位 I2 C 接口,使其退出 Busy 状态。如图(一)所示:
i2c.png
A:将 SCL 和 SDA 切换成 GPIO 的 OD 模式;
B:发送时钟脉冲并等待 SDA 跳变到高电平;
C:在 SDA 上发出一个低电平脉冲;
D:在 SDA 拉高后,将 SCL 的 SDA 切换回 I2 C 接口;
E:通过 CR1 中的 SWRST 位复位 I2 C 接口;
建议
STM32 中的 I2 C 接口被设计成为主从自适应接口,并充许多个主机共享一条 I 2 C 总线。I 2 C 接口在被使能之后,会不断的检测 SCL 及 SDA 的电平与跳变。当发现有低脉冲出现在 SCL 或 SDA 上时,则认为总线进入了 Busy 状态,其 Busy 标志会置‘1’,直到在总线上检测到一个符合要的停止条件之后,才认为总线回到了空闲状态,这时由硬件清除 Busy 标志。当 I2 C 接口认为总处于 Busy 状态且不是由自己占用时,会拒绝向总线上发送信号,因为它认为此刻 I2 C 总线正在被其它的主机所使用。这时向 I2 C 接口发命令,要求产生起始条件,会导致总线仲裁失败。要从这种状态退出,首先要保证总线是处于空闲状态,即 SCL 和 SDA 都为高电平。然后,通过将 CR1 的 SWRST 置‘1’然后清‘0’来复位 I2 C 接口,以达到清除 Busy 标志回到空闲状态目的。

相关经验

评论

高级模式
您需要登录后才可以回帖 登录 | 注册

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
发文章
关闭

站长推荐 上一条 /8 下一条

快速回复 返回顶部 返回列表