1. I2C协议基础:物理层、协议层、起始条件、停止条件、数据有效性、应答机制
各位同学好,我是老周。做嵌入式这行十几年了,I2C 这协议几乎天天见。说实话,很多工程师调了几年 I2C,遇到问题还是抓瞎——要么波形看不懂,要么设备死活没应答。今天咱们就从最底层开始,把 I2C 的骨头拆开来看。
你想想看,一条总线上挂好几个设备,就靠两根线通信,怎么做到不乱?这背后就是物理层和协议层的配合。我当年第一次用逻辑分析仪抓 I2C 波形时,看到那串高低电平,脑子里全是问号。后来才明白,搞懂协议基础,调试才能有的放矢。
1.1 物理层:就两根线,但规矩不少
I2C 总线物理上就两条线:SCL(时钟线)和SDA(数据线)。所有设备都挂在这两条线上,采用开漏输出加外部上拉电阻的结构。
核心特点:
- 开漏输出:设备只能将总线拉低,不能主动拉高。高电平由上拉电阻提供。
- 线与逻辑:只要有一个设备拉低总线,总线就是低电平。这是仲裁的基础。
- 上拉电阻:通常 4.7kΩ,高速模式可能需要 1.5kΩ 甚至更小。
我遇到过不少新手,上来就问:为什么 SDA 和 SCL 要接上拉电阻?不接行不行?答案是——不行。开漏结构决定了总线必须靠外部电阻拉到高电平。不接上拉,总线浮空,通信全乱套。
| 参数 | 标准模式 (100kHz) | 快速模式 (400kHz) | 高速模式 (3.4MHz) |
|---|---|---|---|
| 上拉电阻典型值 | 4.7kΩ | 1.5kΩ - 2.2kΩ | 0.5kΩ - 1kΩ |
| 总线电容上限 | 400pF | 400pF | 100pF |
| 最大从设备数量 | 127(7位地址) | 127 | 127 |
实战经验:我建议你调试时先用 4.7kΩ 上拉。如果总线距离长或者设备多,再换成 2.2kΩ。上拉太小会拉低信号质量,太大又会让上升沿变缓——逻辑分析仪上能看到波形变圆角。
1.2 协议层:谁说话,谁听话
I2C 是主从架构。总线上只有一个主设备(Master),其他都是从设备(Slave)。主设备负责产生时钟、发起通信、决定何时结束。从设备只能响应。
每个从设备都有一个唯一的7位地址(也有10位地址的,但用得少)。主设备发地址时,总线上所有从设备都会收到,但只有地址匹配的那个才会应答。
注意:同一个 I2C 总线上不能有两个相同地址的设备。我踩过这个坑——两个传感器地址都是 0x68,结果读数据时两个同时应答,数据全乱了。后来只能加一个 I2C 多路复用器解决。
下面这张图展示了 I2C 通信的基本结构:
1.3 起始条件与停止条件
这两个条件是 I2C 通信的"开关"。没有它们,总线上的设备不知道什么时候开始、什么时候结束。
起始条件(Start Condition):SCL 为高电平时,SDA 从高电平切换到低电平。
停止条件(Stop Condition):SCL 为高电平时,SDA 从低电平切换到高电平。
记住这个口诀:
- 起始:SCL 高 → SDA 下降沿
- 停止:SCL 高 → SDA 上升沿
这两个条件只能由主设备产生。从设备不能发起起始或停止。
我刚开始学的时候,总把起始和停止搞混。后来逻辑分析仪抓了几次波形,一眼就看明白了——起始是 SDA 先跳,停止也是 SDA 先跳,但方向相反。
1.4 数据有效性:时钟高时采样
I2C 的数据传输有个铁律:SDA 上的数据必须在 SCL 为高电平时保持稳定。数据变化只能在 SCL 为低电平时发生。
为什么?因为接收方是在 SCL 的上升沿或高电平期间采样 SDA。如果 SDA 在此时变化,采到的数据就是错的。
| SCL 状态 | SDA 允许行为 | 说明 |
|---|---|---|
| 高电平 | 必须稳定 | 接收方在此阶段采样数据 |
| 低电平 | 允许变化 | 发送方在此阶段更新数据位 |
调试技巧:用逻辑分析仪看 I2C 波形时,重点看 SCL 高电平期间 SDA 有没有抖动。如果有,说明信号完整性有问题——可能是上拉电阻太小、总线电容太大,或者有噪声干扰。我曾经在一个电机驱动板上遇到过,电机一转,I2C 就出错,最后发现是电源噪声耦合到了 SDA 线上。
1.5 应答机制:确认收到
I2C 的每个字节(8位)后面都跟着一个应答位(ACK/NACK)。这是协议层的握手信号。
具体流程是这样的:
- 发送方发出 8 位数据后,释放 SDA(拉高)
- 接收方在第 9 个 SCL 时钟周期拉低 SDA(表示 ACK)或保持高电平(表示 NACK)
- 主设备检测 SDA 状态,判断是否继续通信
常见故障:
- 从设备无应答(NACK):地址不对、设备未上电、总线冲突、设备忙
- 主设备不检测应答:有些 MCU 的 I2C 外设默认不检查 ACK,导致发送错误数据而不自知
我曾经调试一个温湿度传感器,死活读不到数据。逻辑分析仪一抓,发现从设备返回了 NACK。查了半天,原来是传感器地址搞错了——数据手册写的是 7 位地址 0x76,但我左移了一位当 8 位地址发,当然对不上。
下面这个流程图展示了完整的 I2C 单字节写操作:
1.6 本章小结
I2C 协议的基础就这些:两根线、主从架构、起始停止、数据有效性、应答机制。听起来简单,但实际调试中,每一个环节都可能出问题。
我个人习惯是:拿到一个新 I2C 设备,先用逻辑分析仪抓一下波形,确认起始条件、地址、应答都正常,再开始写驱动代码。这样能省去后面大量的排查时间。
核心要点回顾:
- 物理层:开漏 + 上拉,线与逻辑
- 起始条件:SCL 高时 SDA 下降沿
- 停止条件:SCL 高时 SDA 上升沿
- 数据有效性:SCL 高时 SDA 必须稳定
- 应答机制:第 9 个时钟,拉低为 ACK,高为 NACK