第2章:I2C总线基础
2.1 物理层:SDA与SCL
I2C总线,说白了就是两根线走天下。一根叫SDA(数据线),一根叫SCL(时钟线)。
我刚开始接触I2C时,总觉得两根线能传数据很神奇。后来做项目多了,才明白它的巧妙之处。
SDA(Serial Data Line):负责传输数据。数据是一位一位地在时钟的配合下传出去的。
SCL(Serial Clock Line):负责提供时钟同步。谁控制时钟,谁就是主设备。
这两根线都是双向的。什么意思?就是主设备能拉低,从设备也能拉低。嗯,这里要注意,它们都是开漏输出结构。
关键点:I2C总线上的所有设备,SDA和SCL引脚都是开漏输出。没有设备能主动输出高电平,只能拉低或释放。
2.2 电气特性
I2C的电气特性,其实没那么复杂。我给大家拆开讲。
- 高电平:由外部上拉电阻拉到VDD(通常是3.3V或5V)
- 低电平:由设备内部的开漏MOS管拉低到GND
- 逻辑阈值:VIL最大0.3VDD,VIH最小0.7VDD
举个例子,3.3V供电的系统:
- 低于0.99V算低电平
- 高于2.31V算高电平
- 中间区域?那是禁区,千万别让信号停在那里
我曾经踩过的坑:有一次调试制氧机流量传感器,发现通信时好时坏。查了半天,原来是电源纹波太大,导致逻辑电平刚好卡在阈值附近。从那以后,我设计电路时都会给I2C加个干净的LDO供电。
2.3 上拉电阻选择
上拉电阻,这是I2C设计里最容易出问题的地方。选大了不行,选小了也不行。
电阻选太大:上升沿变慢,高速通信时波形像老太太爬山——慢吞吞的。
电阻选太小:功耗变大,而且从设备可能拉不动。
怎么选?我一般用这个经验公式:
Rp(min) = (VDD - VOL(max)) / IOL(max)
Rp(max) = Trise / (0.8473 × Cbus)
其中:
- VOL(max):低电平最大值,通常0.4V
- IOL(max):从设备最大灌电流,通常3mA
- Trise:允许的最大上升时间(标准模式1000ns,快速模式300ns)
- Cbus:总线总电容(包括引脚电容和走线电容)
给大家一个参考表:
| 总线电容 | 标准模式(100kHz) | 快速模式(400kHz) |
|---|---|---|
| 50pF | 4.7kΩ ~ 10kΩ | 1.5kΩ ~ 4.7kΩ |
| 100pF | 2.2kΩ ~ 4.7kΩ | 1kΩ ~ 2.2kΩ |
| 200pF | 1kΩ ~ 2.2kΩ | 不推荐 |
我个人习惯:做制氧机这类产品,我一般先选4.7kΩ。如果通信距离长或者设备多,再降到2.2kΩ。别一上来就用1kΩ,功耗会让你头疼。
2.4 总线仲裁机制
总线仲裁,这是I2C最巧妙的设计之一。你想想看,多个主设备挂在同一根线上,万一同时发数据怎么办?
I2C的仲裁机制,说白了就是谁先拉低,谁就赢。
具体怎么工作的?
- 多个主设备同时发送起始条件
- 它们各自在SDA上发送自己的地址
- 每个主设备都在每个时钟周期检查SDA电平
- 如果某个主设备想发高电平,但SDA被别的设备拉低了
- 这个主设备就知道自己输了,自动退出
为什么会这样?因为开漏结构下,低电平是「强」的。一个设备拉低,其他设备想拉高也拉不起来。
重要原则:仲裁过程中,输掉的主设备不会破坏总线上的数据。它只是默默地停止发送,等待下一次机会。
我记得有一次调试多主设备系统,两个MCU同时访问同一个流量传感器。一开始我担心会出乱子,但实际测试发现I2C仲裁处理得干干净净。输掉的那个MCU自动重试,整个过程对上层应用完全透明。
仲裁的几种情况:
- 地址仲裁:多个主设备发不同地址,地址小的赢
- 数据仲裁:地址相同,数据位低的赢
- 起始条件仲裁:谁先拉低SDA谁赢
避坑指南:我曾经遇到过一个问题,两个主设备同时发相同地址和数据,结果总线一直处于仲裁状态,谁都没法完成传输。后来发现是软件里没有加随机重试延时。解决办法很简单:每个主设备在检测到仲裁失败后,加一个随机延时再重试。
2.5 实际设计中的注意事项
做制氧机流量传感器项目时,我总结了几条经验:
- 走线长度:SDA和SCL尽量等长,别超过20cm
- 地线处理:两根线旁边最好跟一条地线,减少串扰
- 电容限制:总线上所有设备的总电容不要超过400pF
- 电平匹配:如果主设备是3.3V,从设备是5V,记得加电平转换
嗯,这些细节看着不起眼,但往往就是它们决定了你的产品能不能稳定工作。
下一章,我们会深入I2C的协议层,看看数据是怎么在SDA和SCL的配合下,从传感器传到MCU的。