MicroBus 入门:订阅话题,publish 发布事件
声明: MicroBus 是一个开源项目,作者为 Peter Vanderhell。本文是阅读该项目源码和文档后整理的入门笔记。本文作者不是该项目的开发者,未参与该项目的任何代码贡献。 示例代码已在本机 GCC 与 ARM GCC 下编译运行验证。
项目仓库:github.com/Vanderhell/MicroBus
这篇文章帮你完成一件事:把 MicroBus 跑起来,实现"传感器模块发布电压读数,多个模块按话题订阅接收"。核心概念只有两个:话题(topic,事件的类别)和订阅(subscribe,声明自己关心哪个话题)。事件携带的数据叫 payload(载荷)。
MicroBus 的调用流程
mbus_init()初始化总线mbus_subscribe()按话题注册回调mbus_publish()发布事件,同步调用话题匹配的回调
示例代码:传感器读数广播
mbus.h 自带默认配置(16 个订阅槽、32 字节 payload、8 深度队列),直接包含就能用:
#include "mbus.h"
#include <stdint.h>
#include <string.h>
static uint16_t g_last_mv;
static void on_sensor(const mbus_event_t *event, void *ctx)
{
(void)ctx;
if (event->payload_len != sizeof(uint16_t)) {
return;
}
memcpy(&g_last_mv, event->payload, sizeof(g_last_mv));
}
static void on_any(const mbus_event_t *event, void *ctx)
{
(void)event;
(void)ctx;
}
int main(void)
{
mbus_t bus;
uint16_t mv = 3300;
mbus_init(&bus, NULL); /* 1. 初始化,时钟可传 NULL */
/* 2. 订阅:on_sensor 只收 MBUS_TOPIC_SENSOR,on_any 收所有话题 */
mbus_subscribe(&bus, MBUS_TOPIC_SENSOR, on_sensor, NULL);
mbus_subscribe(&bus, MBUS_TOPIC_ANY, on_any, NULL);
/* 3. 立即发布:同步调用回调 */
mbus_publish(&bus, MBUS_TOPIC_SENSOR, &mv, sizeof(mv));
/* 4. 入队延后分发:先攒事件,主循环统一 dispatch */
mbus_queue(&bus, MBUS_TOPIC_SENSOR, &mv, sizeof(mv));
mbus_queue_signal(&bus, MBUS_TOPIC_BOOT);
mbus_dispatch(&bus);
return 0;
}运行输出(验证版加 printf):
sensor: 3300 mV
any event received, count=1
sensor: 3300 mV
any event received, count=2
any event received, count=3publish 立即触发 on_sensor 和 on_any 各一次;队列里的两个事件在 dispatch 时各触发一次,MBUS_TOPIC_BOOT 不带数据所以只有 on_any 收到。
mbus_config.h 配置项
MBUS_MAX_SUBSCRIBERS:订阅槽数量,默认 16MBUS_MAX_PAYLOAD:payload 上限,默认 32 字节MBUS_ENABLE_QUEUE:队列开关,默认 1MBUS_QUEUE_DEPTH:队列深度,默认 8,必须是 2 的幂MBUS_ISR_SAFE_QUEUE:ISR 安全模式,默认 0;开启需提供临界区宏
MicroBus 的特色
- 话题过滤:订阅时指定话题,回调只收到匹配事件;
MBUS_TOPIC_ANY通配 - payload 拷贝进事件对象,调用方的临时缓冲可以立刻复用
- 有界队列:ISR 里
mbus_queue入队,主循环mbus_dispatch统一处理 - 确定性:分发期间修改订阅表返回
MBUS_ERR_BUSY - 调用者持有状态:
mbus_t放栈或静态,可多实例
适用边界
- 默认单上下文,多线程访问需要外部加锁
- 话题空间 256 个,payload_len 单字节上限 255
mbus_t约 544 B RAM(16 订阅槽 + 8 队列,Cortex-M4),放栈上要确认栈空间足够