news 2026/5/12 22:54:39

图解说明硬件I2C起始与停止条件实现原理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
图解说明硬件I2C起始与停止条件实现原理

深入理解硬件I2C的起始与停止:不只是拉高拉低

在嵌入式开发中,你有没有遇到过这样的场景?

调试一个温湿度传感器,代码写得严丝合缝,地址也核对了八百遍,可就是读不到数据。用逻辑分析仪一抓——SDA线卡在低电平不动了,总线“死”了。

这时候问题往往不在于你的HAL_I2C_Master_Transmit()调用错了,而是在于你没有真正搞懂:I2C通信是怎么开始的?又是怎么结束的?

今天我们就来拆解这个看似简单、实则决定成败的关键机制——硬件I2C的起始条件(START)和停止条件(STOP)。不是泛泛而谈协议定义,而是从电气行为、状态机控制到实际代码落地,一步步讲清楚它们是如何被“制造出来”的。


为什么不能靠“软件延时”随便拉一下?

先说个扎心的事实:很多初学者写的“I2C”其实是GPIO模拟I2C,也就是俗称的“Bit-Banging”。比如:

// 错误示范:手动操作IO口实现“起始” SCL_High(); SDA_High(); delay_us(5); SDA_Low(); // 下降沿 → 起始? delay_us(5); SCL_Low();

这么做行不行?在实验室环境、短距离、单设备的情况下,可能勉强能用。但一旦系统复杂起来,问题就来了:

  • CPU占用率飙升;
  • 中断打断导致时序错乱;
  • 多主竞争时无法正确仲裁;
  • 抗干扰能力极差。

而真正的硬件I2C模块,是通过专用外设控制器+内部状态机自动完成这些关键动作的。它不会“随意”拉低SDA,而是在精确判断总线空闲后,按规范生成符合标准的电平跳变序列。

这才是我们今天要研究的重点。


起始条件:一次通信的“发令枪”

它到底是什么?

根据I2C协议标准,起始条件(START)的定义非常明确:

SCL为高电平时,SDA从高电平变为低电平,即构成一个起始条件。

注意关键词:SCL必须是高电平。如果SCL是低的时候SDA变化,那只是普通的数据位传输;只有当SCL稳定为高时发生的下降沿,才会被所有挂在总线上的设备识别为“新通信开始了”。

这就像体育比赛中的发令枪——只有裁判举旗示意准备就绪(SCL=H),然后开枪(SDA↓),运动员才开始跑。

硬件是怎么做到的?

STM32等MCU的I2C控制器内部有一个通信状态机。当你调用HAL_I2C_Master_Transmit()时,它并不是立刻去操作引脚,而是进入一套严谨的流程:

  1. 检测总线是否空闲
    控制器先检查SDA和SCL是否都为高电平(持续时间满足tSUP)。如果不是,说明总线正被占用,需等待或报错。

  2. 锁定SCL为高电平
    等待当前时钟周期结束,确保SCL处于高态。

  3. 主动驱动SDA下拉
    内部MOSFET导通,将SDA强制拉低。此时产生了一个干净的下降沿。

  4. 置位状态标志(SB)
    在寄存器I2C_SR1中设置SB位,表示“起始条件已发送”,供CPU查询或触发中断。

整个过程由硬件自主完成,无需CPU干预,保证了时序精度和可靠性。

图解时刻:起始条件的波形特征

SCL: ──────┬────────────── │ SDA: ─────┼─────╮ │ ╰────── ... ↑ START Condition (SDA falling edge while SCL = H)

这个小小的下降沿,启动了后续的所有通信步骤:地址发送、应答检测、数据收发……


停止条件:释放总线的“礼貌信号”

如果说起始条件是“我要说话了”,那么停止条件就是“我说完了,请别人发言”。

定义同样严格

停止条件(STOP)的定义是:

SCL保持高电平期间,SDA从低电平变为高电平

这意味着:
- 必须等到SCL为高;
- 然后释放SDA(让上拉电阻将其拉高);
- 上升沿发生在SCL=H期间才算有效。

一旦发出停止条件,总线进入空闲状态,其他主机可以申请使用权。

硬件如何执行?

以STM32为例,当一次传输完成后(如所有字节发完并收到ACK),硬件会根据配置决定是否生成停止条件:

