通常这块内容在I2C设备电气特性这一块,主要讲解电平拉高拉低的最长时间、最短时间,以及处于高电平与电平的阈值与持续时间等等内容。
硬件设计,为了降低单片机的功耗与保护芯片引脚,在满足负载电流和负载电容相关要求的前提下,阻值设置通常比较大。如果同一个总线上挂载多个I2C设备, 即使在 I/O口配置正确的前提下,也会导致驱动能力不足。
现象是拉高电压不足,在拉高、拉低过程中消耗时间过长。这两个问题通常还引起数据线与时钟线:拉高时,高电压持续时间过短;拉低时,低电压持续时间过短。用示波器抓取图形:从波形上看,显示是尖波、斜波、杂波等不符合I2C设备电气特性的波形;从数据上看,数据线高电平持续时间过小 ,上升沿时间过长 ,下降沿时间过长等等数据超出设备电气特性的有效值。典型杂波图,如下所示
如果出现此类异常,建议更换小一点的电阻,用来增强总线驱动能力,提高电平转换速度。应当注意的是每个MCU的耐受电流不一样,减小电阻应避免超过相应引脚承受电流的最大值。
3 SDA 死锁
如果I2C设备的数据偶尔能够正确获取,但是仍然会在总线发送数据或者命令的时候,爆出总线读写错误,那么有可能遇到下面的死锁问题,死锁时候,就是数据线被拉低,主机无法拉高。死锁一般发生在从机上,且为数据线死锁。因为I2C总线是共享的,如果需要确定,是否是从机死锁,可以参照下面两幅图,串联电阻进行测试
如上图所示,如果从机死锁,即从机拉低电平,此时检测到的电压为1/3 Vcc。
如上图所示,如果主机死锁,即主机拉低电平,此时检测到的电压为 1/11 Vcc。依据这个原理,可以准确判定死锁的具体位置,多个传感器依据类似方式进行定位。
3.1 反复重启导致死锁
3.1.1 现象
如果设备需要反复重启,很有可能在从机设备返回数据的时候,SDA被锁住。具体原因是从机设备在回数据,还没有发送完成,主机时钟消失,从机等待时钟信 , MCU重启,如果从机设备的电源没有复位,从机继续等待 MCU 时钟信 ,数据一直被钳住,总线无法完成数据交互。
3.1.2 解决方式
解决重启导致总线死锁,一种方式可以如同 rt-thread 驱动解决方式一样,在系统复位的时候,提供9个时钟信 ,解初总线死锁;另一种是在按下复位键初始化的时候,给从机设备电源断电重启,这个需要引脚控制。
3.1.3 9 个时钟信
I2C设备进行读写操作的过程中,在从机钳住总线的期间,MCU 异常复位,会导致 SDA 死锁,异常产生出现在俩个阶段:从机响应阶段、从机发送数据阶段。下面将针对这两种异常,对时钟信 进行解释,并且总结其他原因,得出结论。
(a) 从机响应阶段
MCU 在开始信 后发送地址,得到从机设备响应,准备开始返回数据,在这个时候,从机将 SDA 信 拉为低电平,如果 MCU 异常复位,会导致总线上 SCL 停止发送时钟信 ,从机等待 MCU 的时钟信 ,产生钳住并且拉低 SDA 的现象。如果想要解锁 SDA,从机需要 9 个时钟信 ,使得从机完成响应,释放 SDA 。
(b) 从机发送数据阶段
如果从机响应完成了,开始给MCU返回数据。这个数据有八位,每一位都有可能为低,如果在数据低位,MCU异常复位,停止发送时钟信 ,从机就会等待 MCU的时钟信 ,产生钳住并且拉低SDA的现象。如果想要解锁SDA,从机需要 1-8个时钟信 ,使得从机完成数据响应,释放 SDA 。
(c)其他情况
在从机一个8位数据发送完成后,等待MCU响应, 即使属于MCU的,从机不再钳住 SDA,没有时钟,数据交互停止。
在主机发送数据阶段,总线所有权在主机,主机异常,数据交互停止,总线释放。所以,这些情况下,不存在SDA死锁的情况。
(d)结论
综上所述,解锁SDA从机最多需要 9 个时钟信 ,也就是异常复位后,MCU至少发送需要9个时钟信 ,完成 i2c 总线的SDA解锁。所以,RT_Thread 为了避免此类问题的产生,在i2c驱动初始化,对总线进行判断,判断是否需要解锁,如果需要,就进行解锁,确保 i2c设备不会因为这个问题导致数据交互失败。
3.2 多个I2C设备导致死锁
多I2C设备除了异常复位导致死锁,还会形成相互干扰的问题,一般情况下,不会把同种从机地址挂在同一条总线上,但除此之外,有些I2C设备设计不是按照标准的I2C总线协议设计,在I2C总线共享的前提条件下,有的设备只要总线上从机地址就会有响应。这样由于从机的错误响应,使得各个I2C总线异常,甚至钳住总线,导致 I2C总线进人一种死锁状态。
解决方式,这样的不标准i2c设备,单独使用一个总线,避免干扰,或者单独一个独立引脚,控制电源。