1. I2C 框架结构
1.1 I2C 硬件框架

I2C 总线拓扑图
 
 ⚫  
 在一个芯片 
 (SoC) 
 内部,有一个或多个  
 I2C  
 控制器  
 
 
 ⚫  
 在一个  
 I2C  
 控制器上,可以连接一个或多个  
 I2C  
 设备  
 
 
 ⚫  
 I2C  
 总线只需要  
 2  
 条线:时钟线  
 SCL 
 、数据线  
 SDA  
 
 
 ⚫  
 在  
 I2C  
 总线的  
 SCL 
 、 
 SDA  
 线上,都有上拉电阻  
 
1.2 I2C 软件框架

以 I2C 接口的存储设备 AT24C02 为例:
 
 ⚫  
 APP 
 :  
 
 
         ◼ 提出要求:把字符串 
 "www.100ask.net" 
 写入  
 AT24C02  
 地址  
 16  
 开始的地方  
 
 
         ◼ 它是大爷,不关心底层实现的细节  
 
 
         ◼ 它只需要调用设备驱动程序提供的接口  
 
 
 ⚫  
 AT24C02  
 驱动:  
 
 
         ◼ 它知道  
 AT24C02  
 要求的地址、数据格式  
 
 
         ◼ 它知道发出什么信号才能让  
 AT24C02  
 执行擦除、烧写工作  
 
 
         ◼ 它知道怎么判断数据是否烧写成功  
 
 
         ◼ 它构造好一系列的数据,发给 I2C  
 控制器  
 
 
 ⚫  
 I2C  
 控制器驱动  
 
 
         ◼ 它根据  
 I2C  
 协议发出各类信号: 
 I2C  
 设备地址、 
 I2C  
 存储地址、数据  
 
 
         ◼ 它根据  
 I2C  
 协议判断 
 
1.3 我们讲什么
1.3.1 对于 Linux I2C 结构

 
 从上到下:  
 
 
 ⚫  
 先讲  
 I2C  
 协议  
 
 
 ⚫  
 APP  
 可以通过两类驱动程序访问设备  
 
 
         ◼ I2C  
 设备自己的驱动程序  
 
 
         ◼ 内核自带的  
 i2c-dev.c  
 驱动程序,它是  
 i2c  
 控制器驱动程序暴露给用户空间的驱动程序(i2c-dev.c)  
 
 
 ⚫  
 I2C Device Driver 
 
 
         ◼ I2C  
 设备自己的驱动程序  
 
 
         ◼ 内核自带的  
 i2c-dev.c  
 驱动程序,它是  
 i2c  
 控制器驱动程序暴露给用户空间的驱动程序(i2c-dev.c)  
 
 
 ⚫  
 I2C Controller Driver  
 
 
         ◼ 芯片  
 I2C  
 控制器的驱动程序 
 ( 
 称为  
 adapter)  
 
 
         ◼ 使用  
 GPIO  
 模拟的  
 I2C  
 控制器驱动程序 
 (i2c-gpio.c) 
 
1.3.2 对于单片机/裸机

 
 从上到下:  
 
 
 ⚫  
 先讲  
 I2C  
 协议  
 
 
 ⚫  
 APP  
 
 
 ⚫  
 I2C Device Driver  
 
 
 ⚫  
 I2C Controller Driver( 
 也被称为  
 adapter) 
 
2 I2C 协议
2.1 硬件连接
 
         I2C 在硬件上的接法如下所示,主控芯片引出两条线  
 SCL,SDA  
 线,在一条 I2C 总线上可以接很多  
 I2C  
 设备,我们还会放一个上拉电阻(放一个上拉电阻的原因以后我们再说)。 
 

2.2 传输数据类比
 
         怎么通过 I2C  
 传输数据,我们需要把数据从主设备发送到从设备上去,也需要把数据从从设备传送到主设备上去,数据涉及到双向传输。  
 
 
         举个例子:          
 

 
         体育老师:可以把球发给学生,也可以把球从学生中接过来。  
 
 
 ⚫  
 发球:  
 
 
         ◼ 老师:开始了 
 (start) 
 
 
         ◼ 老师: 
 A 
 !我要发球给你! 
 ( 
 地址 
 / 
 方向 
 )  
 
 
         ◼ 学生  
 A 
 :到! 
 ( 
 回应 
 )  
 
 
         ◼ 老师把球发出去(传输)  
 
 
         ◼ A  
 收到球之后,应该告诉老师一声(回应)  
 
 
         ◼ 老师:结束(停止) 
 
 
 ⚫  
 接球:  
 
 
         ◼ 老师:开始了 
 (start)  
 
 
         ◼ 老师: 
 B 
 !把球发给我! 
 ( 
 地址 
 / 
 方向 
 )  
 
 
         ◼ 学生  
 B 
 :到!  
 
 
         ◼ B  
 把球发给老师(传输)  
 
 
         ◼ 老师收到球之后,给  
 B  
 说一声,表示收到球了(回应)  
 
 
         ◼ 老师:结束(停止)  
 
 
 我们就使用这个简单的例子,来解释一下  
 IIC  
 的传输协议:  
 
 
 ⚫  
 老师说开始了,表示开始信号 
 (start)  
 
 
 ⚫  
 老师提醒某个学生要发球,表示发送地址和方向 
 (address/read/write)  
 
 
 ⚫  
 老师发球 
 / 
 接球,表示数据的传输  
 
 
 ⚫  
 收到球要回应:回应信号 
 (ACK)  
 
 
 ⚫  
 老师说结束,表示  
 IIC  
 传输结束 
 (P) 
 