// 默认情况下,以下函数会在末尾自动生成 STOP HAL_I2C_Master_Transmit(&hi2c1, dev_addr, data, size, 1000);

其底层流程如下:

  1. 最后一字节发送完毕;
  2. 接收从机ACK;
  3. 控制器检测到传输结束;
  4. 自动清除NO_STRETCH等控制位;
  5. 设置STOP控制位 → 硬件在下一个SCL高电平时释放SDA;
  6. 总线回归高电平(空闲);
  7. 置位STOPF标志位,可用于中断通知。

⚠️ 注意:如果你使用的是“重复起始”模式(Repeated Start),则不会生成停止条件,以便继续发起新的读写操作而不释放总线。

波形图示:STOP 条件长什么样?

SCL: ──────┬────────────── │ SDA: ╰─────┬──────── ↑ STOP Condition (SDA rising edge while SCL = H)

看到没?STOP不是一个简单的“设GPIO为高”,而是一个有时间约束的上升沿事件


实战案例:读取温度传感器全过程

我们来看一个典型的I2C交互流程,结合起始与停止的实际应用。

目标:从LM75温度传感器读取温度值。

正确通信流程分解

步骤操作是否涉及 START/STOP
1总线空闲检测——
2生成起始条件✅ START
3发送设备地址(写模式:0x90)——
4发送寄存器地址(0x00)——
5生成重复起始条件✅ Repeated START
6发送设备地址(读模式:0x91)——
7接收2字节温度数据——
8生成停止条件✅ STOP

其中第5步的“重复起始”尤为关键:它不发出STOP,直接再次发出START,从而维持主控权,避免其他设备插话。

HAL库如何支持?

uint8_t reg_addr = 0x00; uint8_t rx_data[2]; // 使用顺序传输接口,支持 Repeated Start HAL_I2C_Mem_Read(&hi2c1, LM75_ADDR << 1, // 从机地址 reg_addr, // 寄存器地址 I2C_MEMADD_SIZE_8BIT, rx_data, 2, // 读取2字节 1000); // 超时

这段代码背后发生了什么?

  • 第一次START → 发地址+写 → 写寄存器地址;
  • 硬件自动插入Repeated START;
  • 第二次地址+读 → 开始接收数据;
  • 数据接收完成后 → 自动生成STOP。

整个过程由硬件I2C外设流水线处理,CPU只需发起请求即可去做别的事。


常见坑点与调试秘籍

别以为用了硬件I2C就能高枕无忧。下面这些“经典故障”,几乎都和起始/停止有关。

❌ 坑点1:总线卡死,无法生成起始

现象:调用HAL_I2C_Master_Transmit()返回HAL_BUSY,逻辑分析仪显示SDA一直为低。

原因分析
- 某个从机异常拉低SDA(如复位失败、固件卡死);
- 上拉电阻虚焊或阻值过大(>10kΩ),无法将SDA拉高;
- MCU GPIO未配置为开漏输出(OD模式);
- I2C时钟未使能(RCC配置遗漏)。

解决方案
1. 用万用表测SDA/SCL静态电平;
2. 强制复位从机芯片;
3. 临时切换为GPIO模式,手动输出9个SCL脉冲“唤醒”从机;
4. 检查PCB焊接与上拉电阻(推荐4.7kΩ);
5. 确保RCC开启且GPIO复用正确。

💡 小技巧:可以在初始化阶段加一段“总线恢复”代码,模拟9个时钟周期帮助释放总线。

❌ 坑点2:通信结束后总线仍被占用

现象:第一次通信成功,第二次失败;逻辑分析仪发现上次通信后没出STOP。

根本原因
- DMA传输未完成就被中断打断;
- 错误处理路径中未手动补发STOP;
- 设置了SOFTEND_Mode但未调用GenerateStop()
- NVIC中断未使能,导致事件未响应。

应对策略
- 在错误回调中强制调用:
c if (__HAL_I2C_GET_FLAG(&hi2c1, I2C_FLAG_BUSY)) { __HAL_I2C_GENERATE_STOP(&hi2c1); }
- 启用BERR(总线错误)、ARLO(仲裁丢失)中断;
- 添加超时机制,防止无限等待。


设计建议:让I2C更可靠

