对于硬件工程师,I²C 再熟悉不过了,两根线,一根数据 SDA 一根时钟 SCL。当时在使用 avr CPU 设计数据采集器产品的 CPU 主板,外挂了 Silicon lab 的温湿度传感器Si7013,实时时钟,主要实现温湿度、时钟及电流电压等信号通过 I²C 总线到达 CPU 进行处理,并且由 MCU EFM32WG290F64控制在液晶上和上位机界面上的 CPU 自带的 I²C 总线外挂的六个 I²C 从设备,如下图 1 所示。

 

图 1:Avr 的 I²C 接口电路图

 

最初时候,此 CPU 主板的 I²C 接口仅挂了实时时钟和温度芯片,采用 CPU 自带的 I²C 接口。在调试时,波形都比较正常,上升沿和下降沿都能符合要求,通常跑的速率为 100KHz。然而后期改版,需要在 I²C 接口上增加四个 I²C 设备,线路也相应地变长,在调试的时候,就发现 CPU 主板上电后,I²C 工作异常,偶尔会读不到任何信息。

 

经过了长时间的查问题阶段,发现通过 I²C 接口的 SDA 和 SCL 上拉电阻的大小与放置位置都是有讲究的。通常 I²C 上拉电阻放在 CPU 引出的位置,若没有外挂的 I²C 芯片就不需要加上拉电阻,这点在我们的 CPU 主板是没有问题的。然后就是上拉电阻,这个通常讲的就是与速率有关,我们将上拉电阻从 4.7K,2.2K,1K 甚至几百欧姆都测试过,在 1K 和 2.2K 的情况下,上升沿和下降沿会比较陡一点。速率 100KHZ 下采用 2.2K 的上拉电阻测试出的 I2C 波形,如图 2 所示。

 

图 2:在 100Khz 下,采用 2.2K 的上拉电阻测试出的 I²C 波形

 

最终测出的情况,在上拉电阻为 4.7K 的时候,速率在 100KHZ,波形是正常的;在 2.2K 的时候,速率在 100Khz 的时候,波形也是正常;在 1K 的时候,速率为 400Khz,波形也正常;在 470 欧姆的时候,速率为 400KHZ,波形就会畸变。我们采用的上拉 2.2K,速率为 100KHZ 的接口,仍出现 CPU 板电后 I²C 工作异常,读不到任何异常信息。后发现是 SDA 被一直拉低了,SCL 一直为高,I²C 被死锁了。

 

为了解决这种问题,在网络上找到一种采用 IO 模拟 I²C 的方式,调试了一周后,发现这个问题得到了解决。将 I²C 接口当做普通 IO 来操作可能是改动最小的一种方式。其实针对这个问题,还有一些办法可以使用:

1)尽量选用带复位输人的 I²C 从器件。

2)将所有的从 I²C 设备的电源连接在一起,通过 MOS 管连接到主电源,而 MOS 管的导通关断由 I²C 主设备来实现。

3)在 I²C 从设备设计看门狗的功能。

4)在 I²C 总线上增加一个额外的总线恢复设备,用来监视 I²C 总线。当设备检测到 SDA 信号被拉低超过指定时间时,就在 SCL 总线上产生 9 个时钟脉冲,使 I²C 从设备完成读操作,从死锁状态上恢复出来。总线恢复设备需要有具有编程功能,一般可以用单片机或 CPLD 实现这一功能。

 

由于 avr CPU 带多个 I²C 从设备出现死锁的问题,虽然能够通过 IO 模拟解决问题,但是对于编程来说比较麻烦,IO 模拟在高速上面效果并不好。后来更换了Silicon Labs的 MCU,型号为EFM32WG290F64,做了一个最小系统板,外围电路不变,I²C 死锁问题不再存在,有效地解决了我的 I²C 问题。采用 EFM32WG290F64 读到的 I²C 波形如下:

 

图 3:EFM32WG290F64 读到的 I²C 波形

 

另外,设计中通过采用了多片温湿度传感器Si7013,精度也非常高,特别在高温条件下,测试的湿度准确率也非常高。其实 I²C 接口在我们的设计中再常见不过,但在设计中还是要特别注意以下几点,能够充分考虑以下的要点,I²C 设计就可以游刃有余。

1)I²C 线路的负载电容不能超过 400pF;

2)需要满足上升沿和下降沿的时序关系;

3)I²C 上拉电阻和速率有着密切的联系,需要选择合理;

4)如何判断死锁的情况,如上面所示,并提供了一系列的解决方案。