当前位置: 首页 > news >正文

嵌入式状态机怎么写?用“洗衣机“讲清楚(附代码模板)

嵌入式状态机怎么写?用"洗衣机"讲清楚(附代码模板)

一句话: 状态机能用枚举+switch-case把散乱的if-else改造成清晰的状态流转。本文用洗衣机做比喻,5分钟看懂,附可直接复用的代码模板。

单片机程序写着写着就容易乱——标志位满天飞,if-else 嵌套五六层,过两周自己都看不懂。

状态机就是来解决这个问题的。

状态机是什么?想想洗衣机

你家的全自动洗衣机,按"启动"之后是这样的:

进水 → 洗涤 → 排水 → 脱水 → 漂洗 → 排水 → 脱水 → 结束

注意两个关键点:

  1. 洗衣机一次只在一个状态——进水的时候绝不可能同时脱水
  2. 状态切换有条件——水满了才能开始洗,水排干了才能开始脱水

这就是状态机。单片机程序也是一样的道理。

没有状态机的时候,代码长什么样

void main_loop(void) { if (step == 0) { // 进水 if (water_level > FULL) { step = 1; } } else if (step == 1) { // 洗涤 if (timer > 600) { step = 2; } } else if (step == 2) { // 排水 if (water_level == 0) { step = 3; } } else if (step == 3) { // 脱水 if (timer > 300) { step = 4; } } // ... 再写 20 个 else if }

这代码能跑吗?能。好维护吗?你试试三个月后改一步逻辑——牵一发动全身。

用状态机重写

先定义状态:

typedef enum { STATE_INIT, // 初始化 STATE_IDLE, // 空闲 STATE_RUNNING, // 运行中 STATE_ERROR, // 故障 STATE_SHUTDOWN // 关机 } E_SYS_STATE;

主循环变成这样:

E_SYS_STATE g_eState = STATE_INIT; void main_loop(void) { switch (g_eState) { case STATE_INIT: init_peripherals(); g_eState = STATE_IDLE; break; case STATE_IDLE: if (start_cmd_received) { g_eState = STATE_RUNNING; } break; case STATE_RUNNING: run_task(); if (fault_detected) { g_eState = STATE_ERROR; } if (stop_cmd_received) { g_eState = STATE_SHUTDOWN; } break; case STATE_ERROR: handle_error(); if (error_cleared) { g_eState = STATE_IDLE; } break; case STATE_SHUTDOWN: power_down(); break; default: g_eState = STATE_ERROR; // 兜底:跑到不该来的地方,进故障 break; } }

对比一下:

没有状态机有状态机
当前在干什么step变量猜g_eState一目了然
加一个新状态改一堆 if-else加一个 case 就行
出 bug 了不知道从哪跳进来的状态切换只有一处,直接定位
三个月后维护想死还能看懂

状态切换集中管理

实际项目里,状态切换最好统一在一个地方做:

void set_state(E_SYS_STATE eNewState) { if (eNewState == g_eState) { return; // 没变化就不折腾 } // 离开旧状态前做清理 switch (g_eState) { case STATE_RUNNING: stop_all_outputs(); // 安全操作:离开运行态先关输出 break; default: break; } g_eState = eNewState; // ★ 只有这一处赋值 // 进入新状态时做初始化 switch (eNewState) { case STATE_RUNNING: reset_timers(); break; default: break; } }

好处:整个程序里状态切换只有set_state()一个入口。出 bug 的时候在这加个printf,你马上知道是谁、什么时候、切到了什么状态。

状态机 ≠ 一定要画图

很多教程一上来就甩 UML 状态图,小白看着就劝退。

其实核心就三句话:

  1. 用枚举列出所有状态——命名要能看懂,别用 0 1 2 3
  2. switch-case 处理每个状态——default 必须写,兜底
  3. 状态切换统一入口——一个函数搞定,方便调试

画不画图是次要的,先把代码写清楚。

什么时候该用状态机

场景要不要用
单个 LED 闪烁没必要,计时器+标志位够了
设备上电→自检→待机→运行→关机必须用
通信协议解析(等数据→校验→处理→应答)必须用
传感器读值+显示随便,状态不超过 3 个就算了

判断标准很简单:如果你的流程超过 3 步,或者经常在"等某个条件"和"做某件事"之间切换,用状态机。

一个容易犯的错:在状态里死等

// 错误写法:在 case 里 while 死等 case STATE_WAIT_READY: while (!device_ready()); // ← 卡死了!其他事全干不了 g_eState = STATE_NEXT; break; // 正确写法:条件不满足就走,下次循环再检查 case STATE_WAIT_READY: if (device_ready()) { g_eState = STATE_NEXT; } // 不满足就保持当前状态,主循环继续跑 break;

状态机是非阻塞的。每个状态进来,检查条件,能干就干然后切走,不能干就退出等下次循环。整个系统靠主循环的高速轮转来驱动,而不是在某个状态里死等。

总结

要点一句话
核心思想一次只在一个状态,切换有条件
实现方式枚举 + switch-case + 统一切换函数
最大禁忌在状态里 while 死等
什么时候用流程超过 3 步就用

状态机不是什么高深的玩意。说白了就是把"程序跑到哪了"这件事从一堆散乱的 if-else 里拎出来,变成一个清晰的状态变量。写起来多几行代码,调试起来省半天时间。

http://www.jsqmd.com/news/1107801/

相关文章:

  • 手机号码定位系统:免费开源工具助你3秒掌握来电位置
  • 数据产业服务分类(08)——经济学术语——概述
  • 2026年7月份最新《墨香情》手游正版下载全指南 无职业武侠怀旧服新手入门与渠道避坑攻略
  • Windows 11终极瘦身指南:Win11Debloat让系统重获新生
  • 如何为Windows掌机添加完美运动控制:HandheldCompanion终极指南
  • EastWave应用:光场与石墨烯和特异介质相互作用的研究
  • APDTFlow+NSGM+MLflow时序AI工程实践指南
  • 【学习记录】Week5(二):无输出环境突破——Canary 盲爆破与 off-by-null 部分绕过
  • 8GB显存训练LTX-2.3人物LoRA实战指南
  • 为什么你的IDEA永远抓不到NullPointerException?——深入JVM JVMTI事件钩子与IntelliJ调试协议的兼容性断层(含官方未公开API调用日志)
  • IDEA重构重命名失效真相(全链路符号解析大揭秘)
  • 哔咔漫画下载器终极指南:5分钟打造个人离线漫画图书馆
  • 终极B站m4s缓存视频转换实战:高效无损转换为MP4格式
  • 重构生死线:IDEA Safe Rename成功率从61%→99.4%的7个原子级配置项(附JetBrains内部性能基准报告)
  • 自动化越强,人为什么反而要更强:AI 质控中的自动化反讽
  • 污水处理厂数据采集与组态监控系统方案
  • 2026 AI知识库收录IQI评测体系与实体内容RAG入库优化方案
  • 英雄联盟回放管理的终极解决方案:ROFLPlayer完整指南
  • Windows 11终极清理指南:免费开源工具让你的系统性能飙升51%
  • 英雄联盟回放管理终极指南:ROFL播放器完整教程
  • 【限时技术透支】:VMware模板化Jenkins Master镜像制作全流程(含Ansible自动化打包+SHA256校验)
  • Intellij IDEA2022.1.1下载、安装、激活、测试使用及常用配置
  • 【Vibe Coding从入门到精通】第14篇:Agentic Engineering——Vibe Coding的下一站
  • 阿里运营培训/1688访客3秒闪退,阿里运营带你吃透买家采购心智
  • 2026深度实测:好用的Claude Code平替全维度体验指南
  • pkg-config【Linux包管理工具】
  • 接口抽取不是“右键→Extract Interface”就完事了,Java重构核心陷阱全曝光,团队踩坑实录(含JetBrains官方未公开API调用逻辑)
  • Optisystem应用:光电检测器灵敏度建模
  • 企业级AI智能体落地实战:自主性、工具调用与治理架构
  • HTTP/2快速重置攻击漏洞修复实战:从原理到Nginx、F5 BIG-IP修复方案