1. I2C协议基础:从一根线到两根线的故事

各位同学,咱们今天聊聊I2C协议的基础。说实话,我刚入行那会儿,觉得I2C就是个简单的两根线通信,没什么好学的。结果呢?第一次调瑞芯微的板子,I2C死活不通,折腾了两天才发现是上拉电阻选错了。从那以后,我再也不敢小看这个“简单”的协议了。

1.1 I2C总线的起源

I2C(Inter-Integrated Circuit)总线是飞利浦公司在1982年推出的。当时他们想解决一个很实际的问题:芯片之间通信需要太多引脚了。你想想看,如果每个外设都用自己的并行总线,那PCB上得走多少线?

所以飞利浦提出了一个方案:只用两根线——SDA(数据线)和SCL(时钟线),就能让多个设备互相通信。这就是I2C的雏形。后来这个标准被NXP(恩智浦)继承,一直用到现在。

核心特点:

  • 两根线:SDA(串行数据线)和SCL(串行时钟线)
  • 多主多从:总线上可以挂多个主设备和从设备
  • 同步通信:由主设备产生时钟,从设备跟随
  • 地址寻址:每个从设备有唯一的7位或10位地址

1.2 物理层特性:SDA和SCL

咱们先看看这两根线到底长什么样。SDA和SCL都是双向的,也就是说数据可以双向传输。但有个关键点:这两根线都是开漏输出结构。

什么叫开漏输出?说白了,就是芯片只能把引脚拉低到GND,但不能主动拉高到VDD。高电平是靠外部上拉电阻实现的。我刚开始不理解为什么这么设计,后来才明白——这样做的好处是多个设备可以“线与”,任何一个设备拉低总线,总线就是低电平,不会发生短路。

特性 SDA(数据线) SCL(时钟线)
方向 双向 主设备输出,从设备可拉低(时钟拉伸)
输出类型 开漏 开漏
空闲状态 高电平(由上拉电阻拉高) 高电平(由上拉电阻拉高)
数据传输 SCL低电平时改变数据,高电平时采样 产生时钟脉冲

1.3 电气特性与上拉电阻选择

嗯,这里要重点讲一下。上拉电阻的选择直接决定了你的I2C能不能正常工作。我在项目中遇到过好几次,板子画好了,I2C通信时好时坏,最后发现就是上拉电阻值不对。

上拉电阻的作用:

  • 在总线空闲时,将SDA和SCL拉高到VDD
  • 提供足够的电流,保证信号上升沿满足时序要求
  • 限制总线短路时的电流

电阻值怎么选? 这里有个经验公式:

R_pullup(min) = (VDD - VOL_max) / IOL_max
R_pullup(max) = Trise_max / (Cbus × 0.8473)

其中:

  • VDD:总线供电电压(常见3.3V或1.8V)
  • VOL_max:低电平输出电压最大值(通常0.4V)
  • IOL_max:开漏输出最大灌电流(通常3mA或20mA,看规格书)
  • Trise_max:最大允许上升时间(标准模式1000ns,快速模式300ns)
  • Cbus:总线总电容(包括引脚电容、走线电容等)

我的经验值:

  • 3.3V系统,标准模式(100kHz):4.7kΩ ~ 10kΩ
  • 3.3V系统,快速模式(400kHz):2.2kΩ ~ 4.7kΩ
  • 1.8V系统:1kΩ ~ 2.2kΩ(因为电压低,需要更小的电阻提供足够电流)
  • 总线设备多(>8个)或走线长(>20cm):适当减小电阻

避坑指南: 我曾经在一个项目里,用了10kΩ上拉电阻,总线电容大约200pF,结果400kHz模式下上升沿太慢,数据采样出错。后来换成3.3kΩ,问题解决。所以,高速模式一定要算上升时间,别偷懒。

1.4 I2C总线拓扑结构

咱们用一张图来看看I2C总线是怎么连接的。下面这张SVG图展示了典型的多设备I2C总线结构:

I2C总线拓扑结构 Rₚ Rₚ VDD (3.3V) SDA SCL 主设备 (瑞芯微SoC) 从设备1 (温度传感器) 从设备2 (EEPROM) 从设备3 (ADC转换器) 关键说明: • 所有设备的SDA引脚都连接到同一条SDA线上 • 所有设备的SCL引脚都连接到同一条SCL线上 • 上拉电阻Rₚ连接在SDA/SCL与VDD之间 • 每个从设备有唯一地址,主设备通过地址选择通信对象

1.5 总线电容与传输距离

I2C总线的传输距离受限于总线电容。标准模式下,最大总线电容是400pF;快速模式是400pF;高速模式是100pF。你想想看,每增加一个设备,每增加一厘米走线,电容都在增加。

典型电容估算:

  • 每个IC引脚:约5pF ~ 10pF
  • PCB走线:约0.5pF/cm ~ 1pF/cm
  • 连接器/排线:约10pF ~ 30pF

实战建议: 我在瑞芯微RK3588的板子上调试时,挂了6个I2C从设备,总线长度约15cm。算下来电容大约120pF,用4.7kΩ上拉电阻,400kHz跑得很稳。但如果你的总线超过20cm,或者设备超过10个,建议用I2C总线缓冲器(如PCA9517)来扩展。

1.6 电平兼容性问题

现在很多系统是混合电压的。比如瑞芯微SoC是1.8V IO,但外设可能是3.3V或5V。这时候直接连会烧芯片。怎么办?

常见解决方案:

  1. 电平转换器:专用芯片如PCA9306、TXS0102
  2. MOSFET分立方案:用N沟道MOSFET搭建双向电平转换
  3. 直接连接(谨慎):如果从设备IO能容忍1.8V,且主设备IO是5V容忍,可以直连

血的教训: 我曾经图省事,把1.8V的RK3588 I2C直接连到一个3.3V的传感器上,结果传感器输出高电平时,RK3588的IO口承受了3.3V电压,虽然没立刻烧,但一个月后批量返修。从那以后,我再也不敢跨电压直连I2C了。

1.7 本章小结

好了,咱们把I2C协议基础捋一遍:

  • I2C是两根线的串行总线,SDA传数据,SCL传时钟
  • 开漏输出 + 上拉电阻是核心电气结构
  • 上拉电阻选值要算最小值和最大值,别凭感觉
  • 总线电容限制了设备数量和传输距离
  • 不同电压域必须用电平转换