I2C通信DMA传输与CPU负载故障定位实战 - 第1节
1.1 I2C 总线物理层——两根线怎么搞定一切?
I2C 总线,说白了就是两根线:SCL(时钟线)和SDA(数据线)。很多刚入行的工程师会问:就两根线,能传数据还能挂多个设备?
嗯,这里的关键在于——这两根线都是开漏输出,外部必须接上拉电阻。我刚开始做硬件时,就吃过这个亏。板子调了两天,I2C 死活不通,最后发现是上拉电阻焊错了封装,4.7kΩ 焊成了 47Ω。你想想看,47Ω 能把总线拉成什么样?SCL 波形都快成一条直线了。
上拉电阻怎么选?
我个人习惯,标准模式(100kHz)用 4.7kΩ,快速模式(400kHz)用 2.2kΩ。但这不是死规矩,得看总线电容。
| 总线电容 | 推荐上拉电阻(100kHz) | 推荐上拉电阻(400kHz) |
|---|---|---|
| ≤ 100pF | 4.7kΩ | 2.2kΩ |
| 100pF ~ 200pF | 3.3kΩ | 1.5kΩ |
| 200pF ~ 400pF | 2.2kΩ | 1.0kΩ |
1.2 起始条件与停止条件——通信的“握手”与“再见”
I2C 通信的开始和结束,不是靠电平高低,而是靠时序组合。这一点和 SPI 完全不同,SPI 靠片选信号,I2C 靠的是 SDA 和 SCL 的配合。
起始条件(START Condition)
SCL 为高电平时,SDA 从高电平跳变到低电平。这就是起始条件。
我见过不少新手,写代码时先拉低 SCL,再拉低 SDA。这其实是错的。起始条件的核心是:SCL 高电平时,SDA 发生下降沿。顺序不能乱。
停止条件(STOP Condition)
SCL 为高电平时,SDA 从低电平跳变到高电平。这就是停止条件。
为什么要有这两个条件?说白了,就是为了让总线上的所有设备都知道:“我要开始说话了”和“我说完了”。没有这两个条件,从设备根本不知道什么时候该听、什么时候该睡。
1.3 数据有效性——什么时候读数据?
I2C 的数据有效性规则很简单:SCL 高电平时,SDA 上的数据必须稳定。数据变化只能在 SCL 低电平时发生。
你想想看,如果 SCL 高电平时 SDA 还在跳变,那从设备该在哪个时刻采样?所以这个规则是 I2C 通信的基石。
我记得有一次调试一个温湿度传感器,读出来的数据总是跳变。用示波器一看,SDA 在 SCL 高电平时有毛刺。查了半天,发现是 PCB 走线太长,信号反射造成的。加了个 33pF 的小电容滤波,问题解决。
- SCL = 高电平 → SDA 数据必须稳定(从设备在此采样)
- SCL = 低电平 → SDA 数据可以变化(主机在此更新数据)
1.4 应答机制——从设备说“收到”还是“没收到”
I2C 的应答机制,是它比 SPI 更可靠的原因之一。每次主机发送完 8 位数据后,会释放 SDA,然后产生第 9 个 SCL 时钟。从设备如果拉低 SDA,表示ACK(应答);如果保持高电平,表示NACK(非应答)。
ACK 和 NACK 的含义
| 信号 | SDA 状态(第 9 个 SCL) | 含义 |
|---|---|---|
| ACK | 低电平 | 从设备已收到数据,可以继续发送 |
| NACK | 高电平 | 从设备未准备好、数据错误或传输结束 |
为什么会收到 NACK?常见原因有:
- 从设备地址不对(地址不匹配)
- 从设备正忙(比如还在处理上一条指令)
- 主机发送了不支持的寄存器地址
- 从设备接收缓冲区已满
1.5 本章知识体系总览
下面这张图,把 I2C 协议基础的核心逻辑串起来了。从物理层到应答机制,每一步都是环环相扣的。
这张图把 I2C 协议基础的五个核心模块串起来了。从物理层的两根线开始,到起始条件、数据有效性、应答机制,最后以停止条件结束。每个环节出问题,通信就会失败。