2、I2C总线基础回顾:I2C协议架构、起始/停止条件、地址帧、数据帧、ACK/NACK、时钟同步与仲裁
I2C(Inter-Integrated Circuit)总线自1982年由Philips(现NXP)推出以来,凭借其仅需两根线(SCL时钟线、SDA数据线)即可挂载多个器件的极简架构,成为嵌入式系统中应用最广泛的板级通信协议之一。在深入I3C总线之前,必须扎实掌握I2C的协议骨架——因为I3C在设计上保留了I2C的电气特性(开漏、上拉电阻)和部分寻址机制,同时引入了动态地址分配、更高速度模式等增强特性。本章将系统拆解I2C的协议架构、时序关键点、仲裁机制与时钟同步原理,为后续对比I3C的演进打下坚实基础。
上图展示了I2C总线的整体架构与核心机制。总线由两根开漏信号线(SDA、SCL)和上拉电阻构成,所有设备以线与方式连接。主控制器通过SCL产生时钟,SDA传输数据。从设备通过地址识别是否被寻址。仲裁机制解决多主机竞争,时钟同步则通过线与特性自然实现。下面逐一深入剖析每个协议要素。
2.1 I2C协议架构与电气特性
核心原理:I2C采用半双工、同步、多主多从的通信架构。物理层由两根线组成:SDA(串行数据线)和SCL(串行时钟线)。所有设备(主/从)的SDA和SCL引脚均为开漏输出,通过外部上拉电阻(典型值1kΩ~10kΩ,取决于总线电容和通信速率)连接到电源VDD。这种开漏结构实现了“线与”逻辑——任何设备拉低总线,总线即为低电平;只有所有设备释放总线,总线才被上拉为高电平。
I2C协议支持多种速率模式:标准模式(100 kbit/s)、快速模式(400 kbit/s)、快速模式+(1 Mbit/s)和高速模式(3.4 Mbit/s)。速率的选择受总线电容、上拉电阻阻值和从设备能力共同制约。总线电容越大,上升沿越缓,最大速率越低。
| 参数 | 标准模式 | 快速模式 | 快速模式+ | 高速模式 |
|---|---|---|---|---|
| 最大速率 | 100 kbit/s | 400 kbit/s | 1 Mbit/s | 3.4 Mbit/s |
| 最小上拉电阻 | 4.7 kΩ | 1.7 kΩ | 1.0 kΩ | 0.8 kΩ |
| 最大总线电容 | 400 pF | 400 pF | 550 pF | 100 pF |
| 输入阈值 | VIL = 0.3×VDD, VIH = 0.7×VDD | |||
判断方法:在硬件设计时,需根据总线上挂载的设备数量、PCB走线长度和通信速率要求,计算总线上拉电阻值。经验公式为:Rp_min = (VDD - VOL_max) / IOL_max,其中VOL_max通常为0.4V,IOL_max为3mA(快速模式)或20mA(快速模式+)。Rp_max = t_r / (0.8473 × C_bus),其中t_r为上升沿时间要求。
2.2 起始条件与停止条件
核心原理:I2C通信的起始(START)和停止(STOP)条件由SDA和SCL的时序关系定义,是总线状态的“边界标记”。
- 起始条件(S):SCL保持高电平时,SDA由高电平跳变为低电平。该条件由主控制器发起,表示总线从空闲状态进入忙状态。
- 停止条件(P):SCL保持高电平时,SDA由低电平跳变为高电平。该条件由主控制器发起,表示本次传输结束,总线释放。
- 重复起始条件(Sr):在一次传输过程中,主控制器可以在不释放总线的情况下再次发起起始条件,用于改变传输方向(如从写模式切换到读模式)或重新寻址。
时序要求:起始条件和停止条件都有严格的建立时间和保持时间要求。在标准模式下,起始条件建立时间(tSU;STA)最小为4.7μs,保持时间(tHD;STA)最小为4.0μs;停止条件建立时间(tSU;STO)最小为4.0μs。快速模式下这些时间缩短为0.6μs和0.6μs。
static void i2c_start(void) {
sda_high(); // SDA拉高
scl_high(); // SCL拉高
udelay(5); // 等待稳定
sda_low(); // SDA拉低(产生起始条件)
udelay(5); // 保持时间
scl_low(); // SCL拉低,准备传输数据
}
这段代码严格遵循了起始条件的时序定义:先确保SDA和SCL均为高,然后SDA先拉低,再拉低SCL。若顺序颠倒,从设备将无法识别起始条件,导致通信失败。
常见误区:初学者常将起始条件误认为“SDA先低后SCL低”,实际上起始条件的核心是“SCL高时SDA跳变”。若在SCL低电平时SDA跳变,那只是正常的数据位变化,不会触发起始条件。此外,重复起始条件与停止条件+起始条件的区别在于:重复起始不释放总线,中间没有停止条件,这保证了多字节读操作时总线的独占性。
2.3 地址帧与数据帧格式
核心原理:I2C的每次传输以起始条件开始,随后发送地址帧,再发送一个或多个数据帧。地址帧由7位从设备地址(或10位扩展地址)和1位读写标志(R/W)组成,共8位,随后是从设备发送的ACK/NACK位。
7位地址帧结构:
- 地址位(A6:A0):高7位为从设备地址。地址的高4位通常由器件类型决定(如1010为EEPROM,1001为ADC/DAC),低3位可由硬件引脚(A0/A1/A2)配置,允许同一总线上挂载多个同类型器件。
- 读写位(R/W):第8位。0表示主控制器将要写入(发送数据),1表示主控制器将要读取(接收数据)。
- 应答位(ACK/NACK):第9个时钟周期。从设备在收到地址后,若地址匹配则拉低SDA(ACK),否则释放SDA(NACK)。
数据帧结构:每个数据帧为8位数据(D7:D0),MSB先行发送。发送方(主设备写模式或从设备读模式)在SCL高电平期间保持SDA稳定,在SCL低电平期间切换SDA。每个字节后跟一个ACK/NACK位,由接收方产生。
| 帧类型 | 位序 | 长度 | 方向 | 说明 |
|---|---|---|---|---|
| 起始条件 | - | 1位 | 主→总线 | SCL高时SDA下降沿 |
| 地址帧 | A6:A0 + R/W | 8位 | 主→从 | 7位地址+读写标志 |
| ACK位 | ACK/NACK | 1位 | 从→主 | 从设备确认地址匹配 |
| 数据帧 | D7:D0 | 8位 | 主↔从 | 实际传输数据 |
| ACK位 | ACK/NACK | 1位 | 接收方→发送方 | 确认数据接收 |
| 停止条件 | - | 1位 | 主→总线 | SCL高时SDA上升沿 |
判断方法:在调试I2C通信时,使用逻辑分析仪抓取波形,首先确认起始条件位置,然后按字节解析。地址帧的ACK/NACK是判断从设备是否存在的最直接依据——若地址后出现NACK,说明总线上没有匹配该地址的设备,或设备未上电、地址配置错误。
2.4 ACK/NACK机制与时钟同步
核心原理:ACK/NACK是I2C协议的流量控制机制。每个字节传输完成后,接收方在第9个时钟周期释放SDA(对于ACK则拉低,对于NACK则保持高)。主控制器通过检测ACK/NACK判断通信状态:
- ACK(低电平):接收方成功接收字节,可以继续传输下一字节。
- NACK(高电平):接收方未成功接收或不再接收数据。主控制器收到NACK后,应发送停止条件终止传输。
时钟同步(Clock Synchronization):由于I2C采用开漏结构,多个主机同时驱动SCL时,SCL的低电平时间由最慢的主机决定(所有主机都释放SCL后,SCL才被上拉为高)。这种“线与”特性天然实现了时钟同步:
- 每个主机在SCL低电平期间,根据自己的时钟配置决定低电平持续时间。
- 当所有主机都释放SCL后,SCL被上拉为高,此时所有主机同时检测到SCL上升沿,开始高电平计时。
- 高电平时间由最快的主机决定——第一个拉低SCL的主机将SCL拉低,其他主机同步进入低电平状态。
时钟拉伸(Clock Stretching):从设备在需要处理数据或准备响应时,可以拉低SCL并保持,强制主控制器进入等待状态。这是从设备“减速”主控制器的机制,在低速传感器(如温度传感器)中常见。
解决方案:1)在读取传感器前,先查询其状态寄存器,确认转换完成后再发起读取;2)配置I2C外设的时钟拉伸超时时间为10ms,留足余量;3)优化软件架构,将I2C读取放在非实时任务中,避免阻塞关键路径。
复盘经验:时钟拉伸是I2C从设备的合法行为,主控制器必须支持。在选用MCU的I2C外设时,应确认其是否支持时钟拉伸(大多数硬件I2C外设支持,但部分低端MCU的模拟I2C实现可能不支持)。若使用GPIO模拟I2C,必须在等待ACK或数据位时加入超时机制,防止从设备永久拉低SCL导致总线死锁。
2.5 总线仲裁机制
核心原理:I2C支持多主机模式,多个主控制器可以同时发起传输。仲裁机制确保只有一个主控制器赢得总线控制权,且不破坏正在进行的通信。仲裁发生在SDA线上,逐位进行:
- 多个主机同时发送起始条件后,各自开始发送地址帧。
- 每个主机在SCL高电平期间采样SDA,与自己发送的电平比较。
- 如果某主机发送高电平但采样到低电平(因为另一个主机拉低了SDA),则该主机失去仲裁。
- 失去仲裁的主机立即停止发送,释放SDA和SCL,等待下一次总线空闲。
仲裁特点:
- 仲裁不破坏数据——赢得仲裁的主机继续发送,从设备感知不到仲裁发生。
- 仲裁可以发生在地址帧、数据帧或ACK位阶段。
- SCL始终由主机们同步,仲裁过程不影响时钟。
- 如果两个主机发送完全相同的地址和数据,则两者都认为赢得仲裁,直到出现差异位。
判断方法:在调试多主机系统时,若发现数据异常,应使用逻辑分析仪同时监测SDA和SCL,观察是否存在SDA电平与发送数据不一致的时刻——这正是仲裁发生的标志。软件层面,主控制器在发送每个位后应检查总线状态,若检测到仲裁丢失,应设置错误标志并重试。
2.6 常见误区与总结复盘
误区一:认为I2C的ACK是“必须”的。实际上,主控制器在读取最后一个字节时,应发送NACK(释放SDA)来告知从设备“不再需要数据”,然后发送停止条件。若主控制器发送ACK,从设备会继续发送下一字节,导致多读一个字节。
误区二:忽略上拉电阻的阻值选择。上拉电阻过小会导致灌电流过大,损坏开漏输出;过大则导致上升沿过缓,在高速模式下无法满足时序要求。应通过计算和实际测试确定最佳阻值。
误区三:在多主机系统中未处理仲裁丢失。主控制器在发送数据时,必须实时监控SDA状态,一旦发现仲裁丢失,应立即停止发送并释放总线,而不是继续发送造成总线冲突。
误区四:混淆时钟同步与时钟拉伸。时钟同步是多个主机之间的SCL协调机制,时钟拉伸是从设备主动拉低SCL的行为。两者都利用了开漏结构的线与特性,但参与方和目的不同。
| 对比维度 | 时钟同步 | 时钟拉伸 |
|---|---|---|
| 参与方 | 多个主控制器 | 从设备(或慢速主设备) |
| 触发条件 | 多主机同时发起传输 | 从设备需要额外时间处理 |
| SCL低电平时间 | 由最慢主机决定 | 由从设备决定 |
| 对通信的影响 | 无影响,仲裁正常进行 | 主控制器等待,传输暂停 |
| 协议要求 | 所有主机必须支持 | 主控制器必须支持(可选) |
总结复盘:I2C协议的精髓在于“简单而健壮”——两根线、开漏结构、线与逻辑、逐位仲裁,这些设计使得I2C在极低硬件成本下实现了多设备、多主机的可靠通信。理解I2C的协议架构、时序要求和仲裁机制,不仅是驱动开发的基础,更是后续学习I3C的关键前提。I3C在保留I2C电气特性的同时,引入了动态地址分配、带内中断、HDR模式等新特性,但其底层仍然遵循起始/停止条件、ACK/NACK和时钟同步的基本框架。掌握本章内容后,读者应能独立分析I2C波形、排查通信故障,并为理解I3C的兼容模式做好准备。