1. I2C协议基础回顾:物理层、协议层、时序图解读
各位同学好,我是老周。做嵌入式这些年,调试过最多的总线就是I2C。说它简单吧,两根线就能挂一堆设备;说它麻烦吧,一旦出问题,示波器一挂就是半天。今天咱们先把I2C的底子打牢,后面讲多从机故障排查时才不会懵。
1.1 物理层:就两根线,但规矩不少
I2C总线物理上就两条线:SCL(时钟线)和SDA(数据线)。但你别小看这两根线,它们都是开漏输出结构。什么叫开漏?说白了,芯片只能把线拉低,不能主动拉高。拉高的工作交给上拉电阻。
核心要点:I2C总线空闲时,SCL和SDA都必须保持高电平。这是靠上拉电阻实现的。
我在项目中遇到过一位新手,把I2C的上拉电阻焊成了10kΩ,结果总线上升沿慢得像蜗牛,通信距离稍远一点就出错。嗯,这里要注意:上拉电阻的取值跟总线电容、通信速率都有关系。
| 参数 | 标准模式 (100kHz) | 快速模式 (400kHz) | 高速模式 (3.4MHz) |
|---|---|---|---|
| 上拉电阻推荐值 | 4.7kΩ ~ 10kΩ | 2.2kΩ ~ 4.7kΩ | 1kΩ ~ 2.2kΩ |
| 总线电容上限 | 400pF | 400pF | 100pF |
| 最大从机数量 | 理论127个 | 理论127个 | 理论127个 |
避坑指南:我曾经在一条总线上挂了8个从机,用了1kΩ上拉电阻,结果SCL波形直接变成了三角波。后来换成2.2kΩ才恢复正常。总线电容大了,上拉电阻就得小,但太小又会增加功耗,这是个权衡。
1.2 协议层:地址、读写、应答,一个都不能少
I2C的通信协议其实挺清晰的。每次通信都由主机发起,从机响应。你想想看,总线上那么多设备,怎么知道跟谁说话?靠地址。
每个I2C从设备都有一个7位地址(也有10位地址模式,但用得少)。主机发送地址时,实际上发的是8位:7位地址 + 1位读写标志位。读写标志位为0表示写,为1表示读。
1.2.1 通信流程
- 起始条件:SCL高电平时,SDA从高变低
- 发送地址:主机发送7位地址 + 读写位
- 从机应答:从机拉低SDA表示应答(ACK)
- 数据传输:每8位数据后跟一个应答位
- 停止条件:SCL高电平时,SDA从低变高
个人经验:我习惯在写驱动时,把起始条件和停止条件封装成两个独立函数。这样调试时可以在关键位置加断点,看波形对不对。
1.2.2 应答机制
应答是I2C通信的"握手信号"。每发送完一个字节,接收方必须给出应答。如果没收到应答,发送方就知道出问题了。
- ACK (应答):SDA在第9个时钟周期被拉低,表示"收到,继续"
- NACK (非应答):SDA在第9个时钟周期保持高,表示"收完了"或"出错了"
我记得有一次调试温湿度传感器,主机发完地址后一直没收到ACK。查了半天,原来是地址搞错了——传感器的地址是0x5A,我写成了0x5B。就这一位之差,折腾了我两个小时。
1.3 时序图解读:看得懂波形,才能调得好
做I2C调试,示波器是必备工具。但很多人拿到波形图就头疼。其实I2C的时序图有规律可循,咱们拆开来看。
1.3.1 时序参数
| 参数 | 符号 | 标准模式 | 快速模式 |
|---|---|---|---|
| SCL时钟频率 | fSCL | 100kHz | 400kHz |
| 起始条件保持时间 | tHD;STA | 4.0μs | 0.6μs |
| 数据建立时间 | tSU;DAT | 250ns | 100ns |
| 数据保持时间 | tHD;DAT | 0~3.45μs | 0~0.9μs |
| 停止条件建立时间 | tSU;STO | 4.0μs | 0.6μs |
| 总线空闲时间 | tBUF | 4.7μs | 1.3μs |
注意:STM32的I2C外设虽然会自动处理时序,但如果你用GPIO模拟I2C,这些参数就得自己把控。我曾经在快速模式下把tHD;STA设成了0.3μs,结果从机根本不认起始条件。
1.3.2 典型读写时序
写操作是最简单的。主机发完起始条件后,依次发送:从机地址(写)、寄存器地址、数据。每发一个字节等一次ACK。
读操作稍微复杂一点。要先写寄存器地址,然后重新发起始条件,再发从机地址(读),最后从机才会把数据送出来。这个"重新起始"很多人容易搞混。
// 写操作时序
START -> 从机地址+W -> ACK -> 寄存器地址 -> ACK -> 数据 -> ACK -> STOP
// 读操作时序
START -> 从机地址+W -> ACK -> 寄存器地址 -> ACK ->
REPEATED START -> 从机地址+R -> ACK -> 读取数据 -> NACK -> STOP
调试技巧:我习惯在逻辑分析仪上设置触发条件为"START条件",这样每次通信开始都能抓到。然后对照上面的时序模板,一个字节一个字节地核对,很快就能定位问题。
1.4 I2C通信核心流程(SVG图解)
下面这张图把I2C一次完整的数据传输过程画出来了。从起始条件到停止条件,每个环节都标注了关键信号变化。你调试的时候可以对照着看波形。
1.5 常见问题与排查思路
做I2C调试这么多年,我总结了几类最常见的问题。你遇到故障时,可以按这个顺序排查:
- 波形异常:先看上拉电阻对不对,再看总线电容是不是太大了
- 无应答:检查从机地址对不对,确认从机是否上电
- 数据错位:大概率是时钟极性或相位配置错了
- 总线锁死:SCL或SDA被一直拉低,通常是某个从机挂了,断电重启试试
我的经验:调试I2C时,别一上来就怀疑代码。先拿示波器看波形,确认物理层没问题。我见过太多人花一整天改软件,最后发现是上拉电阻虚焊了。