I2C协议基础回顾:物理层、协议层、时序参数详解
各位同学好,我是老周。做嵌入式这些年,I2C是我打交道最多的接口之一。别看它只有两根线,坑是真不少。今天咱们先把I2C的底子打牢,后面讲抗干扰设计时你才能知道问题出在哪。
一、物理层:就两根线,但别小看它
I2C总线就两条线:SDA(数据线)和SCL(时钟线)。都是开漏输出,配上上拉电阻。什么意思呢?说白了,芯片只能把线拉低,不能主动拉高。高电平全靠上拉电阻提供。
关键点:开漏结构决定了I2C的电气特性。多主机仲裁、时钟拉伸这些高级功能,全依赖这个设计。
我刚开始做项目时,总觉得上拉电阻随便选一个就行。结果有一次在高温箱里测试,通信频繁出错。查了半天,发现是上拉电阻选小了,灌电流太大,把IO口的驱动能力吃死了。
上拉电阻怎么选?
这里给个经验值:
| 总线电容 | 标准模式(100kHz) | 快速模式(400kHz) |
|---|---|---|
| ~50pF | 4.7kΩ ~ 10kΩ | 2.2kΩ ~ 4.7kΩ |
| ~100pF | 2.2kΩ ~ 4.7kΩ | 1kΩ ~ 2.2kΩ |
| ~200pF | 1kΩ ~ 2.2kΩ | 不推荐 |
我的习惯:一般先上4.7kΩ。如果总线设备多、距离长,再换成2.2kΩ。别一上来就用1kΩ,功耗会大不少。
二、协议层:起始、停止、应答,三板斧
I2C的协议说简单也简单,就几个基本动作。但组合起来,能玩出花。
1. 起始条件和停止条件
SCL高电平时,SDA从高变低 → 起始条件(Start)。
SCL高电平时,SDA从低变高 → 停止条件(Stop)。
这个时序很关键。我见过有人用GPIO模拟I2C时,起始条件没做对,从机根本不响应。你想想看,从机一直在等那个下降沿,你没给,它就不动。
2. 数据传输
每个时钟脉冲传1位数据。SCL低电平时SDA可以变化,SCL高电平时SDA必须稳定。这个规则保证了数据的可靠性。
3. 应答机制
每传完一个字节(8位),第9个时钟周期是应答位。接收方拉低SDA表示ACK,不拉低就是NACK。
避坑指南:我曾经在一个项目中,从机地址写对了,但就是不ACK。查了两天,发现是从机电源没稳定,上电时序有问题。记住:I2C从机必须在总线空闲时才能正确响应。
三、时序参数:别只看手册,要实测
I2C的时序参数,手册上写得清清楚楚。但实际项目中,你得留余量。
| 参数 | 符号 | 标准模式 | 快速模式 |
|---|---|---|---|
| SCL时钟频率 | fSCL | 100 kHz | 400 kHz |
| 保持时间(起始) | tHD;STA | 4.0 μs | 0.6 μs |
| 建立时间(停止) | tSU;STO | 4.0 μs | 0.6 μs |
| 数据保持时间 | tHD;DAT | 0 μs | 0 μs |
| 数据建立时间 | tSU;DAT | 250 ns | 100 ns |
| SCL低电平时间 | tLOW | 4.7 μs | 1.3 μs |
| SCL高电平时间 | tHIGH | 4.0 μs | 0.6 μs |
嗯,这里要注意:数据保持时间tHD;DAT是0μs。这意味着SCL下降沿之后,SDA可以立刻变化。但实际中,我建议留个几百纳秒的余量,特别是总线电容大的时候。
四、知识体系总览
下面这张图,把I2C协议的核心知识点串起来了。你对照着看,心里就有谱了。
五、一个完整的读写序列
光说不练假把式。咱们看一个实际的I2C写操作流程:
// 伪代码:向从机地址0x50写入两个字节
起始条件
发送从机地址 + 写位 (0xA0) // 7位地址左移1位,最低位为0
等待ACK
发送寄存器地址 (0x10)
等待ACK
发送数据字节1 (0xAB)
等待ACK
发送数据字节2 (0xCD)
等待ACK
停止条件
读操作稍微复杂一点,需要先写寄存器地址,再重新发起始条件,然后读数据:
// 伪代码:从从机地址0x50读取两个字节
起始条件
发送从机地址 + 写位 (0xA0)
等待ACK
发送寄存器地址 (0x10)
等待ACK
重复起始条件 // 这里要注意,不是停止再开始
发送从机地址 + 读位 (0xA1)
等待ACK
读取数据字节1,主机发送ACK
读取数据字节2,主机发送NACK // 最后一个字节要发NACK
停止条件
我的经验:重复起始条件(Repeated Start)是很多新手容易搞错的地方。有些人习惯先发Stop再发Start,这在多主机系统中会丢失总线控制权。记住:读操作一定要用重复起始。
六、常见问题与调试思路
做I2C调试,示波器是必备的。我总结了几种常见波形异常:
- SDA一直低:某个设备把总线拉死了。逐个断开从机排查。
- SCL频率不对:检查主时钟分频配置,特别是用内部RC振荡器时。
- ACK丢失:地址对不对?从机供电正常吗?总线电容太大导致信号畸变?
- 数据错位:大概率是时序余量不够,特别是快速模式下。
避坑指南:我曾经在一个量产项目中,发现部分板子I2C通信不稳定。查到最后,是PCB走线太长,总线电容超过了400pF。400kHz模式下,信号上升沿明显变缓,导致从机采样出错。后来加了施密特触发器整形,问题才解决。