1. I2C总线基础:协议起源、物理层特性与总线拓扑
各位工程师朋友,咱们今天聊聊I2C总线的基础。说实话,我调试过不下几十种I2C设备,从几毛钱的温度传感器到高端的图像传感器,都打过交道。很多朋友一上来就抓波形、看时序,结果越调越乱。为什么?因为物理层的东西没吃透。
I2C这玩意儿,1982年由Philips(现在的NXP)发明。初衷很简单——让芯片之间少连几根线。你想啊,如果每个外设都独立连线,板子上早就乱成蜘蛛网了。I2C只用两根线,就能挂一堆设备,这在当年绝对是革命性的。
1.1 物理层核心:SDA和SCL
I2C总线就两条线:SDA(串行数据线)和SCL(串行时钟线)。但这两根线有个关键特性——开漏输出。
什么叫开漏?说白了,就是芯片只能把线拉低,不能主动拉高。要拉高怎么办?靠上拉电阻。所以总线空闲时,SDA和SCL都是高电平。
核心要点:开漏结构允许多个设备共用总线,谁想发数据,谁就把线拉低。不会打架,因为低电平永远“赢”。这就是所谓的“线与”逻辑。
我个人习惯,在设计阶段就把上拉电阻算清楚。阻值选大了,上升沿太慢;选小了,功耗高,还可能拉不动。标准模式下,4.7kΩ是个常用值,但具体要看总线电容和速率。
| 模式 | 最大速率 | 典型上拉电阻 | 最大总线电容 |
|---|---|---|---|
| 标准模式 (Sm) | 100 kbit/s | 4.7kΩ – 10kΩ | 400 pF |
| 快速模式 (Fm) | 400 kbit/s | 1.5kΩ – 4.7kΩ | 400 pF |
| 快速+模式 (Fm+) | 1 Mbit/s | 1kΩ – 2.2kΩ | 550 pF |
| 高速模式 (Hs) | 3.4 Mbit/s | 0.5kΩ – 1kΩ | 100 pF |
避坑指南:我曾经在一个项目里,为了省电把上拉电阻换成了100kΩ。结果总线上升沿慢得像蜗牛,通信时好时坏。抓波形一看,SCL的上升沿都快赶上半个时钟周期了。从那以后,我选电阻一定先算上升时间常数τ = RC,确保小于时钟周期的10%。
1.2 电气特性与电平标准
I2C的电气特性,说白了就是电压阈值。不同供电电压下,高低电平的判断标准不一样。
举个例子,3.3V系统里,输入低电平阈值是0.3×VDD ≈ 0.99V,输入高电平阈值是0.7×VDD ≈ 2.31V。也就是说,只要SDA/SCL上的电压低于0.99V,就认为是低电平;高于2.31V,就认为是高电平。
嗯,这里要注意:如果总线上混接3.3V和5V器件,必须做电平转换。我见过有人直接把3.3V的MCU和5V的EEPROM连在一起,结果MCU的IO口被烧了。为什么?因为5V器件输出的高电平是5V,超过了3.3V器件的耐压。
| 参数 | 条件 | 最小值 | 最大值 | 单位 |
|---|---|---|---|---|
| VIL (输入低电平) | 固定输入电平 | -0.5 | 0.3×VDD | V |
| VIH (输入高电平) | 固定输入电平 | 0.7×VDD | VDD+0.5 | V |
| VOL (输出低电平) | IOL = 3mA | 0 | 0.4 | V |
| IOL (灌电流) | VOL = 0.4V | 3 | — | mA |
1.3 总线拓扑与设备寻址
I2C是多主从总线结构。什么意思?就是总线上可以有多个主设备,但同一时刻只能有一个主设备控制时钟。从设备呢,就是被主设备点名才能说话。
每个从设备都有一个唯一的7位或10位地址。7位地址最多挂127个设备(地址0x00是广播地址,不能用)。实际项目中,挂十几个设备就差不多了,再多总线电容就超标了。
小技巧:调试时如果找不到设备,先检查地址对不对。我遇到过好几次,数据手册上写的地址是7位,但代码里写成了8位(左移了一位)。结果设备死活不应答。你想想看,地址都错了,设备怎么可能理你?
总线拓扑上,所有设备的SDA连在一起,SCL连在一起。每个设备都是开漏输出,加上拉电阻到VDD。这种结构的好处是:任意设备都可以拉低总线,不会发生短路。
但有个坑——总线电容。每挂一个设备,就会增加几pF到十几pF的引脚电容。加上PCB走线的分布电容,总电容很容易超过400pF。一旦超标,上升沿变慢,时序就乱了。
我曾经在一个项目里挂了8个设备,总线长度超过30cm。结果400kHz下通信完全乱套。后来把速率降到100kHz,又优化了上拉电阻,才稳定下来。所以,长距离或多设备场景,我建议要么降速,要么加I2C总线缓冲器(如PCA9517)。
1.4 知识结构总览
下面这张图,把I2C物理层的核心知识点串起来了。你可以把它当作调试时的检查清单。
1.5 常见问题与排查思路
调试I2C,说白了就是跟物理层较劲。我总结了几条经验:
- SCL拉不低? 检查从设备是否处于死锁状态。有时候从设备异常,会把SCL一直拉低。解决办法:给SCL来9个时钟脉冲,强制复位从设备。
- SDA一直高? 看看上拉电阻是不是焊错了,或者没焊。我遇到过PCB上电阻虚焊,SDA浮空,通信全挂。
- 地址应答没有? 先确认地址对不对(7位还是8位),再确认设备供电是否正常。别笑,我见过有人忘了给传感器供电,查了半天。
- 偶尔通信失败? 大概率是噪声或总线电容超标。降速试试,或者加个33pF的小电容滤波。
一句话总结:I2C物理层就三件事——开漏输出、上拉电阻、总线电容。这三样搞明白了,80%的I2C问题你都能自己解决。