2.3 IIC 传输数据的格式
2.3.1 写操作
 
 ⚫  
 主芯片要发出一个  
 start  
 信号  
 
 
 ⚫  
 然后发出一个设备地址 
 ( 
 用来确定是往哪一个芯片写数据 
 ) 
 ,方向 
 ( 
 读 
 / 
 写, 
 0  
 表示写,1  
 表示读 
 )  
 
 
 ⚫  
 从设备回应 
 ( 
 用来确定这个设备是否存在 
 ) 
 ,然后就可以传输数据  
 
 
 ⚫  
 主设备发送一个字节数据给从设备,并等待回应  
 
 
 ⚫  
 每传输一字节数据,接收方要有一个回应信号(确定数据是否接受完成 
 ) 
 ,然后再传输下一个数据。  
 
 
 ⚫  
 数据发送完之后,主芯片就会发送一个停止信号。  
 
 
 ⚫  
 下图:白色背景表示 
 " 
 主 
 → 
 从 
 " 
 ,灰色背景表示 
 " 
 从 
 → 
 主 
 "  
 

2.3.2 读操作
 
 流程如下:  
 
 
 ⚫  
 主芯片要发出一个  
 start  
 信号  
 
 
 ⚫  
 然后发出一个设备地址 
 ( 
 用来确定是往哪一个芯片写数据 
 ) 
 ,方向 
 ( 
 读 
 / 
 写, 
 0  
 表示写,1  
 表示读 
 )  
 
 
 ⚫  
 从设备回应 
 ( 
 用来确定这个设备是否存在 
 ) 
 ,然后就可以传输数据  
 
 
 ⚫  
 从设备发送一个字节数据给主设备,并等待回应  
 
 
 ⚫  
 每传输一字节数据,接收方要有一个回应信号(确定数据是否接受完成 
 ) 
 ,然后再传输下一个数据。  
 
 
 ⚫  
 数据发送完之后,主芯片就会发送一个停止信号。  
 
 
 下图:白色背景表示 
 " 
 主 
 → 
 从 
 " 
 ,灰色背景表示 
 " 
 从 
 → 
 主 
 "  
 

3 I2C 信号
 
         I2C 协议中数据传输的单位是字节,也就是  
 8  
 位。但是要用到  
 9  
 个时钟:前面 8  
 个时钟用来传输  
 8  
 数据,第  
 9  
 个时钟用来传输回应信号。传输时,先传输最高位(MSB) 
 。  
 
 
 ⚫  
 开始信号( 
 S 
 ): 
 SCL  
 为高电平时, 
 SDA 由 
 高电平向低电平跳变,开始传送数据。  
 
 
 ⚫  
 结束信号( 
 P 
 ): 
 SCL  
 为高电平时, 
 SDA  
 由低电平向高电平跳变,结束传送数据。  
 
 
 ⚫  
 响应信号 
 (ACK) 
 :接收器在接收到  
 8  
 位数据后,在第  
 9  
 个时钟周期,(从设备)拉低  
 SDA  
 
 
 ⚫  
 SDA  
 上传输的数据必须在  
 SCL  
 为高电平期间保持稳定, 
 SDA  
 上的数据只能在SCL 为低电平期间变化  
 
 
         I2C 协议信号如下(前半部分数据是发送地址位和方向,后半部分是数据,发送原理一样):  
 

在 SCL 为高电平时,SDA 拉高,读取到 1;在SCL为高电平时,SDA拉低,读取到0。
4 协议细节
 
 ⚫  
 如何在  
 SDA  
 上实现双向传输? 
 
 
         ◼ 主芯片通过一根  
 SDA  
 线既可以把数据发给从设备,也可以从  
 SDA  
 上读取数据,连接 SDA  
 线的引脚里面必然有两个引脚(发送引脚 
 / 
 接受引脚)。  
 
 
 ⚫  
 主、从设备都可以通过  
 SDA  
 发送数据,肯定不能同时发送数据,怎么错开时间?在 9  
 个时钟里:  
 
 
         ◼ 前  
 8  
 个时钟由主设备发送数据的话,第  
 9  
 个时钟就由从设备发送数据;  
 
 
         ◼ 前  
 8  
 个时钟由从设备发送数据的话,第  
 9  
 个时钟就由主设备发送数据。  
 
 
 ⚫  
 双方设备中,某个设备发送数据时,另一方怎样才能不影响  
 SDA  
 上的数据?  
 
 
         ◼ 设备的  
 SDA  
 中有一个三极管,使用开极 
 / 
 开漏电路 
 ( 
 三极管是开极, 
 CMOS 管是开漏,作用一样) 
 ,如下图: 
 



















