3. I2C总线物理层:SDA/SCL,上拉电阻,电平标准

说实话,很多人做 I2C 通信,上来就写代码调时序,结果波形乱七八糟。我见过不少工程师拿着逻辑分析仪抓到的信号,愣是看不出问题在哪。其实根子多半在物理层——SDA、SCL 这两根线,配上拉电阻和电平标准,才是整个总线的基础。这章我们就把它彻底聊透。

3.1 两条线的使命:SDA 和 SCL

I2C 总线只有两根线:串行数据线 SDA 和串行时钟线 SCL。所有的通信都靠它们完成。你想想看,多设备共用两条线,全靠主设备来控制时钟,从设备响应数据。没有独立的片选线,所以通讯协议里必须要有地址和应答机制,这是后话。

SDA(Serial Data Line):数据线,双向传输。主设备发送地址、控制指令和数据,从设备返回数据或应答。

SCL(Serial Clock Line):时钟线,由主设备驱动。每个时钟脉冲传递一位数据。从设备可以拉低 SCL(时钟拉伸)来要求主设备等待,这在低速从设备中很常见。

我个人的布线习惯:在 PCB 上尽量让 SDA 和 SCL 走线靠近,长度相等,避免走直角。不然信号反射会导致边沿变缓,上拉电阻选再大也白搭。

3.2 开漏输出与上拉电阻——为什么必须这么做?

I2C 总线采用 开漏(Open Drain) 结构。说白了,每个设备的 SDA 和 SCL 引脚内部只有一个 N-MOS 管,只能拉低到 GND,不能主动输出高电平。高电平全靠外部上拉电阻提供。

为什么要这么设计? 为了支持多设备仲裁。如果两个设备同时拉低总线,不会短路,因为开漏结构只能拉低;而且总线仲裁靠的是「线与」逻辑——谁先拉低谁赢。这是 I2C 能挂多个从设备的根本原因。

上拉电阻取值

电阻选不好,问题一大堆。电阻太大,上升沿太慢,通讯频率上不去;电阻太小,灌电流太大,会烧端口甚至影响功耗。我个人一般遵循这样的经验:

场景 推荐阻值(Ω) 依据
标准模式(100kHz) 4.7k ~ 10k 上升时间满足 < 1µs
快速模式(400kHz) 2.2k ~ 4.7k 上升时间 < 300ns
快速+模式(1MHz) 1k ~ 2.2k 上升时间 < 120ns
低速/长线(> 50cm) 2.2k ~ 3.3k 补偿线缆电容

我曾在一个项目里用过 100k 上拉电阻,想省电。结果 400kHz 通讯时波形像正弦波,数据一塌糊涂。所以别乱省,算一下 RC 常数:τ = R × Cbus,其中 Cbus 包括所有从设备引脚电容和 PCB 走线寄生电容(一般 10 ~ 30 pF)。上升时间 ≈ 2.2τ,保证上升时间小于 1/10 的时钟周期就没问题。

避坑指南:我曾经把上拉电阻接到 3.3V 上,但从设备是 5V 电平,结果 SDA/SCL 高电平时只有 3.3V,从设备不认。原因是 I2C 电平必须满足从设备 VIH 门槛。所以电阻的电源电压必须与所有设备兼容。

3.3 电平标准:TTL/CMOS 与非标准混合坑

I2C 规范其实并没有规定固定的电平,而是定义了 逻辑门槛。标准模式下 VIL max = 0.3×VDD,VIH min = 0.7×VDD。但实际中我们常遇到 3.3V 主控和 5V 从设备混搭的情况。怎么办?

常用方案:

  • 电平转换芯片:如 PCA9306、TXS0102。简单可靠。
  • 分立 MOS 管电路:2N7002 搭双向电平转换。省钱但占面积。
  • 纯开漏容忍:部分 IC 的引脚支持 5V 容忍,直接上拉到 5V,但主控必须检查耐压。

我个人建议:如果项目周期紧,用专用电平转换芯片省心。但如果你手头只有电阻和三极管,也可以用下面这个经典电路——注意,只适用于低速场合(100kHz 以下)。

# 简易双向电平转换(3.3V<->5V)
# 使用一个 N-MOSFET(如 BSS138/NTS2101)
# 连接方式:
# 3.3V 侧:SDA_3V3 → 漏极 (D)
# 5V 侧:   SDA_5V  → 源极 (S)
# 栅极 (G) → 3.3V 电源
# 两端各接一个上拉电阻到各自电源域
# SCL 同理

常见电平组合实测经验

主控电压 从设备电压 能否直连? 我的建议
3.3V 3.3V √ 直接连 电阻选 4.7k,OK
3.3V 5V × 不能直连 用电平转换或分压?I2C是双向,分压不行
5V 3.3V ⚠️ 看从设备容忍 若从设备 5V 容忍则上拉到 5V;否则必须转换
1.8V 3.3V × 必须电平转换

3.4 物理层核心知识结构图

下面这张图把 I2C 物理层的关键要素串在一起。你在调试时遇到波形异常,按这个结构去排查:先看电平是否匹配,再查上拉电阻,最后看走线负载。

I2C 物理层核心要素 总线:SDA + SCL 开漏输出,双向,共地 电平标准 VIL = 0.3×VDD VIH = 0.7×VDD 上拉电阻 1k ~ 10k 典型 τ = R × Cbus 寄生与走线 容性负载 10~40 pF 等长/屏蔽/避免直角 同电压 直接连 混合电平 加转换 5V 容忍 查手册 阻值选择 查表计算 电源选择 Vpullup 容性负载 影响上升沿 走线长度 > 20cm 需处理 ⚠️ 调试时:先量静态电平,再看上升沿,最后查时序

3.5 总结:物理层决定稳定性

嗯,说白了 I2C 的物理层并不复杂,但坑真不少。我在一个量产项目中就因为上拉电阻用了 10k 而总线容性负载超过 40pF,导致 400kHz 下上升沿接近 2µs,数据错误率高达 30%。后来换成 2.2k 电阻才稳定。记住几点:

  • 用逻辑分析仪看 SDA/SCL 的上升沿,如果斜率缓得像三角波,先检查上拉电阻和总线电容。
  • 混合电平必须转换,别偷懒直连。
  • 留一点余量:上拉电阻取推荐范围的下限(功耗允许时)。
调试清单:① 确认 Vpullup 与所有设备电平兼容;② 用示波器测 SDA/SCL 高电平是否为 Vpullup;③ 测上升时间是否小于时钟周期的 1/10;④ 检查是否有从设备偷偷拉低 SCL(时钟拉伸导致的时序异常)。这四条走一遍,90% 的物理层问题都能定位。