电子说
1、I2C Introduction
1、I2C 历史
I2C:Inter-Integrated Circuit,集成电路总线。
I2C 是 Philips 公司在 1982 年为主机板、嵌入式系统(短距)设计的一种简单、双向二线制同步串行总线。
Philips 半导体事业部就是现在的 NXP。
I2C 的专利在 2006 年 11 月 1 日已到期,大家可以免费使用。
Intel 1995 年推出的 I2C 兼容总线(System Managerment Bus),即 SMBus 或 SMB
最新版本 I2C spec v.6 于 2014.04.04 推出。
2、I2C 的未来
MIPI 协会在 2014 年左右定稿了 I3C (improved Inter Integrated Circuit)规范,I3C 在 I2C 的规格上建立了功能超集,支持高传输速率模式。
当前不论是 Soc 厂商,还是 device 厂商,都已经开始或正在向 I3C 过度。
I3C spec 有 2016 版本、2018 版本,最新的是 2021 版本(446页)。
3、I2C 的速度
I2C 读法:“I方C”、“I-squared-C”、"I two C"
I2C 是一种低速、串行总线,有 SDA(串行数据线) 和 SCL(串行时钟线) 两条信号线,半双工通信。
通信速度如下:
• Bidirectional bus:
Standard-mode (Sm), 100 kbit/s
Fast-mode (Fm), 400 kbit/s,用在 sensor、carema、touch 等。
Fast-mode Plus (Fm+),1 Mbit/s
High-speed mode (Hs-mode),3.4 Mbit/s,用在 NFC、buck&boost 等
• Unidirectional bus:
Ultra Fast-mode (UFm),5 Mbit/s
速度由 SCL 决定,不同模式对上升沿的要求不一样,上升沿斜率受上拉电阻和等效电容影响。
4、I2C 是一种多主从架构总线
I2C 的读写均由 master 端发起。
I2C 通信的每一个 byte(8bits)都需要 slaver 端的回应 ACK/NACK 作为回应。
多 master 端需要引入仲裁机制。
slaver 端通过设备地址区分,有 7bits 和 10 bits 等地址,还有一种 8bits 地址,实际上是 7bits + 读写位。【其中7位地址 = 种类型号(4bit)+ 寻址码(3bit)】
5、I2C 总线能挂多少设备?
7-bit address :2 的 7 次方,能挂 128 个设备。
10-bit address :2 的 10 次方,能挂 1024 个设备。
但是 I2C 协议规定,总线上的电容不可以超过 400pF。管脚都是有输入电容的,PCB上也会有寄生电容,所以会有一个限制。实际设计中经验值大概是不超过 8 个器件。
总线之所以规定电容大小,是因为 I2C 使用的 GPIO 一般为开漏结构,要求外部有电阻上拉,电阻和总线电容产生了一个 RC 延时效应,电容越大信号的边沿就越缓,有可能带来信号质量风险(方波变三角波)。传输速度越快,信号的窗口就越小,上升沿下降沿时间要求更短更陡峭,所以 RC 乘积必须更小。(可以理解为输出高电平就是给电容充电,电容越大,充电越慢)
注意,要把 spec 规定的预留设备地址去除,保留地址如下:
note:写的是 two groups,而不仅仅是八个,0000 XXX 和 1111 XXX 系列地址都是保留的。
note:注意 1111 1XXX 是 Hs-mode master code,1111 0XXX 是 10-bit slave addressing,博主后面会讲。
6、定义术语
2、I2C Architecture
I2C 采用的 GPIO 一般为开漏模式,支持线与功能,但是开漏模式无法输出高电平,所以需要外部上拉。Vdd 可以采用 5V、3.3V、1.8V 等,电源电压不同,上拉电阻阻值也不同。
一般认为 I2C 总线上,低于 0.3Vdd 为低电平,高于 0.7Vdd 为高电平。
I2C 协议中每个挂到总线上的设备都有独一无二的静态设备地址。
空闲时,I2C 总线上两根线都是高电平,因为有上拉电阻。
1、推挽结构和开漏结构
1、推挽结构:使用两个三极管或 MOSFET,以推挽方式存在于电路中。电路工作时,两只对称的开关管每次只有一个导通,所以导通损耗小、效率高。既可以向负载灌电流,也可以从负载抽取电流。推拉式输出级既提高电路的负载能力,又提高开关速度。
图中上面是 NPN 型三极管,下面是 PNP 型三极管。分别有以下两种情况:
输出高电平:向负载灌电流。
输出低电平:从负载拉电流。
2、开漏结构(OD):对比推挽结构,开漏结构只有一个三极管或者MOS管。
之所以叫开漏,是因为 MOS 管分为三极:源极、栅极、漏极。漏极开路输出,所以叫开漏;如果是三极管:基极、集电极、发射极,集电极开路,所以叫开集输出(OC)。
开集输出,NPN 三极管:
Vin 高电平,三极管导通,对外输出低电平,外部被直接拉到低。
Vin 低电平,集电极(C)开路,输出电平状态由外部决定。
以上分析均采用三极管,MOS 管类似。
因此,推挽结构可以输出高低电平。开漏输出只能输出低电平,高电平由外部电路决定。
2、线与功能
线与:所有 GPIO 输出高就是高,只要有一个输出低,整条线上面的都是低,这就是“与”的意思。
1、推挽结构下,两个 GPIO 口连接到一根线上,假如左边的 PMOS 导通,右边的 NMOS 导通,Vdd 就会通过两个 MOS 管直接接地,由于 MOS 管导通电阻不大,会导致电流很大,直接损坏这两个 GPIO口,因此,推挽输出不支持线与。
note:实际上并不一定是上面 NMOS 下面 PMOS,只要上下两个管子采用不同类型,即可保证同一时刻只有一个管子导通,即可分别输出高低电平。
2、开漏结构:假如很多 GPIO 是开漏结构,接到了一根线,如下图。开漏结构输出的高电平靠外部上拉,假如有一个 GPIO 接地,那么电流会通过上拉电阻流进地,因为有上拉电阻的存在,所以电流不大,不会损坏 GPIO 口。
线与,是 I2C 协议的基础!
小节
mode | open-drain | push-pull |
---|---|---|
speed | slower | fsater |
power | higher | lower |
slave clock stretching | yes | not supported |
power 功耗上,开漏因为上拉电阻的存在,每次高低电平变换都会消耗能量,因此功耗高。
clock stretching 时钟延展方面,开漏支持时钟延展,推挽结构不支持时钟延展。原因和上面的推挽不支持线与一样的。有的人会有疑问,时钟延展不是在 SCL 低电平时,从设备去拉 SCL 线吗?不应该有问题呀。但如果是推挽 GPIO,此时主控会尝试拉高 SCL ,才会发现 SCL 被从设备拉低,这时候就会短路。
再次提醒,线与:当总线上只要有一个设备输出低电平,整条总线便处于低电平状态,这时候总线被称为占用状态。
3、上拉电阻计算
1、上拉电阻过小,电流大,端口低电平 level 增大,会发现总线上电平拉不到 0V。
2、上拉电阻过大,上升沿时间增大,方波可能会变成三角波。
因此计算出一个精确的上拉电阻阻值是非常重要的。计算上拉电阻的阻值,有明确计算公式:
最大电阻和上升沿时间 tr 、总线电容 Cb 、标准上升沿时间 0.8473 有关。
最小电阻和电源 Vdd 电压、GPIO 最大输出电压 Vol、 GPIO 最大电流 Vol 有关。
查《I2C-bus specification and user manual.pdf》7.1节:
查《I2C-bus specification and user manual.pdf》表10:
从上图可以得到最大电阻和最小电阻计算公式以及如下数据:
1、标准模式:0~100KHz,上升沿时间要求 tr = 1us
2、快速模式:100~400KHz,上升沿时间要求 tr = 0.3us
3、高速模式:up to 3.4MHz,上升沿时间要求 tr = 0.12us
note:该上升沿时间 tr 是 0.3Vdd 到 0.7Vdd 的时间要求。
假设:Vdd 是 1.8V,Cb 总线电容 200pF(虽然协议规定负载电容最大 400pF,实际上超过 200pF波形就很不好,我们以 200pF 来计算,实际大家使用时建议以 100pF 计算)
标准模式 :
快速模式:
高速模式:
最小电阻(Vdd越大,上拉电阻就要越大):
注意,高速模式下,电源电压一般采用 1.8 V,不会采用 3.3V,因为如果用 3.3V 计算你会发现最小电阻比最大电阻大。
采用合适的电源电压和合适的上拉电阻,才会让你的 I2C 传输信号最优。
大家在不同速率采用的电阻一般有以下几种:1.5K、2.2K、4.7K。
上拉电阻关系图
3、I2C Transfer
0、Definition of timing
想要深入探讨 I2C 协议,必须深刻理解各种时间的定义,如下为 F/S-mode
建立时间(Tsu):时钟上升沿到来之前,输入端数据已经到来并稳定持续的时间间隔。
保持时间(Thd):时钟上升沿到来之后,输入端数据继续保持稳定并持续的时间间隔。
标识符 | 定义 |
---|---|
tf | 信号下降时间 |
tr | 信号上升时间 |
tLOW | 信号低电平时间 |
tHIGH | 信号高电平时间 |
tHD;DAT | 数据保持时间 |
tSU;DAT | 数据建立时间 |
tSP | 输入滤波器必须抑制的毛刺脉宽 |
tBUF | 启动和停止条件的空闲时间 |
tHD;STA | 重复起始条件的保持时间 |
tSU;STA | 重复起始条件的建立时间 |
tSU;STO | 停止条件建立时间 |
Sr 重新启动,S 启动,P 停止。
如上参数在 spec 中有严格规定,可查表,一般 standard mode 和 Fast mode 在一起,Hs mode 单独列,表4、表5、表6、表7:
Master
提供时钟 SCL
开启和停止数据传输
寻址其他设备
slave
被主设备寻址
1、数据有效性
在 SCL 高电平期间,SDA 必须稳定,所以一般情况下,SCL 高电平宽度小,SDA 高电平宽度大,用示波器看也是这样的。
2、起始条件和停止条件
起始条件:SCL 高电平时,SDA 由高变低。
停止条件:SCL 高电平时,SDA 由低变高。
note:因为 SCL 和 SDA 两根线有上拉电阻,因此空闲时两根线为高电平。因此,START 条件一定是某条线拉低,spec 规定是 SDA 线拉低为开始条件。这也是开始条件和停止条件不能互换的原因。(至于为什么不是 SCL 线拉低为开始条件,大家看到后面会理解)
byte format
传输长度必须是一个字节(8 bit)
每次传输的字节不受限制
数据必须以 MSB 开头进行传输,也就是先传输最高位
从机可以将时钟线 SCL 保持在低位,迫使主机进入等待状态。
在 ACK 后,从设备可以拉低 SCL 线进行时钟延展(比如从设备需要准备数据等)
note:SCL 高电平的时候,SDA 开始采样,SDA 是高就是 1,是低就是 0。SCL 低电平期间,SDA 变换数据。不可以在 SCL 高电平期间变换数据,否则会认为是 起始和停止条件。
3、ACK or NACK
每次传输完一个字节以后,从设备要进行一个回应,回应 ACK 或者 NACK。
ACK :在传输 8 bit 以后,在第九个 bit ,SCL 高电平,如果 SDA 是低电平,说明回应了 ACK。
NACK:在传输 8 bit 以后,在第九个 bit ,SCL 高电平,如果 SDA 是高电平,说明回应了 NACK。
spec 规定以下五种情况会出现 NACK
主机发送到总线上的地址,却没有匹配的从机,因此出现 NACK
从机处于 busy 状态,出现 NACK
在传输过程中,从机获取其不理解的数据或命令。
在传输过程中,从机无法再接收任何数据字节。
主接收机必须向从发射机发送传输结束的信号的时候,会出现 NACK。
4、write data
主机向从机写数据,在通信结束的最后一个字节,正常从机都会回应一个 ACK ,告诉主机最后一个字节写成功,这时候主机会产生 STOP 信号。
如果最后一个字节从机回应一个 NACK ,主机也会产生一个 STOP 信号,并且这时候主机会向上层上报一个 ACK error 。
上层如何处理,是上层的事情,芯片设计时 I2C 外设控制器一定会在这个时候产生一个 ACK error。如果用的是 Linux 操作系统,可以配置在上层忽略最后的这个 ACK error 。
5、read data
主机从从机读数据,在最后一个字节后,主机会给从机一个 NACK ,告诉从机不再读数据了,然后主机产生一个 STOP 信号。这是唯一一个在正常传输过程中的 NACK
6、复合格式
在重复开始信号 Sr 前后,两个 slave address 可以不同。也就是说,一个 I2C 主机可以不产生 STOP 信号,直接产生一个重复开始信号去访问另外一个从机。(如果 I2C 总线上有多个主机,则不用再一次仲裁,节省时间)
另外,在 Linux 系统中,由于 i2c_msg 结构体的规定,单笔 I2C 传输最大 64KB,超过 64KB 也要再来一次 STOP 信号或者 重复开始信号。
7、I2C Transfer Regulation
以 START 条件开始
以 STOP 条件结束
传输的第一个字节为 7bit 从机地址 + 1bit 读写位
每个总线上的设备都会比较 STRAT 信号后面的 7bit 地址与自己的地址是否匹配
每个 byte(8 bits) 后面都会有 ACK 或者 NACK
在 START 信号或者 repeated START 信号后,从机必须重置自己的总线逻辑
一个 START 后面紧跟着一个 STOP 信号,是非法格式
主机 master 可以不产生 STOP 信号,而是直接产生一个 repeated START 信号+另外一个设备地址,直接开始访问另外一个设备
8、10-bit addressing
10 位从机地址规定如下,其中 11110 为 10 位地址的指示信号,A9-A0 表示 10bits 地址:
主机向从机写数据(需要 2 bytes)
主机从从机读数据(需要 3 bytes)
9、示波器波形图示例
主机向从机写数据
上图中,大家会在 SDA 线上发现有三个很细的毛刺,每次都是出现在从机回应了 ACK 以后。这是由于从机拉低 SDA 线回应 ACK 后,释放了 SDA 线,因为有上拉电阻的存在,SDA 线被拉高,然后主机又立刻接管了 SDA 线,把 SDA 线拉低。即该毛刺是由于 slave 和 master 换手有时差导致的。
因为该毛刺是出现在 SCL 低电平期间,而 SCL 低电平期间,SDA 本来就可以变换数据,所以不会对 I2C 通信产生负面影响,该毛刺一般不用关注。
如果觉得波形不美观,可以找芯片原厂,看能否调整 master 控线的 setup time 和 hold time ,来减小该毛刺的幅值。
主机从从机读数据
10、补充
I2C 不支持从设备在 SCL 和 SDA 总线上发起一个中断,通知主设备来读数据。有中断需求的从设备需要额外接一根中断线,通知主控数据已经准备好,让主控发起读数据的操作。
这无疑增加了系统复杂性,多占用了 pin 脚。I3C 则不存在这种问题,I3C 允许从设备在 SCL 和SDA 上发起中断,叫“带内中断”,I3C 后面会讲。
4、I2C Synchronization And Arbitration
三个概念:时钟延展、同步、仲裁
1、Clock stretching 时钟延展
时钟延展:通过将 SCL 线保持在低电平来暂停传输。在 SCL 再次拉高之前,传输无法进行。
从机通过将 SCL 线拉低,强制主机进入等待状态。
时钟延展功能是可选的,非必须。
byte level
时钟延展导致需要更多时间来存储接收到的字节或准备另一个要传输的字节
bit level
通过延长每个时钟低电平周期来降低总线时钟。任何主机的速度都与该设备的内部运行速度相适应。
在 Hs mode,只能使用 byte level,也就是只能在传输完一个字节(8bits)后拉低 SCL 进行时钟延展。在 Standard-mode 和 Fast-mode,既可以 byte level 也可以 bit level,bit level 意思是哪怕你之传输了 2 bits ,从机也可以拉低 SCL 线进行时钟延展,临时暂停传输。
时钟延展通俗解释
I2C 主设备始终控制着时钟线 SCL,不论是往设备写还是从设备读。一般情况下,如果操作对象是 EEPROM 或者其他简单设备而言,无所谓,但是,如果从设备是处理器,在接到主机命令后要去处理一些运算然后得出结果返回给主机。这个时候可能造成来不及处理。怎么办?这时,从设备会主动控制时钟线把它拉低!直到数据准备好之后再释放时钟线,把控制权交还给 MASTER。这也是 I2C 通信系统中,从机唯一能控制总线的时候!
关键是很多 I2C 主机不支持 clock stretching 功能,所以,无法和带有 clock stretching 功能的从机通信!所以,各位在选择主机器件之前,必须要注意这一点,不然整个设计方案可能报废,影响很大。
2、Synchronization And Arbitration
I2C 是多主从架构,也就是一条总线上可以同时挂多个 I2C 主机和多个 I2C 从机。
但是如果有两个或两个以上的主机同时向总线上发送启动信号并开始传送数据,这样就形成了冲突。要解决这种冲突,就要进行仲裁的判决,这就是 I2C 总线上的仲裁。
I2C 总线上的仲裁分两部分:SCL 线的同步和 SDA 线的仲裁,这两部分没有先后关系,是在同时进行。
SCL Synchronization
所有主机都在 SCL 线上输出自己的时钟,因此同步过程需要定义自己的时钟。
SCL 同步是由于总线具有线“与”的逻辑功能,即只要有一个节点发送低电平时,总线上就表现为低电平。当所有的节点都发送高电平时,总线才能表现为高电平。正是由于线“与”逻辑功能的原理,当多个节点同时发送时钟信号时,在总线上表现的是统一的时钟信号。这就是 SCL 的同步原理。
同步过程如下图:
主机 1 产生 CLK1,主机 2 产生 CLK2,同时向 SCL 线上输出自己的时钟,由于 CLK2 的低电平更长,因此 SCL 线上出现的电平和 CLK2 保持一致。因此在第一个周期中,CLK1 后期进入了高电平等待状态。后面 SCL 上的电平以 CLK2 为准。
SDA Arbitration
SDA 线的仲裁也是建立在总线具有线“与”逻辑功能的原理上的。节点在发送1位数据后,比较总线上所呈现的数据与自己发送的是否一致。是,继续发送;否则,退出竞争。
SDA 线的仲裁可以保证 I2C 总线系统在多个主节点同时企图控制总线时通信正常进行并且数据不丢失。总线系统通过仲裁只允许一个主节点可以继续占据总线。
仲裁在 SDA 上进行,此时 SCL 为高电平。
A 主机传输高电平,B 主机传输低电平,A 失去仲裁。
丢失仲裁的主机将生成时钟脉冲,直到丢失仲裁的字节结束。
仲裁过程:
DATA1 和 DATA2 分别是两个主机向总线所发送的数据信号,SDA 为总线上所呈现的数据信号,SCL 是总线上所呈现的时钟信号。
主机 1、2 同时发送起始信号,在 clock1 ,两个主机都发送了高电平信号。这时总线上呈现的信号为高电平,两个主节点都检测到总线上的信号与自己发送的信号相同,继续发送数据。
第2个时钟周期,2个主节点都发送低电平信号,在总线上呈现的信号为低电平,仍继续发送数据。
在第3个时钟周期,主节点1发送高电平信号,而主节点2发送低电平信号。根据总线的线“与”的逻辑功能,总线上的信号为低电平,这时主节点1检测到总线上的数据和自己所发送的数据不一样,就断开数据的输出级,转为从机接收状态。这样主节点2就赢得了总线,而且数据没有丢失,即总线的数据与主节点2所发送的数据一样,而主节点1在转为从节点后继续接收数据,同样也没有丢掉 SDA 线上的数据。因此在仲裁过程中数据没有丢失。
5、I2C Hs-mode
HS mode 为什么单独讲解?因为高速模式和其他模式有很多不一样的地方。
速度高达 3.4MHz。
用的是 SDAH 和 SCLH 信号线,不是 SDA 和 SCL
Master device
SDAH/SCLH 有一个开漏输出 buffer, SCLH 有一个电流源上拉电路,这个电流源电路缩短了 SCLH 信号的上升时间。任何时侯在 Hs 模式只有一个主机的电流源有效。
没有仲裁和时钟同步,以加速位处理能力。仲裁过程一般在前面用 F/S 模式传输主机码后结束。
以高电平和低电平是 1:2 的比率产生一个串行时钟信号。解除了建立和保持时间的时序要求。
高速数据 SDAH 和高速串行时钟 SCLH 线通过这个电桥与 F/S 模式器件的 SDA 和 SCL 线分隔开来。减轻了SDAH 和 SCLH 线的电容负载,使上升和下降时间更快。
Slave device
Hs 模式从机器件与 F/S 从机器件的唯一差别是它们工作的速度。Hs 模式从机在 SCLH 和 SDAH输出有开漏输出 buffer 。SCLH 管脚可选的下拉晶体管可以用于拉长 SCLH 信号的低电平,但只允许在 Hs 模式传输的响应位后进行。
Hs 模式器件的输出可以抑制毛刺,而且 SDAH 和 SCLH 输出有一个 Schmitt 触发器
Hs 模式器件的输出缓冲器对 SDAH 和 SCLH 信号的下降沿有斜率控制功能
调整了串行数据 SDA 和串行时钟 SCL 信号的时序。没有必要与其他总线系统如 CBUS 兼容,它们不能在增加的位速率下工作。
如果快速模式器件的电源电压被关断,SDA 和 SCL 的 I/O 管脚必须悬空,不能阻塞总线。
连接到总线的外部上拉器件必须调整以适应快速模式 I2C 总线更短的最大允许上升时间。对于负载最大是 200pF 的总线,每条总线的上拉器件可以是一个电阻;对于负载在 200pF~400pF 之间的总线,上拉器件可以是一个电流源(最大值 3mA)或者是一个开关电阻电路,如下图:
只有 Hs 模式器件的系统的物理 I2C 总线配置
(可选)串联电阻器 Rs 保护 I2C 总线设备的 I/O 免受总线上的高压尖峰影响,并将振铃和干扰降至最低。
右下角两个设备,不光是从设备,也可以当主设备。这种器件有一个 MCS 电流源。如果总线上器件较多,会导致总线电容较大,拉升总线电压相当于给电容充电,这需要时间,这会导致波形上升沿过缓,所以加了电流源可以使上升沿很快。
1、data transfer format in Hs-mode
START condition (S)
8-bit master code (0000 1XXX)
Not-acknowledge bit (A)
2、在 Hs 模式下启用电流源上拉电路
3、在下一次重复启动条件后,依旧在 Hs-mode
由上图可以看出,在快速模式(FS mode)下发送一个 Master code,然后切换到高速模式(HS mode),发送从设备地址。
在第一阶段 FS mode 时候,发送主机码(0x0000 1xxx),这时候会进行仲裁。因此 Hs mode 阶段没有时钟同步和仲裁。
在中间的 HS mode 传输结束后,如果是一个 STOP 信号,则立刻回到 F/S mode,如果是 Sr 重复开始i信号,则依旧留在 Hs mode(右下角有说明)
上图为 Hs mode 完整通信波形示意图。先在快速模式下发送主机码,不需要从机回复。然后切换到高速模式,会发送一个 reSTART,然后进行数据传输。
需要注意如下几点:
右上角 t1 到 tH 时间之内,可以进行时钟延展。
Hs mode 中,只能在 byte level 级别进行时钟延展,也就是一个 byte 传输结束后进行时钟延展。
注意左下角的示意图,如果是直上直下的这种波形,是主机电流源上拉。如果是缓坡上升沿,则是电阻上拉。
博主将 I2C spec 单独总结出来,意思是说,不管你是单片机平台,还是 FreeRTOS 平台,还是 Linux 平台,I2C spec 都是一样的,所以总结为一文方便大家查看。
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !