news 2026/2/24 22:31:18

简单理解:为什么是 do-while?I2C 地址应答检测的循环逻辑选型

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
简单理解:为什么是 do-while?I2C 地址应答检测的循环逻辑选型

在这段 I2C 地址应答检测代码中,选择do-while循环而非while循环,核心原因是“必须先执行 1 次状态检测,再判断是否继续循环”—— 完全匹配 I2C 通信中 “发送地址后,必须立即检测应答” 的时序要求,同时兼顾超时控制的合理性。

结合代码逻辑和 I2C 通信场景,具体分析如下:

一、先明确:do-whilewhile的核心区别

循环类型执行逻辑关键特点
do-while先执行循环体 → 再判断条件至少执行 1 次循环体
while先判断条件 → 条件成立才执行循环体可能 1 次都不执行

这段代码的核心需求是:发送 I2C 地址后,必须立刻检测从机的应答(ACK/NACK),不能跳过首次检测—— 这正是do-while的核心优势。

二、为什么必须 “先检测,再判断超时”?

1. I2C 时序的硬性要求:发送地址后需立即采样应答

I2C 通信中,“地址传输 + 应答” 的时序是固定的(以主机发送地址为例):

  1. 主机发送完 8 位地址(7 位地址 + 1 位读写位);
  2. 第 9 个 SCL 时钟周期是 “应答位窗口”—— 从机需在此时拉低(ACK)或不拉低(NACK)SDA;
  3. 主机必须在第 9 个 SCL 周期内采样 SDA 电平(检测应答),不能延迟。

对应到代码中:

  • 发送地址的操作(I2C_Send7bitAddress(...))执行后,必须立刻读取 SR 寄存器(循环体第一句reg_val = i2c_no->SR),检测ADRS(ACK)或RXNACK(NACK)标志;
  • 若用while循环,会先判断i--(超时计数器),若i初始值为 0(极端情况),会直接跳过检测 —— 导致错过 “应答位窗口”,永远无法检测到从机的应答,通信直接失败。

do-while强制先执行 1 次循环体:无论i初始值是多少,都会先读取 SR 寄存器检测应答,完全匹配 I2C 时序的 “即时采样” 要求。

2. 超时控制的合理性:“检测 1 次,再减计数”

代码中i是 “超时计数器”,作用是限制最大检测次数(避免死循环)。do-while的 “先执行后判断” 逻辑,让超时控制更合理:

  • 循环体执行 1 次 = 检测 1 次应答(消耗 1 个 “检测周期”);
  • 检测后,i--递减 1,若i仍大于 0,继续检测;若i为 0,退出循环(超时)。

举例:若i初始值为0x100(256 次检测),实际会执行256 次应答检测(覆盖足够的应答位窗口时间),而while循环会执行0x100次判断,可能少 1 次检测。

这种 “检测次数 = 超时计数器初始值” 的逻辑,更符合嵌入式开发中 “精准控制超时时间” 的需求(比如根据 I2C 波特率计算,256 次检测对应 1ms 超时)。

3. 错误处理的即时性:收到 NACK 后立即重试

代码中若检测到RXNACK(从机发送 NACK),会立即执行 “清除标志→发送停止信号→跳转try_start重试”。do-while的 “首次检测优先” 确保:

  • 从机发送 NACK 的瞬间,就能被捕获到,不会因为 “先判断超时” 而延迟处理;
  • 避免总线长时间处于 “等待应答” 状态,减少总线占用和冲突风险。

三、反例:若用while循环会怎样?

假设把代码改成while循环,逻辑会变成:

// 错误示例:while循环(先判断i--,再执行检测) while (i--) { // 先减i,再判断是否执行 reg_val = i2c_no->SR; // 检测ACK/NACK... }

会出现两个致命问题:

  1. 错过首次应答检测:若i初始值为0xFFFF,第一次循环会先执行i--(变成0xFFFE),再检测应答 —— 看似差异不大,但时序上延迟了 1 个 CPU 周期,可能错过 I2C 的 “应答位窗口”(尤其 400KHz 高速 I2C,时序窗口极短);
  2. 超时计数偏差:若i初始值为1while (i--)会先执行i=0,判断0为假,循环体 1 次都不执行 —— 直接超时,即使从机正常发送了 ACK,也无法检测到,通信失败。

四、总结:do-while的选择逻辑

这段代码选择do-while,本质是“I2C 时序要求” 与 “循环执行逻辑” 的精准匹配

  1. 时序匹配:必须先检测应答(循环体),再判断超时,避免错过应答窗口;
  2. 逻辑匹配:至少执行 1 次检测,确保 “发送地址后必有应答检测”,不会因超时计数器初始值导致漏检;
  3. 效率匹配:检测后立即处理(ACK 跳next、NACK 跳重试),无额外延迟,符合 I2C 高速通信的需求。

这是嵌入式 I2C 驱动开发中 “应答检测 + 超时控制” 的经典范式 ——do-while几乎是该场景下的唯一选择,也是工业级驱动代码的标准写法。

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

React中文网课程笔记1—快速入门

概述 本章节将介绍开发者每天都会使用的 80% 的 React 概念。本章介绍的知识如下: 如何创建和嵌套组件如何添加标签和样式如何显示数据如何渲染条件和列表如何对事件做出响应并更新界面如何在组件间共享数据 如何创建和嵌套组件 React 应用程序是由 组件 组成的…

作者头像 李华
网站建设 2026/2/8 10:20:27

YOLOv8类别不平衡问题缓解方法

YOLOv8类别不平衡问题缓解方法 在真实世界的目标检测任务中,模型常常面临一个看似简单却极具挑战性的问题:某些类别的目标几乎随处可见,而另一些则凤毛麟角。比如,在城市道路监控中,“汽车”可能每帧画面都出现几十次&…

作者头像 李华
网站建设 2026/2/16 10:15:57

YOLOv8自动学习超参数机制AUGMENTTrue说明

YOLOv8自动学习超参数机制AUGMENTTrue说明 在目标检测的实际项目中,一个常见的挑战是:如何用有限的数据训练出泛化能力强、鲁棒性高的模型?尤其是在工业质检、医疗影像或小样本场景下,数据稀缺问题尤为突出。传统做法依赖人工设计…

作者头像 李华
网站建设 2026/2/17 19:16:22

NunuAI:国内环境顶级模型平替

1. 放弃对单一模型的纯爱幻想 2025年底了,还在纠结 GPT-5.2 和 Claude-4.5 谁更强?这种争论在工程实践中毫无意义。现实情况是:OpenAI 的逻辑推演偶尔会陷入过度对齐的死循环,而 Anthropic 的模型在处理长文档关联时,…

作者头像 李华
网站建设 2026/2/18 12:41:01

YOLOv8预训练模型下载地址汇总(HuggingFace 官方)

YOLOv8预训练模型下载地址汇总(HuggingFace & 官方) 在智能安防、工业质检和自动驾驶等实时视觉系统中,开发者常常面临一个看似简单却极易卡壳的问题:如何快速获取可运行的YOLOv8预训练模型?不是每个人都有时间从…

作者头像 李华
网站建设 2026/2/17 19:26:35

论文降AI率之前,这些句式不改基本必翻

一、为什么手动降重总翻车?学术党必知的3大痛点“明明查重率达标了,导师却说论文有AI味要求重写!”——这是不是你的真实写照?很多同学误以为同义词替换调整句式就能蒙混过关,结果陷入三大困局:❌ 痛点1&am…

作者头像 李华