第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的仲裁机制,说白了就是谁先拉低,谁就赢

具体怎么工作的?

  1. 多个主设备同时发送起始条件
  2. 它们各自在SDA上发送自己的地址
  3. 每个主设备都在每个时钟周期检查SDA电平
  4. 如果某个主设备想发高电平,但SDA被别的设备拉低了
  5. 这个主设备就知道自己输了,自动退出

为什么会这样?因为开漏结构下,低电平是「强」的。一个设备拉低,其他设备想拉高也拉不起来。

重要原则:仲裁过程中,输掉的主设备不会破坏总线上的数据。它只是默默地停止发送,等待下一次机会。

我记得有一次调试多主设备系统,两个MCU同时访问同一个流量传感器。一开始我担心会出乱子,但实际测试发现I2C仲裁处理得干干净净。输掉的那个MCU自动重试,整个过程对上层应用完全透明。

仲裁的几种情况

  • 地址仲裁:多个主设备发不同地址,地址小的赢
  • 数据仲裁:地址相同,数据位低的赢
  • 起始条件仲裁:谁先拉低SDA谁赢

避坑指南:我曾经遇到过一个问题,两个主设备同时发相同地址和数据,结果总线一直处于仲裁状态,谁都没法完成传输。后来发现是软件里没有加随机重试延时。解决办法很简单:每个主设备在检测到仲裁失败后,加一个随机延时再重试。

2.5 实际设计中的注意事项

做制氧机流量传感器项目时,我总结了几条经验:

  • 走线长度:SDA和SCL尽量等长,别超过20cm
  • 地线处理:两根线旁边最好跟一条地线,减少串扰
  • 电容限制:总线上所有设备的总电容不要超过400pF
  • 电平匹配:如果主设备是3.3V,从设备是5V,记得加电平转换

嗯,这些细节看着不起眼,但往往就是它们决定了你的产品能不能稳定工作。

下一章,我们会深入I2C的协议层,看看数据是怎么在SDA和SCL的配合下,从传感器传到MCU的。