尧图精选

Mixly循环进阶:while和do...while实战用法与案例详解

🕒 发布时间:2026/10/1 10:28:27 📁 来源:尧图网络
前面几篇我们陆续把顺序结构、选择结构里的常用积木都摸了一遍上一讲还把for循环这个“数数循环”讲透了。很多人到了这里就产生一个感觉循环嘛能数数、能遍历够用了。但真去动手做项目你会发现完全不是那么回事。按键什么时候被按下去你不知道超声波传感器什么时候能读到稳定数值你也不知道串口数据什么时候从电脑那边发过来你还是不知道。这些场景共同的特点就是循环次数不固定你要做的不是“循环N次”而是“一直等等到某个条件成立为止”。这种逻辑靠for循环来写会非常别扭必须用while循环和do……while循环。这篇教程我就把这两个循环在米思齐Mixly里的用法一次讲透包括积木在哪里、条件怎么填、和底层C语言代码怎么对应另外附上三个可以直接抄走的真实项目案例。这一讲适合刚学完for循环、想更进一步理解循环控制逻辑的初学者也适合在课堂上带学生做创客项目的老师。看完你会发现死循环并不一定是坏事很多时候我们要的就是让程序一直转直到一个条件把它放行。1. 为什么for循环搞不定所有循环问题1.1 for循环的本质是“数次数”想搞清楚while存在的意义得先回头看看for循环到底擅长什么。for循环的标准结构是“初始化变量—判断条件—执行循环体—更新变量”四步走的固定流程它非常适合那种你事先就能算出要跑多少遍的场景。举个最直白的例子你要让LED灯闪烁10次这个“10”是提前定好的程序一启动就知道循环要执行10遍那就用for循环把次数设置好干净利落。再比如你要遍历数组里的10个元素每个元素处理一遍这也是确定次数的循环for循环是天然的选择。但问题来了。假如你要做一个智能门锁项目需要“当密码输入正确时才开门”用户什么时候输对密码可能是3秒后可能是3分钟后也可能一直输不对。这个等待时长是运行期才能知道的写程序的时候根本没法预知次数。你用for循环怎么写总不能在写代码的时候就把用户的手速和运气先算进去吧。for循环的局限性就在这里它强依赖一个“可预估的循环次数”一旦次数不确定或者循环结束的条件依赖于外部状态比如传感器数值、按键状态、串口数据for循环就变得笨手笨脚了。这时候循环条件本身才是主角次数的多少反而无所谓我们要的就是“条件成立继续转条件不成立就停下”。1.2 while真正擅长的事等待和轮询while循环干的活可以概括成两个词等待和轮询。它做的事情是“先看条件条件成立就进循环体走一圈走完回来再看条件直到条件不成立为止”。这个机制和真实世界里的交互逻辑高度吻合。比如你去看病医院门口闸机就是一台while循环的机器它不停检测“当前有没有人站到闸机前”有人就开门让进去没人就一直等循环条件就是“无人通过”。这个循环的次数完全无法预知可能一天几百人也可能一中午没一个人。在Arduino项目里这种“等待型”循环太常见了。等待按键被按下、等待传感器数据落到有效范围、等待串口收到指令全都是while的典型应用场景。你能明显感觉到用while描述这类逻辑是顺着人的直觉走的条件是什么就写什么不需要为了凑一个“循环次数”而刻意构造变量。顺便说一个初学者容易忽略的点Arduino的loop()函数本身就是一个无限的while循环——主板一直在反复执行你写在主程序里的代码。理解了这一点你就会明白为什么很多程序内部还需要主动写while因为loop()每一次从头执行是有间隔的而while可以让你在同一轮循环里“卡住”等待某个条件这能极大简化控制逻辑避免写出绕来绕去的状态变量。2. 在Mixly里把while循环积木用起来2.1 积木在哪里、长什么样打开Mixly插好开发板左侧模块区找到“控制”分类往下拉你会看到一个写着“循环执行”的积木块。这个块的外形和for循环积木很像右侧有一个C形的凹槽用来装循环体凹槽上方横着一个六边形的条件插槽。把鼠标移上去提示文字会告诉你它是while循环。没错Mixly里的“循环执行”块对应的就是C语言里的while关键字。有些旧版或改版后的Mixly这个块可能显示为“当……执行”之类的文字但只要看到“C形结构六边形条件插槽”的组合基本可以确定就是它。如果界面上实在找不到你也可以在搜索框里输入“while”来定位。使用的时候很简单从“循环执行”块拖出来把它的“肚子”撑开把要重复执行的积木塞进去再在顶部条件插槽里放一个条件表达式一个while循环就搭好了。执行逻辑是程序每次运行到这里先看条件是否为真为真就进循环体走一遍走完再回头判断如此往复。2.2 循环条件怎么填才算对条件插槽要放的是一个逻辑值也就是判断结果是“真”还是“假”的东西。最常用的做法是从“逻辑”分类里拖出比较运算符比如“大于”“小于”“等于”“不等于”然后在运算符左右两侧接上变量、数字或传感器读取结果。举个例子如果你希望“当温度高于30度时一直打开风扇”那条件插槽里就放一个大于号左边接温度传感器读到的数值变量右边填30。程序执行到循环时会实时读取当前温度只要大于30就一直执行循环体内的“打开风扇”语句一旦温度降到30以下条件变假循环体停止。这里给大家一个实操建议条件插槽里也可以直接放变量本身。Mixly的变量值有“真”“假”两种特殊状态有些传感器模块比如倾斜开关、火焰传感器的数字输出引脚读出来直接就是逻辑值这种情况下你只需要把变量块拖进去选中“真”或“假”就可以作为循环条件了不需要再去套一层比较运算。另外循环条件不一定要填进去。你把条件插槽空着或者放一个永远为真的逻辑值这个while就变成了一个“无限循环”。在Mixly里可以拖出“逻辑”分类下的“真”这个块填进去程序就会永远在循环体里来回跑直到断电或者遇到“跳出循环”积木。这种无限循环在项目里是有合法用途的后面案例三会用到。2.3 动手验证看生成的C语言代码Mixly最大的好处是拖好积木后切换到代码区能直接看到自动生成的C语言代码。这是绝佳的学习机会。假设我搭了这样一个逻辑先定义一个整数变量i并赋值为0然后拖一个“循环执行”块条件设置为“i 5”循环体里放“i增加1”。切换到代码区你会看到类似这样的内容int i 0; while (i 5) { i i 1; }这就是最标准的while循环写法。对照积木和代码一起看你能很直观地理解每个积木对应哪一个关键字、哪一对花括号。我强烈建议你在学习阶段每次搭完循环都用这个功能对照一遍图形化积木是帮我们理清思路的但底层跑的还是C语言看懂代码才能举一反三以后脱离开Mixly去写纯代码也不至于一脸懵。3. do……while先干一票再问条件3.1 Mixly里的“执行直到”积木在“控制”分类里循环执行块的附近还有一个块叫“执行……直到”。这里需要特别注意它就是C语言里的do……while循环。它的外形同样是C形结构但积木上文字的排列方式暴露了它的核心逻辑先执行循环体再判断条件。条件文字写在循环体的“出口”位置这代表程序从循环体执行完之后才去检查条件。这跟“循环执行”块有本质区别。C语言里do……while的语法是do { // 循环体 } while (条件);特点明确不管条件成不成立循环体都至少先执行一次然后再判断。而普通的while循环是先判断后执行条件一开始就是假的话循环体一次都不跑。3.2 while和do……while到底差在哪把两者放在一起对比差别就非常清晰了。while循环是一个“门卫”式的循环你得先过安检条件合格才放你进去do……while则是一个“先干活后汇报”的循环你先执行一轮最后再检查要不要继续下一轮。用一个生活中的例子帮助记忆你去自动售货机买饮料投币后机器会先检查你投的钱够不够不够就吐出来不卖给你这是while逻辑。而p曲冤案此处不适用——换个例子。你去做体检不管你有没有病先做一轮基础检查医生根据结果判断要不要做进一步检查这是do……while逻辑起码得先查一次才能知道下一步怎么办。在程序行为上最重要的区别就是“第一次执行与否”。假如条件初始为假while循环直接跳过循环体do……while则会先执行一次循环体然后发现条件为假退出。这多执行的一次在很多场景下正是我们需要的。3.3 什么时候该用do……whiledo……while最适合的场景是循环体里的操作会影响到条件的判断且你需要至少做一次才会知道条件是否满足。最典型的就是传感器数据读取。超声波模块读取距离时如果你连一次都没读怎么知道传回来的数值是不是有效的所以正确的逻辑就是先读一次拿到数值检查它在不在有效范围内如果在就继续用这个值不在就再读一次直到读到一个有效值为止。这种“先测量后判断”的需求用do……while写起来非常顺逻辑流畅自然。再比如串口通信。你要等待单片机和电脑建立通信并收到一个特定的开始字符做法也应该是先检查一次串口缓冲区有没有数据进来没有就继续等有就取出来判断是不是想要的字符。如果你用while先判断缓冲区再读取第一次数据还没到程序直接跳过整个流程反而容易出错。还有一种更隐蔽的场景值得注意循环条件依赖的变量需要在循环体内初始化。你用一个变量控制循环而变量的值是在循环体里计算出来的这时候用do……while可以保证变量一定被赋过值避免因为初始值未定义而出现逻辑漏洞。这在图形化编程里可能感触没那么深但等你转到纯C语言就会知道未赋值的变量参与条件判断是多容易踩的坑。4. 三个可以直接抄走的实战案例4.1 案例一用while等待按键松开实现单击检测第一个案例目标是做一个“按一下翻转灯状态”的小程序按键每按下并松开一次LED灯就在亮和灭之间切换一下。这个案例非常适合练习while因为它的核心难点不在按键检测而在“防止按下期间程序反复执行翻转操作”。来看看如果不用while会发生什么。主程序里写“如果按键按下则翻转LED状态”。真相是一个手指按下去到松开表面看起来一瞬间单片机却已经在这个循环里跑了成百上千次每次检测到按钮是低电平就翻转一次状态。结果就是灯在极短时间内反复亮灭肉眼看到的效果是灯似亮非亮、闪烁不停完全达不到“按一下切换一次”的效果。解决办法就是用while等待按键松开。在检测到按键按下、完成一次状态翻转之后立刻卡在一个循环里等待按键被松开程序才继续向下走。具体搭法如下先把硬件接好按键一端接GND另一端接数字引脚2引脚2设置为上拉输入模式Mixly里有“数字输入”的上拉选项选中上拉即可LED正极接引脚13可以借用板载LED。图形化逻辑是这样的“初始化”块里设引脚2为输入上拉模式设引脚13为输出模式。“主程序”的“如果”块判断引脚2读到的值为低电平表示按键被按下。条件成立时用“数字输出”把引脚13设为“高”或“低”的切换状态这里可以用一个变量保存LED当前状态也可以用“数字输出”直接取反Mixly里有“翻转”或者用变量更方便简化为每次切换。拖入“循环执行”块条件设置为“引脚2读到的值等于低电平”循环体里什么都可以不放或者放一个“延时10毫秒”的积木。这段逻辑的意思是按键按下的瞬间完成LED翻转然后程序就卡在while循环里直到手指松开、引脚2恢复高电平循环才会结束程序回到最上面等待下一次按键。有些读者可能会问循环体空着会不会有问题在Mixly里空循环体完全允许程序会反复执行空的判断。但我个人建议放一个10到20毫秒的延时一方面能降低引脚信号抖动的影响让检测更稳定另一方面也让CPU稍微喘口气养成好习惯。不过别放太长否则用户快速按键时会感觉反应迟钝。这个案例做完你可以做一个easy的扩展实验把while等待松开的逻辑去掉试试对比一下前后效果你会对“等待型循环”的价值有非常深刻的体会。4.2 案例二do……while循环读取超声波直到拿到有效值第二个案例把视角切换到传感器读取场景。超声波传感器HC-SR04测距是市面普及率极高的模块。正常测距范围大概在2厘米到400厘米之间超出这个范围或者前方没有有效遮挡物时读到的值经常是0或者异常大。如果把0当真实距离去用你的避障小车可能会突然急刹车或者疯狂乱转。解决思路就是不读到有效值不罢休。用do……while实现“先读一次判断是否有效无效就继续读”。接线参考Trig接A0Echo接A1在Mixly的“传感器”或“执行器”分类下找到超声波模块积木选择对应引脚即可它会直接返回厘米为单位的距离值。图形化逻辑这样搭在“变量”分类里新建一个变量命名为“距离”类型选择整数。拖入“执行……直到”块。把“距离”变量赋值为超声波读取结果这个操作放进循环体。循环条件设置为“距离小于2或者距离大于400”。这里要注意条件语句的语义Mixly里的“执行……直到”块循环会一直执行直到条件变为真才退出这一点和C语言里“do while结果是假就退出”有细微差异要特别留意Mixly对此做了翻转处理。如果你用的是标准的“执行……直到”块它的含义是“重复执行直到条件成立”所以条件应写“距离小于2或者距离大于400”也就是“读到的值非法”这个判断结果。这样一来程序会反复读取超声波直到距离值落在2到400之间的有效区域才继续向下执行。这里实际测试时我发现一个细节超声波传感器的读取是需要时间的一般建议两次触发之间至少间隔60毫秒否则数据容易跳变。所以在do……while循环体的读取操作之后最好加一个“延时100毫秒”精度损失不大但数据稳定度提高很多。这个程序写完后你用一个挡板在传感器前面来回移动串口打印的距离值会非常顺滑。一旦你把手完全贴在传感器表面读到低于2厘米的异常值时你就知道do……while正在背后不停重读数据了。这个案例选do……while而不是while就是因为程序需要“至少读取一次”才能判断数据是否有效这正好是do……while相对于while的独有价值。4.3 案例三给while循环加超时保护防止彻底卡死第三个案例是我自己在项目里吃过亏之后总结出来的强烈建议所有人在写等待型循环时都养成这个习惯给循环加超时保护。先说血泪教训。我曾经写过一个程序用while循环等待串口收到指定命令结果用户在电脑端忘了把串口发过来或者某个通信环节出问题程序就硬生生卡在等待循环里后面的逻辑全都不跑了。最气人的是LED灯也不闪了按键也没反应了整个设备像个砖头。排查了半天才意识到是while循环里没有任何退出机制它成了真正意义上的“死循环”。死循环听上去是程序员的幽默但落到硬件上就是设备失控。Arduino里的普通函数是没有办法“绕过”一个死循环去执行其他代码的它不像电脑操作系统可以抢占CPU单片机执行到while死循环就是真的停在那里什么都不管了。所以我的习惯是在等待型循环里加一个计数变量每次循环累加一旦超过一个很大的阈值就用“跳出循环”积木强制退出。具体做法新建变量“超时计数”初始化为0。拖入“循环执行”块条件设置为“真”这表示一个无限循环。循环体内第一件事判断“数字引脚2读取值等于低电平”这个条件如果成立说明等待的信号到了立刻用“跳出循环”块退出循环。判断完再给“超时计数”加1。然后再判断“超时计数大于1000000”是否成立如果成立说明等太久了也用“跳出循环”退出。循环体末尾放一个“延时1毫秒”用于控制速度。这个方案把“while条件判断”与“超时退出”完全分开了。本质上是一个无限循环但内部通过多次条件判断来决定何时退出比直接把这个复杂条件写到while的插槽里要清晰得多。而且它最大的好处是你可以在循环退出后增加一个标志变量记录“这次退出是因为信号到了还是因为超时”后续程序可以根据这个标志做出不同反应比如超时就提示用户“通信超时请重试”。这个“无限循环内部判断退出超时保护”的三件套是我做交互类项目时用的最高频模板。灯带等待蓝牙指令、电机等待限位开关触发、屏幕等待用户触摸全都可以套这个模板。强烈建议你把这个结构亲手搭出来跑一遍然后把超时阈值改小比如设成100再故意不触发等待条件观察程序在预定时间后自救返回你会深深爱上这个底裤级的保险措施。5. 常见问题与排查技巧实录5.1 程序卡死、灯不闪、无响应先查死循环玩while循环遇到程序没有响应第一反应不用怀疑八成是某个循环的条件永远为真程序正在里面无限打转。排查方法也很简单在循环体的首尾各加一个“串口打印”积木分别输出“循环开始”和“循环结束”这样的文本然后把串口监视器打开。如果只看到“循环开始”刷屏看不到“循环结束”基本就能锁定这个循环出不去了。定位到问题循环后重点检查这个循环条件所依赖的变量是否有可能变为“假”。常见坑有三个一是条件里用了传感器读数但传感器接线错误导致读数恒为一个不可能让循环退出的值二是变量在循环体里被重新赋值了但赋值的逻辑写错变量永远满足循环条件三是循环体内忘了更新循环变量这在从for循环改写成while循环时特别常见。比如你原来用for实现“i从0到99”改成while后写了“条件i100”循环体里却忘了写“i增加1”i永远停在0循环直接变成死循环。5.2 循环一次都不执行条件初始就是假和死循环相反的另一个极端是循环体一次都进不去。这种问题在while循环里非常隐蔽因为程序不会报错逻辑上也不违反规则只是运行结果告诉你“这段代码好像失效了”。实际上不是失效是进入循环之前条件已经是假的了。我刚学的时候就被这样坑过一次。我想写一个程序当温度高于30度时循环执行风扇加速结果明明天气很热风扇就是不动。排查后才发现温度传感器那个变量在初始化时被赋了一个内部测试值35度按道理应该触发循环但我在循环条件里写的比较方向反了写成了“温度小于30”35度自然不满足条件循环一次都没进。排查方法依然是串口打印进入判断语句之前先把条件里用到的变量值打印出来条件不成立时一眼就能看出来。图形化编程里拖一个“串口打印”积木放在循环块前面把温度变量选进去打印出来你会立刻发现问题。5.3 循环里的延时别乱删它有时是保命的很多初学者看到while循环觉得循环体越短越好、执行越快越好于是把循环体里的延时积木全都删掉。在一些纯计算逻辑里这样做问题不大但凡是涉及传感器读取、通信收发、按键检测的循环延时往往不是拖后腿而是保障系统稳定性的关键。以超声波传感器为例模块的TRIG引脚被置高10微秒以上才是一次有效触发Echo引脚的回响信号需要一定时间如果循环体里没有延时你可能在一个循环周期内重复触发模块根本来不及完成一次完整的声波发射和接收读回来的数据自然全是一堆乱码一样的0或者几百的跳变。按键检测也是同样的道理没有延时的话一次机械抖动可能被当成多次按键导致状态切换多次。所以循环体里的延时只要是和外部硬件打交道的我都不建议轻易删除实在不知道放多久就先用50到100毫秒起步观察效果再调整。5.4 善用串口打印和板载LED搭建“程序探针”最后分享一个我调试while循环时屡试不爽的小技巧不要只依赖串口打印因为输出文本本身需要时间而且有些情况下串口被占用了你根本看不到日志。这时候板载LED就是你最轻量级的调试工具。具体做法是在循环体内的关键位置比如循环的开头、中间、结尾分别让板载LED亮起、熄灭、闪烁一次。如果你用肉眼看到LED按照预期节奏变化说明程序执行流动平顺如果LED直接常亮说明程序停在某处循环出不来如果LED压根没反应说明循环没被进入。这个方法在脱离电脑、用独立电源运行设备时特别好用不需要带一大堆调试线只需要用眼睛观察一盏小灯就够了。对于图形化学习者我特别推荐养成“先加探针再跑程序”的习惯。别怕麻烦很多莫名其妙的循环问题花半分钟加两盏LED探针或者一串打印语句答案就自己浮出水面了。写在最后的一次小折腾按老规矩最后分享一个我实际上课时反复让学生做的小实验把同一个“LED闪5次”任务分别用for、while、do……while三种方式实现然后故意制造一些边界情况比如让条件第一次就是假的再观察三种写法的差异。只有亲眼看到while一次都不跑、do……while硬要多跑一次你对这两个循环的理解才算真正到位了。我个人在实际教学中还有一个体会别急着背语法图形化编程给了我们绝佳的试错环境每个积木拖出来试一遍看效果、看生成代码比死记硬背一百遍while的条件判断位置都管用。循环是程序的节拍器for是稳定的节拍while是灵活的等待do……while是执着地先做再说。这三个兄弟组合在一起足以应对绝大多数项目里的重复逻辑。把这一讲里的案例好好跑一遍循环这块你就算是真正拿下了。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →