目录
I2C简介
I²C(Inter-Integrated Circuit),中文应该叫集成电路总线,它是一种串行通信总线,使用多主从架构,是由飞利浦公司在1980年代初设计的,方便了主板、嵌入式系统或手机与周边设备组件之间的通讯。由于其简单性,它被广泛用于微控制器与传感器阵列,显示器,IoT设备,EEPROM等之间的通信。
I²C最重要的功能包括:
- 只需要两条总线;
- 没有严格的波特率要求,例如使用RS232,主设备生成总线时钟;
- 所有组件之间都存在简单的主/从关系,连接到总线的每个设备均可通过唯一地址进行软件寻址;
- I²C是真正的多主设备总线,可提供仲裁和冲突检测;
- 传输速度;
- 标准模式:Standard Mode = 100 Kbps
- 快速模式:Fast Mode = 400 Kbps
- 高速模式: High speed mode = 3.4 Mbps
- 超快速模式: Ultra fast mode = 5 Mbps
- 最大主设备数:无限制;
- 最大从机数:理论上是127;
这里要注意IIC是为了与低速设备通信而发明的,所以IIC的传输速率比不上SPI
I2C仅需两根线就可以支持一主多从或者多主连接,I2C使用两个双向开漏线,配合上拉电阻进行连接
I2C的物理层
IIC一共有只有两个总线: 一条是双向的串行数据线SDA,一条是串行时钟线SCL
- SDA(Serial data)是数据线,D代表Data也就是数据,Send Data 也就是用来传输数据的
- SCL(Serial clock line)是时钟线,C代表Clock 也就是时钟 也就是控制数据发送的时序的
所有接到I2C总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。I2C总线上的每个设备都自己一个唯一的地址,来确保不同设备之间访问的准确性。
IIC主要特点:
通常我们为了方便把IIC设备分为主设备和从设备,基本上谁控制时钟线(即控制SCL的电平高低变换)谁就是主设备。**
- IIC主设备功能:主要产生时钟,产生起始信号和停止信号
- IIC从设备功能:可编程的IIC地址检测,停止位检测
IIC的一个优点是它支持多主控(multimastering), 其中任何一个能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控。
支持不同速率的通讯速度,标准速度(最高速度100kHZ),快速(最高400kHZ)
SCL和SDA都需要接上拉电阻 (大小由速度和容性负载决定一般在3.3K-10K之间) 保证数据的稳定性,减少干扰。
IIC是半双工,而不是全双工 ,同一时间只可以单向通信
为了避免总线信号的混乱,要求各设备连接到总线的输出端时必须是漏极开路(OD)输出或集电极开路(OC)输出。这一点在等下我们会讲解
IIC的高阻态
漏极开路(Open Drain)即高阻状态,适用于输入/输出,其可独立输入/输出低电平和高阻状态,若需要产生高电平,则需使用外部上拉电阻
高阻状态:高阻状态是三态门电路的一种状态。逻辑门的输出除有高、低电平两种状态外,还有第三种状态——高阻状态的门电路。电路分析时高阻态可做开路理解。
我们知道IIC的所有设备是接在一根总线上的,那么我们进行通信的时候往往只是几个设备进行通信,那么这时候其余的空闲设备可能会受到总线干扰,或者干扰到总线,怎么办呢?
为了避免总线信号的混乱,IIC的空闲状态只能有外部上拉, 而此时空闲设备被拉到了高阻态,也就是相当于断路, 整个IIC总线只有开启了的设备才会正常进行通信,而不会干扰到其他设备。
数据传输协议
主设备和从设备进行数据传输时遵循以下协议格式。数据通过一条SDA数据线在主设备和从设备之间传输0
和1
的串行数据。串行数据序列的结构可以分为:
- 起始位
- 地址位(7bit或者10bit)
- 读写位(1bit)
- 应答位(1bit)
- 数据位+应答位(数据位8bit;应答位1bit;数据+应答可以重复传输多次,直到遇到停止位)
- 停止位
起始位
当主设备决定开始通讯时,需要发送开始信号,需要执行以下动作;
- 先将SDA线从高压电平切换到低压电平;
- 然后将
SCL
从高电平切换到低电平;
在主设备发送开始条件信号之后,所有从机即使处于睡眠模式也将变为活动状态,并等待接收地址位。
起始位由主机发送
具体如下图所示;
地址位
地址位支持7bit、10bit,主设备如果需要向从机发送/接收数据,首先要发送对应从机的地址,然后会匹配总线上挂载的从机的地址;
地址位由主机发送
读写位
该位指定数据传输的方向;
- 如果主设备需要将数据发送到从设备,则该位设置为
0
; - 如果主设备需要往从设备接收数据,则将其设置为
1
。
读写位由主机发送;1表示读操作,0表示写操作
应答位
应答位包含两种,
- ACK:从机正确收到数据或地址+读写位
- NACK:从机未应答,工作异常
主机每次发送完数据、发送完读写位,之后会等待从设备的应答信号ACK
;
- 如果从设备发送应答信号
ACK
,则SDA
会被拉低; - 若没有应答信号
NACK
,则SDA
会输出为高电平,这过程会引起主设备发生重启或者停止;
应答位由从机发送到SDA;应答时时钟由主机发送;
0表示ACK,1表示NACK;
数据块
一次传输的数据总共有8位,由发送方设置,它需要将数据位传输到接收方。
发送之后会紧跟一个ACK
/ NACK
位,如果接收器成功接收到数据,则从机发送ACK。否则,从机发送NACK。
数据可以重复发送多个,直到接收到停止位为止。
停止位
当主设备决定结束通讯时,需要发送结束信号,需要执行以下动作;
- 先将SDA线从低电压电平切换到高电压电平;
- 再将SCL线从高电平拉到低电平;
下图为完成I2C时序图
多主机仲裁
在多主的通信系统中。总线上有多个节点,它们都有自己的寻址地址,可以作为从节点被别的节点访问,同时它们都可以作为主节点向其他的节点发送控制字节和传送数据。但是如果有两个或两个以上的节点都向总线上发送启动信号并开始传送数据,这样就形成了冲突。要解决这种冲突,就要进行仲裁的判决,这就是I 2C总线上的仲裁。
I2C总线上的仲裁分两部分:SCL线的同步和SDA线的仲裁。
SCL线的同步(时钟同步)
SCL同步是由于总线具有线“与”的逻辑功能(开漏输出),即只要有一个节点发送低电平时,总线上就表现为低电平。当所有的节点都发送高电平时,总线才能表现为高电平。正是由于线“与”逻辑功能的原理,当多个节点同时发送时钟信号时,在总线上表现的是统一的时钟信号。这就是SCL的同步原理
SDA仲裁
SDA线的仲裁也是建立在总线具有线“与”逻辑功能的原理上的。节点在发送1位数据后,比较总线上所呈现的数据与自己发送的是否一致(类似于CAN总线的回读机制)。是,继续发送;否则,退出竞争。SDA线的仲裁可以保证I2C总线系统在多个主节点同时企图控制总线时通信正常进行并且数据不丢失。总线系统通过仲裁只允许一个主节点可以继续占据总线
仲裁过程
上图是以两个节点为例的仲裁过程。DATA1和DATA2分别是主节点向总线所发送的数据信号,SDA为总线上所呈现的数据信号,SCL是总线上所呈现的时钟信号。当主节点1、2同时发送起始信号时,两个主节点都发送了高电平信号。这时总线上呈现的信号为高电平,两个主节点都检测到总线上的信号与自己发送的信号相同,继续发送数据。第2个时钟周期,2个主节点都发送低电平信号,在总线上呈现的信号为低电平,仍继续发送数据。在第3个时钟周期,主节点1发送高电平信号,而主节点2发送低电平信号。根据总线的线“与”的逻辑功能,总线上的信号为低电平,这时主节点1检测到总线上的数据和自己所发送的数据不一样,就断开数据的输出级,转为从机接收状态。这样主节点2就赢得了总线,而且数据没有丢失,即总线的数据与主节点2所发送的数据一样,而主节点1在转为从节点后继续接收数据,同样也没有丢掉SDA线上的数据。因此在仲裁过程中数据没有丢失。
总结:SDA仲裁和SCL时钟同步处理过程没有先后关系,而是同时进行的。
I2C死锁
在实际使用过程中,I2C比较容易出现的一个问题就是死锁
死锁的产生常见的有两种情况:
- 一种是从设备在回复ACK时主设备异常复位;
- 另一种是从设备在回复数据位是0的时候主设备异常复位。
两种情况的相同点都是主设备异常复位时SDA处于被从设备拉低状态,而主设备复位后SCL处于高电平状态(空闲状态)。此时从设备会等待主设备拉低SCL取走ACK或者数据位,而主设备会等待从设备释放SDA线。主设备和从设备互相等待,隔空对望,进入死锁状态。
解决死锁问题的几种常见方法:
- 主设备在检测到SDA被拉低超过一段时间后,主动复位从设备从而使之释放SDA。这种方法的前提是从设备有复位引脚,MCU可以控制从设备的复位引脚使之复位。
- 主设备在检测到SDA被拉低超过一段时间后,推送9个Clock到时钟总线上,取走从设备的ACK位从而使从设备释放SDA为高电平。
- 在主从设备之间串联一个I2C缓冲器,该缓冲器可以自动检测死锁状态。当检测到死锁时会主动断开与主设备的连接,并发送9个Clock给从设备,等从设备释放SDA线后从新与主设备建立连接。
I2C的死锁问题无法从根本上避免,除了MCU的异常复位导致I2C死锁,从设备在正常通信过程中也有可能异常拉低SDA导致死锁。所以软件在设计时要考虑当死锁发生时要能够从死锁中恢复,使得I2C通信可以继续进行。
时钟扩展
什么是I2C时钟延展(SCL Stretching)?在I2C的主从通讯过程当中,总线上的SCL时钟总是由主机来产生和控制的,但若是从机跟不上主机的速率,I2C协议规定从机是能够经过将SCL时钟线拉低来暂停一个传输的,直到从机释放掉SCL线,传输继续进行。
clock Stretching为从机可选配置,如果不使能,则从机无法控制SCL;如果使能,则从机可通过将SCL强行拉低,来降低传输速度,SCL拉低期间,主机只能等待从机释放SCL。
Repeat Start
有时master需要在一次通信中进行多次消息交换(例如与不同的slave传输消息,或切换读写操作),并且期间不希望被其他master干扰,这时可以使用“重复开始条件”-----在一次通信中,master可以产生多次start condition,来完成多次消息交换,最后再产生一个stop condition结束整个通信过程。由于期间没有stop condition,因此master 一直占用总线,其他master无法切入。