项目推荐做法
上拉电阻一般选4.7kΩ;高速模式(>400kHz)可用2.2kΩ
总线电容不超过400pF,否则影响上升时间
电源去耦每个I2C器件旁加100nF陶瓷电容
PCB布局SDA/SCL走线尽量短,远离高频信号线
长距离传输>30cm建议使用I2C缓冲器(如PCA9515)
地址冲突用逻辑分析仪扫描总线上所有响应设备

特别提醒:不要为了省两个电阻就不加上拉!I2C是开漏结构,没有上拉=没有高电平=通信必崩。


结语:掌握本质,才能游刃有余

起始与停止条件,看似只是两个电平跳变,实则是I2C通信的“门把手”——开门进来,关门离开。

当我们理解了:
- 起始条件是如何由硬件状态机精准生成的;
- 停止条件为何不能随意省略;
- 重复起始如何避免总线争抢;
- 常见卡死问题背后的电气真相;

我们才能真正驾驭硬件I2C,而不是被它牵着鼻子走。

下次当你面对一个“读不出数据”的I2C设备时,不妨先问自己一句:

“它真的收到了起始信号吗?”
“通信结束后,总线被释放了吗?”

也许答案就在那一条上升沿里。

如果你正在做传感器集成、多设备通信或低功耗设计,欢迎在评论区分享你的I2C踩坑经历,我们一起排雷。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/13 6:29:48

传统vs深度学习:骨骼检测方法对比,云端快速验证

传统vs深度学习&#xff1a;骨骼检测方法对比&#xff0c;云端快速验证 引言&#xff1a;为什么需要骨骼检测技术&#xff1f; 骨骼检测&#xff08;又称人体关键点检测&#xff09;是计算机视觉领域的重要技术&#xff0c;它能从图像或视频中定位人体的关节位置&#xff08;…

作者头像 李华
网站建设 2026/5/10 21:53:12

HY-MT1.5-1.8B vs 商业翻译API:实测对比报告

HY-MT1.5-1.8B vs 商业翻译API&#xff1a;实测对比报告 1. 引言 在全球化加速的背景下&#xff0c;高质量、低延迟的机器翻译能力已成为智能应用的核心基础设施。无论是跨境电商、跨国协作&#xff0c;还是内容本地化与实时通信&#xff0c;用户对翻译服务的需求正从“能用”…

作者头像 李华
网站建设 2026/5/10 21:52:23

AI人脸隐私卫士在社交媒体的应用:用户上传预处理实战

AI人脸隐私卫士在社交媒体的应用&#xff1a;用户上传预处理实战 1. 引言&#xff1a;社交媒体时代的隐私挑战与自动化应对 随着社交媒体的普及&#xff0c;用户每天上传数以亿计的照片和视频。然而&#xff0c;这些内容中往往包含大量未授权的人脸信息——无论是街拍、聚会合…

作者头像 李华
网站建设 2026/5/10 21:52:02

HY-MT1.5-1.8B性能优化:让翻译速度提升3倍的技巧

HY-MT1.5-1.8B性能优化&#xff1a;让翻译速度提升3倍的技巧 在实时翻译、边缘计算和多语言交互日益普及的今天&#xff0c;模型推理效率直接决定了用户体验与部署成本。腾讯开源的混元翻译模型HY-MT1.5-1.8B凭借其“小体积、高质量”的特性&#xff0c;成为轻量级翻译场景中的…

作者头像 李华
网站建设 2026/5/10 21:52:25

利用AXI DMA实现千兆以太网数据直传

打通高速数据动脉&#xff1a;AXI DMA如何让千兆以太网“零拷贝”飞起来你有没有遇到过这样的场景&#xff1f;FPGA系统接上千兆网口&#xff0c;满心期待地抓取视频流或传感器数据&#xff0c;结果刚到几百兆速率就开始丢包。调试发现CPU占用率飙到90%以上&#xff0c;几乎被中…

作者头像 李华
网站建设 2026/5/12 21:42:35

图解说明隔离电路在高压环境下的设计原理

高压系统设计中的隔离艺术&#xff1a;从光耦到数字隔离的实战解析在电力电子、工业控制和新能源汽车等领域&#xff0c;工程师们每天都在与“高压”打交道。无论是光伏逆变器中400V直流母线&#xff0c;还是电机驱动里频繁跳变的dV/dt噪声&#xff0c;都对系统的安全性与可靠性…

作者头像 李华