该文章参考http://www.cnblogs.com/BitArt/archive/2013/05/28/3103917.html,在此感谢。
关于I2C总线介绍详见http://www.cnblogs.com/BitArt/archive/2013/05/28/3103917.html。
关于I2C总线 ACK和NACK信号说明,详见http://blog.csdn.net/luckywang1103/article/details/17549739
该文章主要记录I2C通信调试过程中遇到疑问点。
一、未调试前的观点
1、启动和停止条件
启始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。
2、读写操作
3、数据有效和变化
数据有效:在SCL时钟高电平期间保持不变。
数据变化:SDA上的数据必须在时钟信号的低电平期间改变。每个时钟脉冲传送一位数据(即在上升沿实现SDA数据传递)。
写入顺序: 对于一个byte,先MSB,后LSB。
3、ACK应答信号
每个字节后会跟随一个ACK信号。ACK bit使得接收者通知发送者已经成功接收数据并准备接收下一个数据。所有的时钟脉冲包括ACK信号对应的时钟脉冲都是由master产生的。例如发送一个byte数据,共产生9个时钟脉冲:前八个脉冲用于数据传递,第9个脉冲用于ACK或NACK信号。
ACK信号:发送者在ACK时钟脉冲低电平期间释放SDA线,接收者可以将SDA拉低并在时钟信号为高时保持低电平。
NACK信号:当在第9个时钟脉冲的时候SDA线保持高电平,就被定义为NACK信号。Master要么产生STOP条件来放弃这次传输,或者重复START条件来发起一个新的开始。
所以判断有无ACK信号:关注ACK时钟(即第9个时钟)高电平期间,SDA总线状态。如果为拉低,表示有ACK信号;如果为高,表示NACK。
注意:读操作ACK产生前的主机释放SDA总线,不够明显。因为read位为1.而写操作ACK不同,write位为0,主机释放总线,能够明显看到高电平。
二、调试后的观点
调试环境:DM8168 + MCP79410,其中
1、DM8168是集成I2C硬件模块的ARM
2、MCP79410是集成RTC、EEPROM等模块的I2C接口器件。
MCP79410的I2C总线上地址:0x6F,调试之前配置DM8168的I2C模块。
调试项
1、写操作(向MCP79410器件内0x0A地址,写0x5A数据)
MCP79410手册中写操作时序
示波器监测到写操作
在SCL时钟的上升沿读取SDA总线上数据。
2、读操作(读MCP79410器件内0x0A地址中内容)
MCP79410手册中随机读操作时序
示波器监测到读操作
3、ACK应答要求
MCP79410手册中ACK操作时序
应答信号产生位置
首先主机在第1-8个SCL时钟内 发送完第一个字节(ID地址+R/W)后,主机释放SDA总线(即置高),等待从机ACK信号。 如果从机在 第9个SCL时钟低电平(即第8个SCL时钟高电平结束 --- 第9个SCL时钟高电平前)时间段拉低SDA,表示从机有ACK;反之,SDA一直为高电平,表示从机无应答NACK。若从机有ACK(即SDA为低),在第9个SCL时钟高电平保持ACK,然后在随后下降沿,从机释放SDA总线。可以解释示波器监测到I2C的ACK应答信号波形。
三、小结
3.1 之前误解
1、将从机释放总线的那个脉冲 误以为是从机ACK应答信号。之前纠结 为什么从机ACK应答信号出现在第10个SCL时钟的低电平,不符合I2C的应答时序?
原因:出现第10个SCL时钟期间的低电平信号 非ACK应答信号。而是在第9个SCL时钟高电平期间 从机一致拉低SDA(即ACK信号),到第10个时钟低电平期间释放SDA总线(即SDA总线变为高电平),此时主机写入数据MSB位为0 拉低SDA总线。所以误以为该信号为ACK信号。
2、主机读取从机数据后,是否有应答信号? 好像没有,需要实测验证。
3.2