
单片机事件驱动框架 5 分钟上手用 EventOS Nano 告别轮询地狱【免费下载链接】eventos嵌入式开发框架事件驱动超级轻量。最低占用ROM 1.5KBRAM 172字节。核心技术是事件总线支持Reactor和状态机两种模式协作式内核极度可靠。可深度裁剪移植方便。项目地址: https://gitcode.com/gh_mirrors/eve/eventos如果你还在用一堆while(1)里的标志位和delay硬扛整个项目的业务逻辑那么这篇关于事件驱动框架的文章值得你读完。今天要介绍的EventOS Nano是一个面向单片机的开源事件驱动框架C 语言实现、专为 STM32 等 MCU 设计最低只占 ROM 1.2KB、RAM 172 字节却能把纷乱的轮询代码改造成清晰的事件响应结构。我们用一个按键控制 LED的例子带你 5 分钟走完整个上手流程。那个被 while(1) 困住的深夜 写单片机业务代码写到后面你大概率会遇到这种场景while (1) { if (key_scan() PRESSED) { delay_ms(20); /* 去抖... */ } if (uart_flag) { handle_uart(); } if (sensor_flag) { do_something(); } // 代码越加越长缩进越来越深谁都敢往里塞逻辑 }功能少的时候这没什么可一旦按键、串口、定时、传感器全涌进来这个循环就会变成一团谁也理不清的面条。更糟的是任何一个小改动都可能影响其他功能的时序——因为所有代码都在互相抢 CPU 时间片。事件驱动的思想正是为了解决这个问题不让程序去反复问而是让事情发生主动通知程序。EventOS Nano 做的就是把这个机制变成一套轻量、可靠、可裁剪的框架。事件队列和状态机用一顿饭就能讲明白 EventOS Nano 的两大核心一个是事件队列一个是状态机或 Reactor它们并不难理解。事件队列 ≈ 餐厅门口的叫号屏。你外部中断、串口、定时器把号事件递进去屏幕队列按顺序存放后厨事件循环每叫一个号就处理一件事。谁来的早谁先处理大家互不打断。状态机 ≈ 一台自动售货机。机器只有待机、收钱、出货、找零几个状态每个状态下只关心该关心的事件。比如出货状态下收到出货超时就转去报警状态。在 EventOS Nano 里一个事件 事件主题编号 携带的数据 数据长度。谁发布它、谁订阅它双方互不认识天然解耦。而协作式内核让框架在任意时刻只处理一个事件不产生资源竞争这在可靠性要求高的场合非常珍贵。实战按键控制 LED六步搞定 官方仓库里带了examples/stm32f103、examples/stm32f030两个裸机例程我们把它们拆解成六个动作。第 1 步把源码放进你的工程git clone https://gitcode.com/gh_mirrors/eve/eventos然后只把eventos/目录eventos.c、eventos.h、eventos_config.h、eventos_def.h拷进工程剩下的都是你的业务代码。如果你用 MDK可以直接参考examples/stm32f103/MDK/eventos-nano.uvprojx的工程配置。第 2 步定义你自己的事件主题事件主题用一个枚举来定义起点必须是Event_User小于它的编号是框架系统事件别去占用enum { Event_KeyPress Event_User, // 按键按下 Event_LedToggle, // LED 翻转 Event_Max };这个枚举通常单独放在event_def.h里全工程共用。第 3 步初始化框架三件套在main()里按顺序调用每句都有明确职责eos_init(); // 框架本体初始化 eos_sub_init(sub_table, Event_Max); // 订阅表发布-订阅模式需要 eos_event_pool_init(heap, sizeof(heap)); // 事件池事件数据的内存来源如果你开启了发布-订阅EOS_USE_PUB_SUB订阅表和事件池都是必需的只想用最小内核的话这些都可以裁剪。第 4 步注册一个事件处理器Reactor 模式框架提供了两种业务载体入门先玩 Reactor——一个收到什么事件就处理什么事件的回调static void led_handler(eos_reactor_led_t *me, eos_event_t const *e) { if (e-topic Event_LedToggle) led_toggle(); // 收到翻转事件点亮/熄灭 LED } void app_led_init(void) { eos_reactor_init(led.super, 1, EOS_NULL); // 初始化1 是优先级 eos_reactor_start(led.super, EOS_HANDLER_CAST(led_handler)); // 挂上处理函数 }想进一步掌控状态跳转框架还内置了状态机模式HSM启用EOS_USE_SM_MODE后用eos_sm_init/eos_sm_start玩法类似但更强大。第 5 步按键按下发布事件按键扫描可以在中断里做也可以放在空闲钩子里。关键是发布动作只有一行eos_event_pub_topic(Event_KeyPress); // 不带数据最轻量 eos_event_pub(Event_KeyPress, data, sizeof(data)); // 想带数据用这个注意eos_event_pub_topic和eos_event_pub是仅有的两个允许在中断服务函数里调用的接口其他 API 别在中断里用否则可能崩溃。第 6 步启动事件循环剩下的交给框架eos_run(); // 主循环在这里跑起来永不返回再配合 1ms 的 SysTick 中断里调用eos_tick()提供时间基准你的按键 → 事件 → LED链路就完整跑起来了。中断负责投递信件eos_run负责逐封拆阅各干各的互不干扰。核心 API 速查表 接口一句话用途eos_init()框架打底初始化写业务代码前先调它eos_sub_init()为发布-订阅模式准备订阅表空间eos_event_pool_init()划一块内存给事件数据当仓库eos_run()启动事件循环让框架开始干活永不返回eos_tick()喂给框架的心跳放在定时器中断里eos_event_pub()/eos_event_pub_topic()发布事件前者携带数据、后者只有主题中断里可安全调用eos_event_pub_period()/eos_event_pub_delay()发布周期事件 / 延时事件免费送一个软定时器eos_reactor_init()/eos_reactor_start()初始化 Reactor 并挂上事件处理回调eos_sm_init()/eos_sm_start()初始化状态机并以某状态为起点启动EOS_EVENT_SUB()订阅某个主题之后相关事件才会送给你eos_delay()毫秒级延时不屏蔽事件接收、释放 CPU把它搬进你的工程三个必做一个可裁剪 必做一实现三个移植接口。框架把依赖硬件的地方收敛成了三个函数以 STM32 裸机为例临界区就是开关全局中断断言则打印错误码并死循环void eos_port_critical_enter(void) { __disable_irq(); } void eos_port_critical_exit(void) { __enable_irq(); } void eos_port_assert(eos_u32_t err) { user_print(ASSERT %d, err); while(1); }完整的裸机移植说明在移植文档跟着抄一遍即可。必做二实现三个回调钩子。eos_hook_idle空闲时做点轮询或干脆留空、eos_hook_start启动前初始化硬件、eos_hook_stop异常停止时安全关闭设备没有特殊需求时实现成空函数就能编过。必做三加上时间基准。在 1ms 定时器中断里调用eos_tick()并在eventos_config.h里把EOS_TICK_MS设为 1。可裁剪按需关特性。打开eventos/eventos_config.h把用不到的开关置 0 即可省资源EOS_USE_SM_MODE状态机、EOS_USE_PUB_SUB发布订阅、EOS_USE_TIME_EVENT时间事件、EOS_USE_EVENT_DATA事件数据。全裁干净后框架只剩 ROM 1.2KB / RAM 172 字节几乎可以静默嵌进任何系统。下一步往哪走跑通 LED 只是起点。EventOS Nano 还藏着一套好用的时间事件软定时器、层次状态机HSM和未来的事件桥机制都可以在你的第二个例程里尝鲜。想深入理解事件思想推荐读项目里的博客文章完整的快速入门见官方快速入门文档框架核心实现就在eventos/eventos.c配合test/目录里的单元测试一起读收获更大。下次当你再面对一个越写越臃肿的while(1)时不妨想想与其继续轮询不如让事件自己说话。【免费下载链接】eventos嵌入式开发框架事件驱动超级轻量。最低占用ROM 1.5KBRAM 172字节。核心技术是事件总线支持Reactor和状态机两种模式协作式内核极度可靠。可深度裁剪移植方便。项目地址: https://gitcode.com/gh_mirrors/eve/eventos创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考