第9课(四):I²C,两根线挂很多器件

硬件学习路线 · 通信接口之四 · 同步、半双工、多主多从,只用 SDA 与 SCL 两根线,是 EEPROM、传感器和小屏幕的常用接口

一、什么是 I²C?

I²C(Inter-Integrated Circuit,读作 I-squared-C),由飞利浦(现在的 NXP)提出,是一种同步串行总线:只有两根线,SDA(数据)和 SCL(时钟),却可以挂几十个器件。每个器件有自己的地址,主机用地址找到它。

类比:I²C 像一个学校的广播系统:两根线是整个学校共用的喇叭线路。每个班级(器件)有自己的班号(地址)。老师(主机)先广播"请 3 班回答",只有 3 班会应答,其它班保持安静。所有人都能听到广播,但只有被点名的人才回应。
与 SPI 的最大不同:SPI 每挂一个从机多一根片选线;I²C 不需要片选,靠地址区分。代价是速度相对低,而且协议更复杂一些。

二、两根线与开漏结构

I²C 双线总线与上拉 示意图:每条线独立上拉
VDDRp SDARp SCLSDASCL主机开漏接口从机 A开漏接口从机 B开漏接口两根总线互不短接,SDA 与 SCL 各有一个上拉电阻

2.1 为什么必须是开漏?

I²C 上的每一个器件,SDA 和 SCL 都只能拉低,不能主动拉高。高电平靠外部的上拉电阻拉起来。这样做的原因是:如果两个器件一个想拉高、一个想拉低,推挽输出会直接短路;而开漏结构下,只要有一个器件拉低,线就是低,不会短路。这叫线与关系。

记住这一点:I²C 的线上没有"主动拉高"的器件。线是高的,只是因为上拉电阻把它抬起来,并且没有人拉低它。第9课(总览)讲过的开漏输出,正是为这个场景设计的。

2.2 主机与从机

三、上拉电阻:怎么算?

上拉电阻 Rp 不能随便取。它太大,线上升太慢,速率上不去;它太小,拉低时电流太大,器件(尤其是 SDA 的下管)承受不了。取值要同时满足两个条件:

Rmax = tr / (0.8473 × Cb) (上升时间 tr 的限制,决定速率上限) Rmin = (VDD − VOL) / IOL (下拉电流 IOL 的限制,决定最小阻值) tr:上升时间(标准模式 1000 ns,快速模式 300 ns);Cb:总线总电容(pF,含线缆和所有器件);VOL:低电平(约 0.4 V);IOL:允许吸收的电流(通常 3 mA)

3.1 动手算一算

Rmax(速率允许的上限)-
Rmin(电流允许的下限)-
你选的 Rp 是否合适-
常见取值:3.3 V 系统、短总线,4.7 kΩ 是最常见的选择;速率要求高或线较长时,减小到 2.2 kΩ 左右。具体以器件手册和实测波形为准(用示波器看上升沿是否在时序允许范围内)。

四、START、STOP、ACK:三个特殊信号

信号SCL 为高时,SDA 怎样变化作用
START(起始)SDA 从高变低(SCL 保持高)宣布"一次通信开始"
STOP(停止)SDA 从低变高(SCL 保持高)宣布"一次通信结束",总线回到空闲
ACK(应答)接收方在第 9 个时钟把 SDA 拉低表示"我收到了,请继续";保持高则为 NACK(无应答)
类比:START 像敲门、STOP 像关门。数据在 SCL 低电平时准备好,在 SCL 高电平时被读取。只有 START 和 STOP 时,SDA 可以在 SCL 为高时变化,这正是它们被识别为特殊信号的原因。
规则必须牢记:数据位在 SCL 为低时才能改变;在 SCL 为高时,SDA 必须保持稳定,被对方读取。唯一的例外是 START 和 STOP。

五、动手看一帧数据

一帧通常是:START → 地址字节(7 位地址 + 1 位读写位)→ ACK → 数据字节 → ACK → …… → STOP。下面演示发送一个地址字节加 ACK,选择地址与读写方向。

上:SCL(时钟,主机给) 下:SDA(数据,两边共用)
读这张图的方法:先找 START(SDA 在 SCL 高时下降),再逐位读 SDA(每个 SCL 高脉冲时读一位),然后看第 9 位是否有 ACK(从机把 SDA 拉低)。

六、地址:7 位与 8 位的坑

I²C 的地址通常是 7 位。发送时,地址后面再跟一位读写位,合起来正好是一个字节。因此资料里常见两种写法,很容易搞混:

写法含义例子(7 位地址 0x3C 的 OLED)
7 位地址只包含地址本身0x3C
8 位写地址7 位地址左移一位,最低位为 0(写)0x78(0x3C << 1)
8 位读地址7 位地址左移一位,最低位为 1(读)0x79
发送的第一个字节 = (7 位地址 << 1) | R/W 例:MPU6050 地址 0x68,写地址 = 0xD0,读地址 = 0xD1。很多人把 0xD0 当成地址,结果找不到器件
地址冲突:同一条总线上两个器件地址相同,会同时响应,数据全乱。例如 DS3231 与 MPU6050 都是 0x68,不能挂在同一条总线上(除非有地址脚可以改)。选器件时要先查地址表。
找不到器件时:可以写一个"扫描程序",依次对 0x08 ~ 0x77 每个地址发送 START 并看有没有 ACK。这是 I²C 调试最实用的方法。

七、速率与总线电容

模式速率说明
标准模式100 kbps最通用,兼容性最好
快速模式400 kbps大多数传感器与 EEPROM 支持
快速模式 +1 Mbps较少见,要求高
每一帧的大致时间 ≈ (字节数 + 1)× 9 位 / 速率 例:400 kbps 下,写 1 字节(加地址共 2 字节)约 2 × 9 / 400000 ≈ 45 μs
总线电容越大,波形越慢:线越长、器件越多,Cb 越大,上升沿越缓。Cb 超过 400 pF 时,I²C 的规范就不再保证正常工作。所以 I²C 适合板内或短线,远距离要换 RS485 或加专门的总线扩展芯片。

八、常见问题排查

现象最可能的原因怎么查
完全没有 ACK,找不到器件地址写错(7 位与 8 位混淆)、没有上拉、接线错用扫描程序;量 SDA、SCL 是否有上拉电压
SDA 或 SCL 一直被拉低,总线"卡死"从机在通信中途出错,仍占着线;或某个器件短路断电重启;用主机发几个时钟脉冲恢复("总线清除")
偶尔出错、数据乱跳上拉太大、线太长、速率太高、干扰减小上拉电阻,降低速率,缩短线路
两个器件同时响应地址冲突更换器件,或使用地址脚改变地址
3.3 V 与 5 V 器件混用出错电平不匹配,5 V 器件把 SDA 拉高到 5 V用电平转换器(双向 MOSFET 或专用芯片)
总线卡死的类比:班上一个同学一直举着手不放(SDA 被拉低),其它人就没法说话。解决办法不是责怪大家,而是让老师(主机)发几次时钟,引导那个同学放下手。

九、小测验:I²C

十、本节小结

回到本课总览:第9课(总):GPIO 与通信接口总览

本课五页:总览 · UART · RS485 · SPI · I²C