事件驱动状态机例子

发布时间:2026/10/14 16:05:32

事件驱动状态机例子 核心思想中断/定时器只投递事件主循环或 RTOS 任务消费事件状态机根据“当前状态 事件”决定转移和动作。场景定义短按按键切换 LED 开/关长按 2 秒进入/退出 LED 闪烁按键需要 20ms 去抖事件源按键 GPIO 中断产生EV_KEY_DOWN/EV_KEY_UP10ms 定时器中断产生EV_TICK_10MS事件和状态定义typedef enum { EV_KEY_DOWN, EV_KEY_UP, EV_TICK_10MS } Event; typedef enum { ST_IDLE, // 空闲 ST_DEBOUNCE_DOWN, // 按下去抖 ST_PRESSED, // 已按下等待短按/长按 ST_LONG_PRESS, // 长按已触发 ST_DEBOUNCE_UP // 松手去抖 } State;事件队列ISR 只投递事件#define EVQ_SIZE 16 static Event evq[EVQ_SIZE]; static volatile uint8_t head 0, tail 0; bool event_post_from_isr(Event ev) { uint8_t next (head 1) % EVQ_SIZE; if (next tail) { return false; // 队列满可记录溢出 } evq[head] ev; head next; return true; } bool event_get(Event *ev) { if (tail head) { return false; } *ev evq[tail]; tail (tail 1) % EVQ_SIZE; return true; }按键中断void key_isr(void) { if (gpio_read(KEY_PIN) 0) { event_post_from_isr(EV_KEY_DOWN); } else { event_post_from_isr(EV_KEY_UP); } }10ms 定时器中断void timer_10ms_isr(void) { event_post_from_isr(EV_TICK_10MS); }状态机处理static State state ST_IDLE; static uint16_t press_ms 0; void fsm_dispatch(Event ev) { switch (state) { case ST_IDLE: if (ev EV_KEY_DOWN) { press_ms 0; state ST_DEBOUNCE_DOWN; } break; case ST_DEBOUNCE_DOWN: if (ev EV_TICK_10MS) { press_ms 10; if (press_ms 20) { // 去抖 20ms press_ms 0; state ST_PRESSED; } } else if (ev EV_KEY_UP) { state ST_IDLE; // 抖动忽略 } break; case ST_PRESSED: if (ev EV_TICK_10MS) { press_ms 10; if (press_ms 2000) { // 长按 2s led_blink_toggle(); state ST_LONG_PRESS; } } else if (ev EV_KEY_UP) { led_toggle(); // 短按动作 press_ms 0; state ST_DEBOUNCE_UP; } break; case ST_LONG_PRESS: if (ev EV_KEY_UP) { press_ms 0; state ST_DEBOUNCE_UP; } break; case ST_DEBOUNCE_UP: if (ev EV_TICK_10MS) { press_ms 10; if (press_ms 20) { state ST_IDLE; } } break; default: state ST_IDLE; break; } }主循环消费事件void main_loop(void) { Event ev; while (1) { if (event_get(ev)) { fsm_dispatch(ev); } // 可以在这里进入低功耗等待中断唤醒 // __WFI(); } }如果是 RTOS可以把fsm_dispatch放在一个任务里事件队列换成xQueueSendFromISR()/xQueueReceive()。按键中断不直接切换 LED也不做去抖计时只投递EV_KEY_DOWN/EV_KEY_UP。定时器中断不判断长按只投递EV_TICK_10MS。真正逻辑在fsm_dispatch()里根据state event决定是否转移状态是否执行动作比如led_toggle()、led_blink_toggle()是否累计时间、去抖、判断长按
延伸阅读

更多相关文章

2026/10/14 16:05:32

NLP诗歌接龙Python项目实战:顶针索引与押韵打分机制拆解

简介:面向NLP学习者和诗歌爱好者的Python实战项目,实现诗句按韵脚与语义自动接龙。技术层面覆盖中文分词(jieba)、拼音转换(pypinyin)、词性标注与语义分析,并融合规则匹配与统计学习算法&#…

2026/10/14 16:00:31

医院网络安全建设规划:从资产梳理到主动防御

简介:《医院网络安全建设规划》是一份针对医疗机构信息安全整体规划的完整方案文档,适合医院信息科人员、网络安全工程师及医疗信息化项目管理者参考。内容依据等级保护基本要求,围绕设计原则、网络结构分析、业务系统分析、等保建设流程及安…

2026/10/14 17:16:05

RK3288外接USB麦克风在钉钉/ZOOM无法录音的排查与修复

拿着 RK3288 的板子做音视频会议产品,第一件让我头疼的事就是外接 USB 麦克风在钉钉和 ZOOM 里录不了音。我一开始以为是硬件兼容性,换了三支不同型号的 USB 麦克风、两根 OTG 线,甚至加了独立供电的 HUB,问题还是复现。真正怪的是…

2026/10/14 17:16:05

景区导航App开发实战:Spring Boot + Android 全流程

在景区里打开导航是最让人崩溃的事情之一:地图上明明显示“您已到达目的地”,可你面前只有两米高的灌木丛和一脑袋的问号。城市导航在景区失灵几乎是常态,道路数据缺失、卫星信号被山体遮挡、POI分布稀疏,这些问题的根源在于通用地…

2026/10/14 17:16:05

SAP ABAP调用RESTful API测试用例设计与本地模拟调试要点

做SAP开发这些年,最怕听到一句话就是“这接口之前明明调通了,怎么一到生产就出问题”。去年我们团队接了个订单同步项目,ABAP端需要调用某外部仓储系统的RESTful API,真正跑下来才发现,SAP ABAP调用RESTful API本身不算…

2026/10/14 17:16:05

toor 鸿蒙化实战:Flutter 依赖注入库迁移与生命周期对齐要点

1. 为什么我要折腾“toor 鸿蒙化”,以及这件事到底解决什么问题今年年初,我接手的一个跨平台项目要往鸿蒙系统上迁移。第一轮跑起来后,页面倒是能显示了,但点进详情页就崩溃,而且报错位置五花八门——有的说实例没注册…

2026/10/14 17:11:03

商贸单据打印工具开发:Electron与SQLite实践

1. 项目背景与核心价值在商贸流通领域,每天需要处理的送货单和销售单据数量庞大。传统手工填写方式效率低下且容易出错,而通用办公软件又难以满足行业特有的格式和功能需求。这正是我们开发这套专业打印工具的初衷——为中小型商贸企业提供一套开箱即用的…

2026/10/14 11:31:03

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/13 17:09:18

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/14 2:32:55

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/14 0:00:33

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:33

macOS/iOS高精度计时:mach_absolute_time原理与实战

1. 项目概述:为什么mach_absolute_time是 macOS/iOS 时间测量的“黄金标准”在 macOS 和 iOS 开发中,我见过太多人用CFAbsoluteTimeGetCurrent()或NSDate.timeIntervalSinceReferenceDate做性能打点,结果在高精度场景下被系统时钟跳变、NTP 同…

2026/10/14 0:00:33

SCORM课件演示与测试全解析:从API通信到自动化验证

简介:这是一套遵循SCORM标准的交互式课件演示与测试资源,面向E-Learning课程开发者、LMS平台测试人员及在线教学从业者,用于验证课件在不同学习管理系统中的识别、传递与跟踪能力。压缩包共28个文件,约12.07MB,以swf动…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