你的 I2C 为什么没反应?
I2C 总线死锁、波形毛刺、地址冲突、时钟拉伸……
两根线能玩出多少种不工作的花样?
你做的 AI 门禁系统已经能识别出人脸,通过 UART 把结果发给了显示屏,又通过 SPI 读到了温湿度。
现在你想挂一个 I2C 接口的传感器——比如一个 EEPROM 保存配置,或者一个环境光传感器。
接上两根线:SDA、SCL,加上上拉电阻,写代码,运行——
读不到数据。
用示波器一看,波形上全是毛刺,ACK 信号时有时无。
问题出在哪?
大概率是:你对 I2C 只知其然,不知其所以然。
本期是 Comake 硬件科普第三期,带你彻底搞懂 I2C 总线。
读完你会知道:
1️⃣ I2C 与串口、SPI 相比有什么优缺点
2️⃣ I2C 协议的核心时序:起始、地址、数据、应答、停止
3️⃣ 常见的波形毛刺是怎么产生的,怎么解决
4️⃣ 时钟拉伸、多主仲裁是什么
5️⃣ I2C 不通时,按照什么顺序排查
一、I2C 是什么?为什么需要它?
I2C(Inter-integrated Circuit) 是飞利浦 1982 年推出的总线,用 两根信号线 实现多个设备之间的短距离通信。
SDA:数据线
SCL:时钟线
它解决了两个问题:
串口太慢、不能挂多个设备
SPI 引脚太多、越多从机时 CS 引脚越多
一句话:I2C 用最少的两根线,挂最多的一堆设备。
二、I2C vs 串口 vs SPI:怎么选?
选型建议:
单设备、高速、全双工 → SPI
调试、简单通信、不在意速率 → UART
多设备、引脚紧张、速率适中 → I2C
三、I2C 协议核心
I2C 总线空闲时,SDA 和 SCL 都是高电平。
一次完整的 I2C 传输,包含以下帧:
1. 起始条件(Start Condition)
master 将 SCL 置高,然后将 SDA 拉低。
所有 slave 知道:传输要开始了。
💡 多个 master 同时抢总线时,谁先拉低 SDA,谁赢得总线。
2. 地址帧(7-bit 地址)
master 发送 7 位地址 + 1 位读/写位(0=写,1=读)。
例如:地址 0x6D(二进制 01101101),最后一位若为 0 表示写,1 表示读。
第 9 个时钟:ACK 位。被寻址的 slave 必须拉低 SDA 表示“我收到了”。
⚠️ 如果 slave 没有拉低 SDA(即 NACK),可能原因:地址错误、设备未上电、设备忙。
3. 数据帧(8 位数据 + 1 位 ACK)
每发送一个字节,接收方必须回复一个 ACK(拉低 SDA)。
数据帧数量任意,直到 master 产生停止条件。
4. 停止条件(Stop Condition)
master 将 SDA 拉低,然后将 SCL 拉高,再将 SDA 拉高。
总线恢复空闲。
5. 重复开始条件(Repeated Start)
如果 master 想在同一总线上连续与不同 slave 通信,可以不发送 stop,而是发送一个 重复开始条件,这样总线不会被其他 master 抢走。
四、波形毛刺:真实 I2C 调试案例
工程师在调试 I2C 时,发现波形上有“半高”的毛刺:
“半波高的地方其实都是在每一笔数据 ACK 信号被 slave 拉下来后间隔的地方。
这时候 Host/Slave 瞬间都没人在拉,因为外部还有一个 pull high 电阻在,所以会被拉起来一些,但之后 host 又开始传 0101 的讯号,就又恢复正常。”
这是正常现象,不是故障。
原因解释
2C 是 开漏 + 上拉电阻 结构,注意Sigma芯片的I2C默认是推挽的,可以软件改为OD。
当主机或从机释放 SDA(都不驱动时),上拉电阻会把 SDA 拉回高电平。
在 ACK 之后的那个短暂“释放窗口”,电压从低往高爬升,如果爬升速度不够快(上拉电阻太大或总线电容太大),就会看到一个 缓慢上升沿,看起来像“半高”。
一旦主机重新驱动下一笔数据的第一个 bit(通常是高电平),波形立刻恢复。
什么时候算真正的问题?
毛刺导致 SCL 上出现额外脉冲 → 检查 SCL 是否被干扰
毛刺被误识别为起始/停止条件 → 检查上拉电阻是否太小(上升太快)或太大(上升太慢)
毛刺幅度超过 Vih/Vil 阈值 → 需要示波器测量,可能信号完整性问题
解决方法
五、进阶特性:时钟拉伸与多主仲裁
时钟拉伸(Clock Stretching)
有些低速 slave 处理数据慢,在 master 发完一个字节后,slave 需要时间处理。
这时 slave 可以把 SCL 拉低并保持,迫使 master 等待,直到 slave 释放 SCL。
⚠️ 如果系统中存在会拉伸时钟的设备,master 必须支持检测 SCL 被拉低并等待。大部分简单 slave 不支持时钟拉伸。
多主仲裁(Arbitration)
I2C 允许多个 master 挂在同一总线上。当两个 master 同时想发送数据时:
谁先把 SDA 拉低,谁赢得总线
输掉的 master 自动退出,等待下一次机会
仲裁过程通过 线与逻辑 实现:只要有一个 master 输出 0,总线就是 0。
💡 如果你的系统只有一个 master,不需要关心仲裁。
六、I2C 不通?按这个顺序排查
调试工具推荐:
逻辑分析仪(抓取 start/address/ACK)
示波器(看上升沿、毛刺)
七、Comake Pi 开发板的 I2C 优势
✅ 上拉电阻已集成:D1/D2 板子的 I2C 引脚默认配好 2.2k 上拉,400kHz 直接跑
✅ 电平兼容:部分 I2C 引脚支持 1.8V/3.3V 可选
✅ 总线电容优化:PCB 走线已控制,可挂 4~6 个标准 I2C 设备
✅ 文档清晰:提供 I2C 引脚地址预留表、电平配置说明
✅ 软件支持:Linux 标准 i2c-dev 接口,i2cdetect 一键扫描设备
💡 你不需要自己算上拉电阻,不需要操心 PCB 走线,直接接上传感器,i2cdetect -y 0 就能看到设备地址。
I2C 只有两根线,但隐藏的细节足够你调一整天。
上拉电阻、总线电容、地址冲突、时钟拉伸、波形毛刺——每一个点都可能让你怀疑人生。
学会 I2C,你就掌握了最通用的传感器交互方式。
十、了解 Comake 开发板
Comake Pi D1| Comake Pi D2
👉 [点击以上链接,购买 D1/D2 开发板,开启实操]
加入 Comake 开发者社区
👉 [点击阅读原文] 注册社区,获取完整技术资料和项目支持
Tips:本期I2C使用参考均在Comake社区-文档中心
有任何问题均可通过 Comake 论坛提问。