这是 北航士谔书院 的第 940 篇推送
北航士谔书院X大班提醒您:
道路千万条,学习第一条
不搞单片机,开学两行泪
——新春快乐,我们又回来了!
本文对 I²C 总线的协议做出详细的介绍,并对其在 51 单片机上的应用代码做出解析。
I²C 总线
集成电路间总线(Inter-Integrated Circuit Bus,I²C Bus,读做 I-squared-C 或 I 方 C)是一种连接多个集成电路的总线。它由 Philips Semiconductors(现 NXP Semiconductors)于 1982 年开发。
I²C 总线的特点
多对多。在单个 I²C 总线上,可以有多个主设备(Master Device)和多个从设备(Slave Device)。主设备通常是单片机,而从设备通常是简单的外围设备(如传感器、单色显示屏),不过从设备也可以是单片机。通信总是由主设备发起并主导。通常我们仅在 I²C 总线上安排单个主设备,本文也只讨论有单个主设备的情形。如果存在多个主设备,那么它们需要进行较复杂的时钟同步和使用权仲裁,在此暂不讨论。
简单、易实现。I²C 总线仅需两个引脚就可连接多达 112 个设备,而同类总线,如 SPI 等,则需要更多的引脚。I²C 协议简单直接,不需要复杂的逻辑。
低速。大多数 I²C 设备仅支持在 100 kbit/s 的标准模式(Standard Mode)工作;少数设备最高支持 1Mbit/s 的快速模式+(Fast Mode Plus)。比起其它总线,I²C 的速度是比较慢的。
短距离。I²C 允许的走线距离较短,它通常被用于同一块 PCB 板上的 IC 间互联。I²C 总线不适用于长距离传输。
I²C 总线的常见应用
I²C 总线通常被用于将低速的外围设备通过短距离的线路连接到微处理器(单片机)上。常见的外围设备有温度传感器、电流电压传感器、单色显示屏等。这些设备结构简单,且传输的数据量很少,因此适用 I²C 总线。需要较高传输速度的设备(如高分辨率彩色显示屏)通常使用更高速度的连接方式(如 SPI)。
I²C 总线的引脚组成及电气连接
一个 I²C 总线由两条总线(Serial Clock, SCL 和 Serial Data, SDA)组成。I²C 总线上的设备都直接连接到这两个总线上(如图所示)。
I²C 总线的连接方式。μC 即单片机
所有连接到 I²C 总线的设备均使用开漏(Open-Drain,OD)连接。每个 I²C 设备的电路可以简化为如下图的结构:
开漏连接
可以将每个 P 沟道 MOSFET(MOSFET-P)想象为由单片机内部端口控制的“开关”:
开关
可以观察到,如果 I²C 总线上只连接了设备,那么 I²C 总线不可能处于高电平(因为此时总线没有连接到电源 Vdd)。我们需要在 SDA、SCL 与 Vdd 间各增加一个上拉电阻(如上图 Rp),当“断开开关”时,可以得到高电平;当“合上开关”时,可以得到低电平。
完整的连接示意图
在下文中,我们将合上开关(使相应总线处于低电平)的动作称为“拉低”;断开开关的动作称为“释放”。由于所有设备都并联在总线上,所以若总线上有任意设备拉低总线,总线即处于低电平状态;只有当总线上的所有设备释放总线时,总线才能处于高电平状态。这就是所谓的 Wired-And。
I²C 通信协议概要
空闲状态
I²C 总线处于空闲状态时,所有设备都释放总线,SCL 与 SDA 均处于高电平状态。
起始条件
I²C 总线上的通信总是由主设备(Master)发起。当主设备希望通信时,它就会产生一个起始条件(Start Condition,S),作为开始通信的信号。
起始条件可以描述为:当 SCL 处于高电平时,SDA 由高电平向低电平转换。即,在 I²C 总线空闲状态下,主设备拉低 SDA,代表起始条件,开始一次通信。
帧
在 I²C 协议中,传输总是以帧(frame)为单位进行的。一帧为 8bit,即一字节。主设备和从设备都可以发送帧。
在发送帧时,发送方会逐位 (bit) 发送一字节 (byte) 数据,且先发送最高位(most significant bit,MSB)。例如,如果发送方需要发送 183 = 10110111,则按 1,0,1,1,0,1,1,1(从左到右)的顺序发送。发送一位数据的过程如下:
主设备首先将 SCL 拉低。
发送方(主或从)在检测到 SCL 被拉低后,使 SDA 处于相应的电平:如果要发送 0,就拉低 SDA;如果要发送 1,就释放 SDA。
主设备等待一定的时长后,释放 SCL;此时发送方不改变 SDA 状态。
接收方在 SCL 为高电平时,读取 SDA 的状态,得到相应数据并存储下来。
发送完一位后,主设备再次拉低 SCL,进入下一个循环,发送方发送下一位数据,接收方读取下一位数据。如此循环 8 次,即完成发送一帧。
在发送完一帧的 8 字节后,主设备会将 SCL 再拉低一次。接收方在检测到 SCL 第 9 次被拉低后:
如果接收当前帧成功,则会将 SDA 拉低,表示自己成功收到了数据,这称作一个 ACK 信号(acknowledgement signal)。
如果没有成功接收当前帧,则在 SCL 为低电平时,接收方不会作出任何动作,而使 SDA 保持在释放状态,这称作一个 NACK 信号(not acknowledgement signal)。NACK 信号并不是“主动发出”的,只要接收方没有作出任何反应,就代表一个 NACK 信号。
如果总线上没有任何设备,或者相应的接收方没有正常工作,则发送方会收到一个 NACK。
I²C 帧的传输流程
可以观察到,在传输帧时,SDA 仅在 SCL 为低电平时发生变化。如果当 SCL 为高电平时 SDA 发生变化,则会构成起始条件或停止条件。
停止条件与重复起始条件
在传输完一帧后,主设备可以选择继续传输帧,也可以选择停止传输,还可以选择从头开始一次新的传输。
如果它希望停止传输,则需要产生一个停止条件(Stop Condition,P),其可以描述为:当 SCL 处于高电平时,SDA 由低电平向高电平转换。
如果它希望从头开始新的传输,则需要产生一个重复起始条件(Repeated Start Condition,Sr)。重复起始条件与起始条件是相同的。
起始条件和停止条件
SCL、SDA 名称的含义
有同学可能会对 Serial Clock 和 Serial Data 名称的含义感到不解。
SCL 总是由主设备控制,且它以几乎固定的频率切换,因此它被称作 clock。SDA 则负责传输数据,因此被称作 data。
Serial 的含义是“串行”,即同一时间只能发送一位(one bit),而要传输的许多位数据“排队”被传输。与“串行”(serial)相对应的是“并行”(parallel)。并行总线通常由多根数据线组成,它一次能够发送多位数据。并行总线看似效率更高,但实际上它面临电平问题和串扰问题。
目前的计算机板卡互联协议中,串行协议占据统治地位。PCI-E、SATA 等都是串行传输的。一些较老的传输协议是并行协议,如 AGP、PCI 和 IDE。有关串行和并行传输方式的更多内容,可以参见这个知乎问题。
I²C 从设备地址
每个 I²C 从设备均有一个(在单个总线上)独一无二的 7 位从设备地址(slave address),该地址由设备厂商决定,不过有时也可以由用户自行定义其中的某些位,以允许在同一个 I²C 总线上同时存在相同的多个设备。具体的地址可以在芯片数据手册中找到。
通常在从设备地址后会附加一个数据方向位(data direction bit),一共 8 位数据,构成一个完整的帧。通常数据方向位为 0 时表示主设备发送、从设备接收,称为 WRITE;数据方向位为 1 时表示主设备接收、从设备发送,称作 READ。
以蓝桥杯开发板 CT107D 上的 PCF8591 芯片为例。该芯片是一个具有 I²C 功能的模数转换芯片(Analog to Digital Converter,ADC),用于将模拟信号(analog signal,如通过光敏电阻的电流)转换为数字信号(digital signal,由具体二进制表示的电压大小),相当于一个电压表(将电压转换为具体的读数)。
PCF8591 完整脚位图
在 PCF8591 数据手册 8.1 Addressing 一节及 Table 5, 6 中,我们可以找到有关芯片地址的详细信息。
如表格所示, PCF8591 的地址为 1001xxx,其中最后 3 位由 A2 – A0 脚(即脚位图中的 5 – 7 脚)决定。如果相应的脚为低电平,则对应的位为 0;否则对应的位为 1。例如如果这三个脚都是高电平,则芯片的地址是 1001111。
一次完整的 I²C 传输
主设备产生起始条件,代表一次通信的开始。
主设备发送一帧,表示需要通信的从设备地址和数据方向位。如果相应地址的从设备存在,则从设备将 SDA 拉低,发出 ACK 信号;如果没有相应地址的从设备存在,则主设备会收到 NACK 信号。
主设备和从设备以帧为单位进行通信;除最后一帧外,每帧传送完后,接收方需发送 ACK 信号以确认。具体的通信过程需要参照相应设备的数据手册,具体细节一般在数据手册的 Functional description 中。PCF8591 数据手册的第 8 节即为 Functional description。
在最后一帧传送完后,接收方不发出 ACK,此时主设备作出以下动作:
若希望与其他从设备通信,则产生一个重复起始条件,然后继续进行第 2 步;
若希望停止通信,则产生一个停止条件。产生停止条件后,两条数据线均被释放,I²C 总线进入空闲状态。
接下来我们以 PCF8591 和 51 单片机为例,看看如何使用 I²C 总线通信。
(未完待续)
图文|田韵豪
排版|李亦龙
出品|士谔书院X大班