目录
前言
说起I2C总线大家并不陌生,很多单片机的外设如时钟芯片,eeprom等都是I2C总线,通常写好几个基本的驱动函数如START STOP ACK READ WRITE等函数就可以正常工作了,但是在某些特殊情况应用的I2C总线的时候,就会发现还有很多问题是你没有考虑到的。
一、问题描述
有一块智能电池,带有可以读电池电量的I2C总线接口,但是无论怎么调整驱动程序,将总线频率从400k降到40k,还是容易发生读写数据出错的问题。
二、问题分析
1、通过逻辑分析仪抓取读取出错时的总线波形,发现时钟总线在很长时间被异常拉低了,这显然不是程序干的,因为调试程序没有干别的事情,仅仅在固定间隔的驱动总线,应该是电池拉低了总线。
2、通过查找资料,发现在I2C标准协议中(见附录),当I2C从机在忙时可以暂停总线传输,方法是将时钟总线拉低,只要总线未被释放,主机需要一直等待,像SMT32等一些单片机的I2C外设,作为主机都有自动等待从机的功能,但如果直接用I0口模拟I2C总线,理想情况下时序完全由主机控制,很多的芯片速度都很高,一般不会出问题,但在一些比较特殊的情况下,这种模拟I2C总线遇到从机忙的时候就会操作失败。
三、解决办法
问题的关键在于模拟I2C总线在驱动时钟总线的时候未判断总线的状态,原来时钟总线的驱动是 SET_CLK_HIGHT() 和 SET_CLK_LOW() ,现在只需重新定义这两个操作动作,即在每个动作执行前检查时钟总线是否已经是高电平了,如果不是,则一直计时等待,直到从机释放总线继续运行,或者超时异常退出即可。