AS32系列MCU芯片I2C模块性能解析与调试
国科安芯推出的AS32X601内置的I2C模块提供了符合工业标准的两线串行制接口,可用于MCU和外部IIC设备的通讯。IIC总线使用两条串行线:串行数据线SDA和串行时钟线SCL。 IIC接口模块实现了IIC协议的标准模式和快速模式,支持多主机IIC总线架构。其中标准模式为100K,快速模式400K。
-
硬件设计
I2C 总线内部使用漏极开路输出驱动器,因此 SDA和 SCL 可以被拉低为低电平,但是不能被驱动为高电平,所以每条线上都要使用一个4.7K上拉电阻,默认情况下将其保持在高电平。
-
I2C时序
①Start开始信号、Stop停止信号:
这两个信号由主机产生,不属于数据域交互:
在SCL的高电平时,主机将SDA的电平由 高–>低是Start信号(下降沿);
在SCL的高电平时,主机将SDA的电平由 低–>高是Stop信号(上升沿);
②7位寻址
AS32X601的I2C只支持7位寻址模式,配置过程中从机地址需要左移1位才为实际地址。
③数据方向
0写/1读
④应答ACK、非应答NACK
在SCL的一个时钟周期内,从机在SCL的高电平时,将SDA的电平由高拉低(或者继续保持低电平状态) 则是ACK信号;
从机在SCL的高电平时,如果SDA的电平一直是 高电平 则是NACK信号;
-
时钟
I2C0、I2C1时钟来自APB0,I2C2、I2C3时钟来自ABP1。具体配置可见I2C_CTLR寄存器。
-
软件编程
-
配置I2Cx需要的GPIO为复用功能。
-
通过配置I2C_INITSTRUCT初始化I2Cx,包括时钟分频,从机地址,ACK,高低电平时间等。
3. 按需求配置中断,并配置IRQ_HANDLER;
4. 调用收发接口,并处理数据
-
I2C挂死原因解析
由于I2C采用线与结构,只要总线上任何一个器件拉低了SDA或者SCL,其他器件都无法拉高它们,看到的都是低电平。如果有器件不释放总线,则整个总线上的通讯都会被暂停 。
在实际操作中,I2C主是可编程器件,如果主机主动拉低了总线,可以通过调试代码了解原因,也可以通过复位I2C外设或者复位芯片来退出。而I2C从机往往不带RESET引脚,如果挂死了总线即使整个系统复位都无法解除,仅重新上下电才可以恢复,因此分析I2C从机挂死。
首先I2C从机在两种情况下会拉低SDA线。
①主机向从机写数据或地址时,从机如果发出ACK应答,则会第9个CLK的期间拉低SDA;
②主机读数据的时候,从机会在bit为0时对应的CLK期间拉低SDA。
根据I2C协议,SCL为高的时候,SDA电平应保持,而等到SCL为低后(也就是下降沿后)才能发生改变。若SCL拉高后主机不再拉低,从机会持续拉低SDA,直到见到SDA的下降沿。
最常见的情况是主机在通讯的过程中产生了复位。由于复位动作通常会立刻执行,外设状态机都恢复到默认状态,也就发不出完整的CLK。那么等到主机复位完成回来后,SCL为高,SDA被从机拉低。主机无法发起START起始条件,不能开始下一次与从机的通讯,这称为SDA挂死。
我们一般情况下用GPIO在SCL线上模拟一个下降沿,让从机状态机继续走下去。只发一个下降沿并不一定能将SDA释放,因为并不清楚当主机复位异常发生时刻从机到底处于哪一个状态,所以需要逐个CLOCK去抓波形,直到见到SDA被释放了,我们才终止并且发送STOP条件告诉从机这次通讯结束。