I2C 物理层:SCL、SDA、上拉电阻
咱们搞 I2C,首先得把这物理层吃透。说白了就是两根线:SCL 和 SDA。再加上一个不能少的上拉电阻。
别小看这三样东西。我见过太多工程师,程序写得很漂亮,最后栽在这最简单的硬件上。来,咱们从头捋一遍。
SCL 和 SDA:两根线的故事
SCL 是时钟线,由主机控制。SDA 是数据线,双向的。
有意思的地方在于,这两根线都是开漏输出。什么叫开漏?就是输出只能拉低,不能主动拉高。想发高电平?靠外部电阻帮你拉上去。
我刚开始做 I2C 时,总想把 SCL 和 SDA 当成普通 GPIO,直接推挽输出。结果呢?总线冲突,通信乱得一塌糊涂。嗯,后来才明白,开漏结构是为了避免多个设备同时驱动线路。谁想拉低就拉低,想高?大家一起放手,让电阻来干。
上拉电阻:为什么必须要有?
没有上拉电阻,你的 I2C 总线就是个哑巴。开漏输出默认是高阻态,不接电阻,线路电压就悬空了,读到的都是随机值。
电阻的取值很关键。太小了,驱动电流大,费电。太大了,上升沿变慢,跑不出高速。你想想看,100kHz 和 400kHz 模式下,对电阻的要求是不一样的。
| 总线模式 | 推荐上拉电阻范围 | 典型值 |
|---|---|---|
| 标准模式(100kHz) | 4.7kΩ ~ 10kΩ | 4.7kΩ |
| 快速模式(400kHz) | 2.2kΩ ~ 4.7kΩ | 3.3kΩ |
| 高速模式(3.4MHz) | 1kΩ ~ 2.2kΩ | 1.5kΩ |
我个人习惯先看 VDD,再选电阻。5V 系统用 4.7kΩ 起步,3.3V 系统用 2.2kΩ 或 3.3kΩ。如果有多个设备,电阻可以适当减小。
上拉电阻怎么算?给个公式
工程设计不能光靠感觉。两个边界你得心里有数:
- 最小值:保证输出低电平时,电流不超标。Rmin = (VDD - VOL) / IOL。VOL 一般是 0.4V,IOL 看器件手册,通常 3mA 左右。
- 最大值:保证上升沿时间满足时序要求。Rmax = trise / (0.8473 × Cbus)。Cbus 包括所有设备的引脚电容和走线电容。
举个例子。3.3V 系统,总电容 100pF,要求上升沿 300ns:
Rmin = (3.3 - 0.4) / 0.003 ≈ 966Ω
Rmax = 300e-9 / (0.8473 × 100e-12) ≈ 3540Ω
所以阻值在 1kΩ 到 3.5kΩ 之间。取中值 2.2kΩ 或者 3.3kΩ 都行。
总线电容:你看不见的敌人
I2C 的设计其实很脆弱。每条线的最大电容都有上限。标准模式 400pF,快速模式 400pF,高速模式 100pF。超过这个数,波形就完蛋了。
电容从哪里来?
- 每个器件的引脚电容,通常在 5~10pF
- PCB 走线的寄生电容,大约 1pF/cm
- 过孔、接插件、线缆,每项都能加上几 pF
我建议你算个总数。比如接了 10 个设备,每个 10pF,就是 100pF。走线 30cm,再加 30pF。嗯,这已经 130pF 了,离 400pF 还有余量,但如果你用长线缆,分分钟超限。
硬件布局的几条铁律
你可能觉得布局是 PCB 工程师的事。错了,做 I2C 的都得懂。我有几条死规矩:
- 上拉电阻要靠近主机放,不要放在从机那边。
- SCL 和 SDA 两条线要尽量等长,不要绕大圈。
- 避免在总线中间分支,最好用菊花链拓扑。
- 电源旁路电容要靠近每个 I2C 器件,减少电源噪声耦合到总线上。
有一次项目赶进度,布局工程师把上拉电阻放在了总线的末端,离主机 15cm 远。结果 400kHz 跑不起来,非降速到 100kHz 才行。后面改了一版板子才解决。教训啊。
总结一下要点
- SCL/SDA 是开漏输出,必须配上拉电阻,这是 I2C 的核心机制。
- 上拉电阻取值需要平衡电流和上升时间,4.7kΩ 是通用起点。
- 总线电容是隐形的瓶颈,超过 400pF 必须处理。
- 硬件布局也决定了通信稳定性。上拉电阻靠近主机,走线尽量短。
把这些基础打扎实了,后面讲地址冲突检测时,你才能自信地说「我硬件没问题」。遇到 I2C 通信异常,第一步永远是检查物理层。波形对不对?上拉阻值对不对?总线电容有没有超标?别跳步骤,先解决物理层的问题,再往下查。