【嵌入式基础小知识】简单聊聊 IIC 总线

438 阅读6分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

早上醒来,充分地好好活这一天,最近我只留心这件事。现在我不说谎了,读书也逐渐不是为了虚荣与算计。以前老爱仰赖明天、敷衍当下,现在也不会了。只是一天一天,非常珍惜地过日子。 ​​​ 太宰治 -- 《小说灯笼》

一、概述

IIC-BUS,是 Inter-Integrated Circuit Bus 的缩写,顾名思义,简单、方便地连接各种外设芯片,一种双向2线制同步串行总线。

二、基本特征

基本特征如下:

  • 串行(只有一根数据线,只能一位一位 bit 发送和接收)
  • 同步(两边使用共同的时钟线:无论是接收还是发送数据,时钟都是由主机提供)
  • 单端(区别于差分信号,数据线使用绝对电平作为 0 或者 1 的区分)
  • 双向(半双工,同一时间只能接收或者发送)
  • 主从(Master/Slave,只能由主机发起通信请求,从机只能响应)
  • 总线(Bus,一条通信链路可以接多个设备)

三、电路连接和配置

一般的电路连接如下所示:: 在这里插入图片描述 右图中可知,设备间连接至少需要三根线:SDA(串行数据线)、SCL(串行时钟线)和 GND(地)。 需要注意的是,无论是主机还是从机 SDASCL 的引脚,都需要配置成 漏极开路(OD:Open drain,存在于MOS管中)或者 集电极开路的(Open Collector,存在于三极管中)的形式: 在这里插入图片描述 这个特征需要我们在嵌入式系统中使用 IIC 时需要考虑两个点:

  • 硬件设计时,两根信号线都需要增加上拉电阻
  • 软件设计时,单片机的 GPIO 端口要配置成漏极开路(OD:Open drain)模式,效果就是:导通时会将总线电压拉低到地,不导通时就是高阻态,等效于一个阻值超级大的电阻,相当于分压很大,不影响信号线的电平)

这样的电路设计其实是为了实现 线与 功能,线与的意思就是 逻辑与,对应到这里的的电路是:所有设备不拉低才为高,只要有一个设备拉低就会将总线拉低。

四、优点

  • 只需要2根信号线(节约 PCB 板面积、引脚、成本等,都是钱呀)
  • 协议简单(当然是相对于 USB以太网等协议)
  • 协议容易实现(硬件电路比较简单)
  • 支持的器件多(硬件 IIC 功能是现在单片机的标配,当然一些低端的 8 位单片机可能没有,但也能使用 GPIO 模拟实现) 。
  • 总线可以同时挂载多个器件 (这就是总线的优势了)
  • 总线电气兼容性好(对于常用的 5V、3.3V都支持,就看你上拉电阻选择哪一个了)
  • 速率较高(100kbps ~ 400kbps ~3.4Mbps,其实这个速率只能算一般吧)
  • 距离较远(几米,降低速率~十几米,不过一般都是比较近的使用场景,为了保证信号的准确性,远距离会选择具有差分信号的信号线)

五、I2C 总线的电平逻辑

I2C 是电平有效的(SPI 则是边沿有效的),也就是说:在传输数据的过程中,在 SCL 为低电平时,数据线 SDA 的电平发生变化,在 SCL为高电平时,SDA 的电平保持不变(这个时候的电平就是通信的数据位)。 当然,也有特殊情况,在 I2C 总线开始和结束数据传输时,SDA 在 SCL 为高时变化,这正好能够区分是传输数据还是起始结束信号。

5.1、起始与结束信号

在这里插入图片描述 如图所示,

  • 起始位: 当SCL处于高电平时,SDA从高电平向低电平跳变,产生“起始”位。 总线在起始条件产生后便处于忙(Busy)的状态。可将“起始”位简记为S。
  • 停止位: 当SCL处于高电平时,SDA从低电平向高电平跳变,产生“停止”位。 总线在停止条件产生后处于空困状态。可将“停止”位简记为P。

5.2、通信数据帧

在这里插入图片描述 在这里插入图片描述

灰色方块表示主机控制 SDA 数据线发送数据,白色方块表示从机控制 SDA 数据线给主机应答或者响应数据给主机。

SA(Slave Address) 为从机地址,主机不需要地址,但是从机必须要有个地址,因为总线连接多个设备时需要用地址区分,同时设备也只响应针对自身地址的通信,其中总线的从机地址位为 7 bits,即只可以连接 128 个从机设备。(值得说明的是,大多数 I2C 从机设备会将这7位固定好几位,这样有能够减少设备的引脚数的优势,这个看手册的说明即可)

5.3、高阶知识

重复起始(Repeated Start)

在这里插入图片描述 上图中的 Sr 为重复起始 (Repeated StartI2C 通讯中,有时需要切换数据收发的方向,例如 I2C 设备是个EEPROM 存储器时,要读 EEEPROM ,需要先写入地址(主->从),再读取数据(从->主), 此时无需给出停止位,然后再给开始位,而是直接再产生一次开始位,就可以了,称为“重复起始位,记为 Sr。这样做的好处是提高了通信的效率。

I2C 从设备子地址

我们知道,有一些 I2C 器件,除了器件自身的 I2C 地址SA外,其内部还有若干个单元可被访问,相应具有子地址(寄存器), 比较典型的是 EEPROM 存储器等,子地址可以是 1字节~N字节,主机可以发送数据来对子地址进行控制。下面我们来探讨两种情况:对从设备的寄存器写入数据和对读取从设备某些寄存器的值。

如下图所示, 主机先发送从机的 IIC 地址和写标记,接着紧跟寄存器的地址,然后跟着发送该寄存器的数据,完成对指定寄存器的写入操作。 在这里插入图片描述

如下图所示, 主机发送从机的 IIC 地址和写标记,然后发送所要读取寄存器的地址值,然后发起一次重启读操作,从设备回应数据,完成一次对从设备某个寄存器值的读取操作。 (值得说明的是,为什么要启动一次 Sr 重启操作呢?因为一次通信只能有一个方向,读或者写,若要转换方向,那必须重新发起) 在这里插入图片描述

六、参考资料

更多精彩内容,更多惊喜,请关注我的 CSDN 博客(嵌入式小散修),或者关注公众号《嵌入式小散修》在这里插入图片描述