一篇文章讲透I2C总线协议

最近一段时间工作上比较忙,一直没有抽出空来写文章与大家分享,这两天腾出些时间静下心来沉淀一番 。看标题大家已经知道了是来总结I2C总线,我相信大家或多或少的都接触过I2C总线,这篇文章我们就由浅入深的仔细来研究研究,看看能不能挖掘些新东西,加深一下理解 。
先说概念I2C英文全称Inter-Integrated Circuit,字面意思是集成电路之间,也就是我们常说的I方C总线—I2C bus 。它是一种串行通讯总线,使用多主从架构,由飞利浦公司(恩智浦NXP的母公司)在80年代开发,用于主板、嵌入式系统连接周边低速设备 。
I2C由两条双向开漏线组成,这是一个很大的优势,接线简单 。两条线利用上拉电阻将电位上拉 。典型电位为+3.3V或+5V 。标准传输速率为100Kb/s,低速模式10Kb/s 。
物理层下图为I2C总线的物理拓扑图,大家可以看到一共只有两条总线,一条SDA(serial data)数据线用来承载数据、一条SCL(serial clock line)时钟线用来控制数据收发时序 。所有I2C设备的SDA都接到了总线的SDA上,SCL都接到了总线的SCL上 。每个设备都有自己的唯一地址,以保证设备之间访问的准确性 。

一篇文章讲透I2C总线协议

文章插图
I2C总线的物理拓扑图
I2C在物理层的连接可以说是非常简单,这也是它最大的优势,原理就是通过控制SDA和SCL线的高低电平时序,来产生I2C总线协议所需要的信号进行数据传输 。在总线处于空闲状态时SCL和SDA被上拉电阻拉高,保持高电平 。
需要注意的是I2C的通讯方式为半双工,因为只有一条数据线,某一时刻只可能单向通讯 。这也说明了I2C不适合大数据量的传输应用 。
对于主机、从机的区分很简单,发布主要命令的就是主机,接受命令的就是从机,同一条I2C总线允许多个主机的存在 。
协议层作为基础我们先来了解几个重要的小概念 。
1、初始状态(即空闲状态):SDA与SCL均为上拉电阻所致的高电平时为初始状态;
2、开始信号:当SCL为高电平的时候,SDA被拉低,此为开始信号,表明通讯开始 。
3、终止信号:当SCL为高电平的时候,SDA被拉高,此为终止信号,表明本次通讯结束 。
一篇文章讲透I2C总线协议

文章插图
 
到这里大家有没有发现点什么?当SCL处于高电平的时候,SDA电平一旦变化就会是一种信号,要么开始要么是终止 。所以在数据传输过程中,SCL处于高电平时,SDA必须保持状态稳定,只有SCL处于低电平时SDA才可以变化 。
4、应答信号:当发送器向接收器发送完一个字节/8位数据后,第9个时钟周期内,接收器必须给发送器一个应答信号,这样数据才算传输成功 。高电平表非应答,低电平表应答 。
一篇文章讲透I2C总线协议

文章插图
 
我们了解这几个信号状态后,来一步一步看看数据是如何传输的 。
1、向从机设备的某一个寄存器写一个字节数据:开始信号+设备地址(7位)+读/写(1位)+等待从机应答+寄存器地址(8位)+等待从机应答+要写的数据(8位)+等待从机应答+终止信号 。下图为24C02 EEPROM存储器写数据的时序图 。
一篇文章讲透I2C总线协议

文章插图
 
2、写我们见识了,那读一个试试:下图为读取24C02当前地址一个字节数据的时序图,是不是一目了然了 。值得注意的是当读的时候地址7位后的读写状态位为1 。这里说一下为什么最后是NO ACK,在“读”这个操作下,主机为接收器,主机的NO ACK表示停止接收24C02的数据,不然24C02会继续发 。
一篇文章讲透I2C总线协议

文章插图
 
3、我们再读一个长一点的:下图为读取24C02任意地址一个字节数据的时序图 。开始信号+设备地址(7位)+写(1位)+等待从机应答+数据地址(8位)+等待从机应答 。前面这一步为假写,目的是告诉24C02要读哪个地址的数据 。继续,开始信号+设备地址(7位)+读(1位)+等待从机应答+读到的数据(8位)+等待主机(接收机)应答+终止信号 。
一篇文章讲透I2C总线协议

文章插图
 
补点干货1、设备的地址 。I2C设备的地址为8位,但是时序操作时最后一位不属于地址,而是读or写状态位 。这就是为什么arduino的SH1106库里操作的地址不是0x7-而是0x3-,因为有用的是前7位,地址整体右移一位处理了 。再一个设备地址的前四位是固定死的,是厂家用来表示设备类型的,比如接口为I2C的温度传感器类设备地址前四位一般为1001即9X、EEPROM存储器地址前四位一般为1010即AX、oled屏地址前四位一般为0111即7X等等 。


推荐阅读