I2C基础
一、I2C 的一些基础概念
1.1 I2C 是什么
I²C总线(Inter-Integrated Circuit)是由荷兰飞利浦半导体公司(在1982年开发的一种两线式串行通信协议。
恩智浦半导体(NXP Semiconductors)在2006年收购了飞利浦半导体,继续维护I2C总线技术。
I²C总线最初设计用于电视机内部芯片之间的通信,旨在简化布线并降低制造成本。
通过使用两根信号线(串行数据线SDA和串行时钟线SCL),它有效地减少了复杂电子系统中的连接复杂性。
初期的I²C总线支持标准模式,通信速率最高为100kHz。
随着技术的进步,逐步扩展为快速模式(400kHz)、快速增强模式(1MHz)、高速模式(3.4MHz)以及超快速模式(5MHz)。
为了提高抗噪声能力和通信效率,后续版本引入了差分信号和改进的总线仲裁机制。
飞利浦半导体公司放弃了对I²C技术的专利权,使其成为开放标准。这一举措促进了该技术在全球范围内的广泛应用。
合宙 780EPM 模组,支持两路I2C,并且有多组引脚都可以复用为 I2C 总线。
1.2 I2C 和 GPIO 的关系
I2C本质上也是一种 GPIO 的应用。
和 onewire 使用单总线不同的是, I2C 用了两个 GPIO 协作来通信。
I2C总线的两根信号线分别是 SCL 和 SDA。
SCL 和 SDA 都是配置成开漏输出模式的 GPIO,并通过上拉电阻,在所有主设备和所有从设备都不输出低电平的时候,SCL 和 SDA 都保持高电平。
SCL 保持高电平的状态,称为 SCL 被释放状态;
SDA 保持高电平的状态,称为 SDA 被释放状态。
采用了开漏输出+外接上拉电阻的模式,就满足了线与逻辑(WIRE-AND)。
线与逻辑是 I2C 通信的逻辑基础。
SCL 和 SDA 都是满足线与逻辑的。
线与逻辑导致的总线的状态如下(如下这三点要牢记,这是理解I2C通信的基础):
(1)所有设备都是开漏输出,所以要么拉低总线,要么保持高阻态;
(2)所有设备都释放总线(就是保持高阻态)的话,总线是高电平;
(3)只要有任何一个设备拉低总线的话,总线就是低电平。
1.3 I2C 的主从设备关系
1.3.1 主设备和从设备地址的数量
I2C 总线允许多个主设备同时存在,也允许多个从设备同时存在。
1.3.2 从设备的地址
每一个从设备,都有一个地址。
主设备在数据交换之前,先通过地址信息,实现跟特定从设备的通信。
从设备的地址有7bit 和 10bit两种表达方式。
用7bit 地址的方式,有效范围是 0x08 到 0x77 之间, 一共有 112 个有效地址;
用10bit 地址的方式,有效范围是 0x000 到 0x3FF,但需要排除以 11111XXX 开头的保留地址,实际可用的有效地址为 1008 个。
不同于 onewire 的主设备通过命令获取总线上的从设备地址, I2C 的地址,是在产品设计阶段事先协商好的,
从设备要在自己的存储器里面预先存好所以从设备的地址。
I2C 协议自身不支持向从设备分配地址,一些扩展协议(如 SMBus 的地址解析协议,ARP)或特定设计可以实现动态地址分配,
本文不介绍此类地址分配的内容。
1.4 SCL 和 SDA
I2C 系统通过 SCL 和 SDA 两根信号线进行通信。
SDA 负责告知对方传输的数据是 0 还是 1;
SCL 负责告知对方 SDA 上面的信号,哪个时序是有效信号,哪个时序的信号是可以忽略的。
1.5 I2C 总线系统的几个术语
I2C 总线系统的这几个术语,可以用来对齐接下来的话语体系。
1.5.1 发送方(Transmitter)
向总线发送数据的设备,称为发送方。
主设备和从设备,都能作为发送方。
1.5.2 接收方(Receiver)
从总线接收数据的设备,称为接收方。
主设备和从设备,都能作为接收方。
1.5.3 Controller
发起传输,终止传输,生成时钟信号的设备,称为控制器,也就是主设备。
1.5.4 Target
被控制器寻址的设备,称为目标设备,也就是从设备。
1.5.5 多主控(Multi-Controller)
I2C 总线支持多个主控。
多个主控试图在同一个I2C总线都发起通信的时候,通过仲裁机制,判断是哪个主控抢到总线控制权。
主设备也能够工作位从设备模式,从设备有地址,从而实现跟其他主设备的通信。
主设备是没有地址的,所以两个主设备是无法进行通信的。
1.5.6 仲裁(Arbitration)
当多个控制器试图都在总线发起通信的时候,仲裁机制确保同一时间只有一个控制器使用总线。
在本文第四章会介绍仲裁。
1.5.7 同步(Synchronization)
这里的同步,是指时钟同步。
通过线与逻辑实现的时钟同步,是实现仲裁的基础。
在本文第四章会介绍同步。
1.6 I2C 总线的通信速率
I²C 总线支持以下几种速率模式:
(1)标准模式 (Standard-mode, Sm): 100 kbit/s,双向传输;
(2)快速模式 (Fast-mode, Fm): 400 kbit/s,双向传输.
(3)快速模式增强版 (Fast-mode Plus, Fm+): 1 Mbit/s,双向传输.
(4)高速模式 (High-speed mode, Hs-mode): 3.4 Mbit/s,双向传输.
(5)超快速模式 (Ultra Fast-mode, UFm): 5 Mbit/s,仅支持单向传输,不兼容其他模式.
这些速率模式适应不同的应用需求,从低速到高速通信。
标准模式和快速模式是最常用的,因为它们的电路设计简单且成本较低,
而高速和超快速模式则适用于需要更高通信速度的场景。
合宙 Air780EPM 模组,支持标准模式,快速模式,快速模式增强版;
780EPM 不支持高速模式和超快速模式。
二、单个主设备和单个从设备的通信
2.1 通信的开始和结束
无论是主设备向从设备发送数据,还是从设备向主设备发送数据,全都是由主设备发起。
主设备通过发送 START 和 STOP 信号,来通知总线是开始通信还是终止通信。
主设备发起一个 START 信号,是通知从设备开始通信了;
主设备发起一个 STOP 信号,是通知从设备通信结束了,要等待下一个 START 才能开始通信。
START 信号和STOP信号的时序参见下图:
图1 START 和 STOP 信号
主设备作为控制器,在 SCL 高电平的时间段内,把SDA 信号从高拉低,就是通知所有从设备,通信要开始了,你们可以开始接收数据了。
主设备作为控制器,在SCL 高电平的时间段内,把SDA 信号从低拉高,这个动作,就是通知所有从设备,
通信要终止了,你们要等待下一个 START信号才能通信了。
这里的关键信息是,SCL保持高电平不变的同时, SDA 发生了电平变化。
SCL高+SDA电平变化,就是传输开始和结束的通信标志。
2.2 单个通信时隙-传输一个bit
在数据通信的状态, SCL 高电平状态的时间段内,SDA电平是恒定的,要么是高电平,要么是低电平。
SCL高+SDA高,就是代表逻辑1;
SCL高+SDA低,就是代表逻辑0.
SDA 的高电平和低电平的转换过程,必须是在 SCL 低电平的时候发生。
所以,在 SCL 高电平的时间段,SDA的电平是不能变化的。
读取数据的时候,要在 SCL 高电平的时候,才能够读取 SDA 的数据是0还是1.
下图是 I2C 总线做数据传输的时序过程:
图2 I2C 一个比特的通信过程
通过 SCL 和 SDA 两个信号线的配合,bit0 和 bit1 就比较清晰的传递给了对方。
所以,我们现在理解,SCL为什么称为时钟信号。
SCL 变化的快和慢,决定了 SDA 传输0和1的快和慢。
所以,平时所说的传输速率,说的就是 SCL 时钟信号的变化速率。
SCL高电平的变化速率是 1Mbps,就是SCL 信号在1秒钟内变化1M次,那么这个总线系统的速率就是 1Mbps。
SDA 信号的时序, 是严格跟着 SCL 的节奏变化的。
2.3 怎么传输多个字节
SDA线上每个字节是8个bit。
一次传输(START开始,STOP结束称为一次传输)可以发送的字节数不受限制。
每个字节(8bit)传输之后,必须跟着一个传输确认位(Acknowledge bit,简称为 ACK bit)。
传输字节时,要先传输最高有效位(MSB)。
下图展示了一个字节的通信时序:
图3 I2C 多个字节的传输过程
每一个8bit 的字节,都需要传输 9个bit 的通信时间片,额外多出来的第9个bit 是确认bit,称为 ACK。
在每个字节之后都需要有一个ACK 。
ACK 的作用是,允许接收方向发送方发出信号,表示该字节已成功接收,可以发送另一个字节。
ACK 的传输,跟普通数据bit 的传输一样,也是要在SCL高电平的时候有效。
2.4 理解确认信号(ACK和NACK)
2.4.1 ACK信号
ACK 信号定义如下:
发送器在 ACK 的时钟脉冲期间释放SDA线,以便接收器可以将 SDA 线拉低,从而产生ACK信号。
接收器要确保在SCL高的时间段,让SDA稳定保持低电平,便于控制器采集到 ACK 信号。
2.4.2 NACK 信号
当SDA在此第9个时钟脉冲,也就是 ACK 期间,保持高电平,被定义为 “NACK” 信号。
此时控制器可以有两种动作:
(1)发送 STOP 信号,中止传输;
(2)再次发送 START 信号,开始新的传输。
有五种情况会导致生成 NACK:
(1)总线上没有对应地址的接收器,因此没有设备可以响应确认;
(2)接收器无法接收或发送,因为它正在执行一些实时功能,还没有准备好与控制器开始通信。
(3)在传输过程中,接收方会收到它无法理解的数据或命令。
(4)在传输期间,接收方无法再接收任何数据字节。
(5)当前作为接收方的控制器必须向发射方的目标设备发出传输结束信号。
2.5 发送数据和接收数据的转换
I2C系统是通过在发送地址信息的时候,结合R/W方向位,实现发送和接收的转换。
2.5.1 一次实际的数据传输过程
一个实际的数据传输的过程是这样的:
(1)控制器发送START信号, 告知从设备通信开始;
(2)一个地址字节,其中前7位是目标从设备的地址,第8位是R/W位,代表下一个字节是从设备接收还是从设备发送;
R/W 位如果是0,表示是控制器发送数据;
R/W 位如果是1, 表示是控制器接收数据。
START之后的地址字节如下图所示:
图4 I2C 的地址字节
(3)跟当前的目标从设备数据传输完成后,控制器可以发送STOP终止本次通信,也可以再次发送 START 更换一个从设备地址,
继续其他的数据通信。
一个完整的通信过程如下图所示:
图5 I2C 的完整数据通信过程
2.5.2 主设备只发送不接收的通信过程
主设备作为控制器和发射器,向目标从设备发送数据。
传输方向不变,从设备只负责接收。
从设备作为目标接收器,需要对每个进行确认。
当从设备不确认产生 NACK 信号时,主设备可以发送 STOP 信号停止通信。
主设备也可以不需要NACK信号,主动发送 STOP 信号通知通信。
通信过程如图6所示:
图6 主设备只发送的通信过程
2.5.3 主设备只接收不发送的通信过程
主设备作为控制器,在发送第一个地址字节的时候,把 R/W位设置为读取,
这时候,主设备成为控制器+接收器的角色,从设备成为目标设备+发送器的角色,通信过程如图7所示:。
(1)控制器发送START信号;
(2)控制器发送第一个地址字节,R/W为1。该字节的 ACK 信号仍然由目标设备负责生成;
(3)后续的每个字节的 ACK,都由主设备,也就是控制器+接收器负责生成。
(4)如果控制器要终止通信, 最后一个字节生成 NACK 信号之后, 发送 STOP 信号终止通信。
图7 主设备只接收的通信过程
2.5.4 主设备和从设备交替发送的通信过程
主设备和从设备交替发送数据的过程,如图8所示。
在传输过程中改变方向时,主设备要重新再发起一次 START信号和地址字节,但
每次R/W位是相反的。
并且在发送START信号之前,最后一个字节的确认会是 NACK信号。
图8 主设备发送和接收交替的通信过程
这种交替发送的组合格式,经常被用于I2C接口的串行存储器的通信。
读取这类存储器的时候,必须是往存储器先写入一个字节之后,才能再读取数据。
所有的兼容 I2C 总线的从设备,在接收到 START 信号,或者是重复发送的 START 信号之后,都必须重置其总线逻辑,
以便它们都能顺利完成发送和接收。
2.5.5 单个主设备和多个从设备的通信
跟当前地址的目标从设备数据传输完成后,控制器可以发送STOP终止本次通信,换一个地址的从设备重新发起通信。
也可以不发送STOP信号,再次发送 START,更换一个从设备地址,继续其他的数据通信。
2.6 时钟拉伸
如果目标设备(从设备)在执行其他功能之前,无法接收或发送另一个完整的字节数据,
(例如目标设备正在处理内部中断),这时候目标设备(从设备)可以将 SCL 保持低电平,
迫使控制器进入等待状态。
当目标设备准备好接收下一个字节数据,并释放时钟线 SCL 时,数据传输恢复继续进行。
这种从设备拉低SCL迫使主设备等待的过程,称为 I2C 的时钟拉伸。
时钟拉伸给了从设备一个让主设备等待他的机会,可以让整个系统通信更稳定。
2.7 7bit地址和 10bit 地址的传送
截止到目前,本文讲解的都是 7bit 地址。
7bit 地址只能有 112个从设备,当从设备数量可能大于 112 个的时候,可以扩展为 10bit 地址,容纳 1008 个从设备。
具有7bit和10bit 地址的设备,可以连接到同一 I2C 总线,且在所有总线速度模式下都可以使用7位和10位寻址。
截止目前,10bit 寻址尚未得到广泛应用。
发送 10bit 地址的方法跟发送 7bit 地址一样,都是在 START 信号之后发送地址,不同的是,10bit 地址需要用2个字节发送。
其中第一个字节的前7个比特是1111 0XX,其中最后两个XX是10bit 地址的两个最高有效位(MSB);第一个字节的第8个比特是R/W,
用来确定消息的读写方向。
传输的过程如下图所示:
图9 往一个10bit地址的从设备发送数据
如果对10bit设备做读写交替的通信的话,时序如下图所示:
图10 往一个10bit地址的从设备发送和接收交替的过程
三、多个主设备和多个从设备的通信
对于I2C总线有多个主设备的场景,可能会存在多个从设备同时发送 START 信号发起通信的情况,这时候,就需要有个机制,
能够裁决出是哪个主设备抢到了总线,保证通信的稳定进行。
如果 I2C 总线,只有一个主设备作为控制器,你可以忽略这部分内容。
这个裁决机制,称为仲裁(Arbitration)。
在介绍仲裁之前,先要介绍时钟同步的概念。
3.1 时钟同步
图11 I2C 的时钟同步
如上图所示, 两个控制器同时发起通信的话,会造成两个控制器同时拉低SCL线的情况。
这样造成的结果就是,SCL 的低电平的持续时间,取决于拉低时间最长的那个控制器;
SCL 的高电平的持续时间,取决于释放时间最短的那个控制器。
3.2 仲裁
仲裁机制参见下图:
图12 I2C 的仲裁机制
多个控制器持续发送数据,当某个控制器发现 SDA 的电平,和自己认为的电平不一样的时候,就可以认为自己输掉仲裁了
需要马上释放 SDA 和 SCL 信号,如果有必要的话,还需要马上切换为从设备模式,方便其他控制器寻址到自己。
四、I2C 总线的典型电路
这是一个典型的 I2C 总线系统的电路图, SCL 和 SDA 都需要通过上拉电阻,在所有设备释放总线的时候,保持 SCL 和 SDA 为高电平。
图13 I2C 的典型电路
五、I2C 供电方式
I2C 不提供总线供电方式,主设备和从设备,都需要单独的电源供电。