news 2026/4/15 15:29:50

简单理解:为什么是 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/4/14 23:11:56

线索二叉树是对普通二叉树的优化结构,旨在提高遍历效率

一、线索二叉树 线索二叉树是对普通二叉树的优化结构,旨在提高遍历效率。在传统二叉树中,每个结点有左右两个指针,对于n个结点的二叉树,共有2n个指针域,其中只有n-1个被用于连接子结点,其余n1个为空。线索二…

作者头像 李华
网站建设 2026/4/15 11:31:00

GPT-5.2与Claude-4.5国内直连实操指南

2025年最后一天,如果你还在折腾网络或者买那种随时会封号的海外代充,或者忍受镜像站背后偷偷换成低版本API的降智服务,那你这几年的技术圈真是白混了。在当前GPT-5.2和Claude-4.5满地走的环境中,稳定直连和白嫖额度才是硬道理。 …

作者头像 李华
网站建设 2026/4/15 8:10:42

互联网大厂Java面试实录:从Spring到微服务的全面探索

互联网大厂Java面试实录:从Spring到微服务的全面探索 场景描述: 在一家知名互联网大厂的面试室里,面试官严肃地坐在桌子的一边,他面前坐着一位初入职场的Java小白程序员,名叫超好吃。今天的面试主题围绕Java核心技术栈…

作者头像 李华
网站建设 2026/4/10 23:14:54

大模型如何评测之——“刻意破坏训练中的高频共现统计“模板

1、评测样本模板模板 → 示例 → 测什么 → 常见失败,建评测集。一、语言形式 能力解耦类模板 1:低语言质量 高专业度模板【非标准/口语/有错别字的表达】【本质是专业/技术/学术问题】示例“我这个最小二成回归哈, 就是残插不是正太分布会…

作者头像 李华
网站建设 2026/4/6 9:14:49

YOLOv8预测置信度阈值设置技巧

YOLOv8预测置信度阈值设置技巧 在智能监控系统部署过程中,一个常见的问题是:明明模型在测试集上表现优异,实际运行时却频繁误报或漏检。比如夜间摄像头将路灯反光识别为车辆,或者远处的行人因尺寸过小而被完全忽略——这些问题背后…

作者头像 李华
网站建设 2026/4/15 6:21:38

多元统计分析不会做?R语言带你玩转生态数据,快速出图出结果

第一章:R 语言 多元统计分析 生态数据在生态学研究中,多元统计分析是探索物种分布、环境因子影响以及群落结构变化的重要工具。R 语言凭借其强大的统计计算能力和丰富的生态学相关包(如 vegan、ade4、labdsv),成为处理…

作者头像 李华