4. I2C通信模式:主从模式、多主机仲裁、时钟同步与时钟拉伸、高速模式
I2C 这玩意儿,看着简单,就两根线:SCL 和 SDA。但里面的门道,说实话,真不少。我刚开始用 I2C 的时候,觉得不就是发个地址、读个数据嘛,能有多复杂?结果被总线锁死、从机不响应、数据错位这些问题折腾了好几个通宵。今天咱们就把 I2C 的几种核心通信模式掰开揉碎了讲清楚。
4.1 主从模式:谁说话,谁听话
I2C 总线上的设备,分两种角色:主机(Master) 和 从机(Slave)。主机负责产生时钟信号、发起通信、决定什么时候开始什么时候结束。从机呢,就是被主机点名的那位,主机叫它,它才能回话。
我个人习惯把主机想象成「会议主持人」,从机就是「参会者」。主持人拿着话筒(SCL 时钟),点名谁,谁才能发言。其他参会者只能听着,不能插嘴。
主从模式的通信流程,我总结为四步:
- 主机发送起始条件(START):SCL 高电平时,SDA 从高变低。这相当于主持人说「会议开始」。
- 主机发送从机地址 + 读写位:7 位或 10 位地址,加上 1 位 R/W 位。从机收到后,如果地址匹配,会回复一个 ACK(将 SDA 拉低)。
- 数据传输:每 8 位数据后跟一个 ACK/NACK。主机发送时钟,从机或主机根据读写方向提供数据。
- 主机发送停止条件(STOP):SCL 高电平时,SDA 从低变高。主持人说「散会」。
这里有个坑,我刚开始做项目时踩过:起始条件和停止条件之间的时间间隔不能太短。有些从机芯片处理速度慢,连续快速启动停止,它会反应不过来。我建议在两次传输之间至少留 4.7μs 的间隔(标准模式 100kHz 下)。
4.2 多主机仲裁:多个主持人抢话筒
一个 I2C 总线上可以有多个主机。但问题来了:如果两个主机同时想说话,怎么办?
I2C 的解决方案是仲裁(Arbitration)。说白了,就是谁先发现总线被占用了,谁就主动退让。
仲裁发生在 SDA 线上。多个主机同时发送数据时,它们都会监测 SDA 的电平。如果一个主机发送了高电平(1),但检测到 SDA 是低电平(0),说明有其他主机在拉低总线。这时候,这个主机就知道自己「输」了,立刻停止发送 SDA 数据,转为从机模式监听总线。
仲裁的规则很简单:低电平优先。谁先拉低 SDA,谁就赢得总线控制权。输掉的主机不会丢失数据,因为它会在下一个时钟周期重新尝试。
多主机仲裁的典型场景:
- 多个 MCU 共享一个传感器总线
- 热插拔设备需要动态加入通信
- 冗余系统,一个主机挂了,另一个自动接管
4.3 时钟同步与时钟拉伸:慢设备也有发言权
这两个概念,很多初学者容易搞混。我分开讲。
时钟同步(Clock Synchronization)
多主机模式下,每个主机都有自己的时钟源。如果两个主机的时钟频率不一样,怎么办?I2C 的时钟同步机制就是干这个的。
原理其实很简单:线与(Wired-AND)。SCL 线是开漏输出,多个主机同时驱动 SCL 时,谁先拉低 SCL,SCL 就被拉低。所有主机都要等到 SCL 被释放(变为高电平)后,才能继续自己的时钟周期。
结果就是:所有主机的时钟周期被同步到最慢的那个。低电平时间由拉低时间最长的主机决定,高电平时间由拉高时间最短的主机决定。
时钟拉伸(Clock Stretching)
时钟拉伸是从机的特权。当从机需要更多时间处理数据时,它可以在主机释放 SCL 后,主动拉低 SCL,迫使主机等待。主机检测到 SCL 被拉低,就会暂停发送时钟脉冲,直到从机释放 SCL。
我遇到过最典型的例子是 EEPROM 写入。AT24Cxx 系列在写入一页数据后,需要 5ms 左右的内部编程时间。如果主机不等待,直接发下一个命令,EEPROM 不会响应。正确的做法是:主机在发送完写入命令后,发一个起始条件 + 从机地址,如果 EEPROM 拉低 SCL(时钟拉伸),主机就等着;直到 EEPROM 释放 SCL 并回复 ACK,才表示写入完成。
4.4 高速模式(Hs-mode):飙车到 3.4MHz
标准模式 100kHz,快速模式 400kHz,高速模式直接干到 3.4MHz。速度提升了近 9 倍。但高速模式不是随便就能用的,它有一些特殊要求。
| 参数 | 标准模式 | 快速模式 | 高速模式 |
|---|---|---|---|
| 最大频率 | 100 kHz | 400 kHz | 3.4 MHz |
| 上升时间 | 1000 ns | 300 ns | 40 ns |
| 下降时间 | 300 ns | 300 ns | 40 ns |
| 上拉电阻 | 4.7kΩ - 10kΩ | 1.5kΩ - 4.7kΩ | 0.5kΩ - 1.5kΩ |
| 从机数量限制 | 127 | 127 | 受总线电容限制 |
高速模式的工作原理,我简单说一下:
- 主机先进入快速模式:发送一个特殊的「主码(Master Code)」00001XXX,然后跟一个 NACK。这相当于告诉所有从机:「我要飙车了,支持的准备好」。
- 切换到高速时钟:主机将 SCL 频率提升到 3.4MHz。只有支持 Hs-mode 的从机才会继续响应,不支持的从机自动忽略后续通信。
- 电流源上拉:高速模式下,普通的上拉电阻不够用,因为 RC 常数太大,上升时间跟不上。主机需要打开一个内部电流源(通常 2mA - 4mA)来快速拉高 SCL 和 SDA。
- 退出高速模式:发送停止条件后,总线自动回到快速模式或标准模式。
说实话,我在实际项目中很少用到 3.4MHz 的高速模式。大部分场景下,400kHz 的快速模式已经够用了。只有在传输大量数据(比如摄像头配置、音频数据流)时,我才会考虑用 Hs-mode。而且,不是所有 MCU 的 I2C 外设都支持高速模式,用之前一定要查数据手册。
嗯,以上就是 I2C 四种核心通信模式的全部内容。主从模式是基础,多主机仲裁解决冲突,时钟同步和拉伸保证兼容性,高速模式满足高性能需求。搞懂了这些,你在调试 I2C 总线时就能快速定位问题——是地址冲突?是时钟不匹配?还是从机没来得及处理?心里就有数了。