05 ESP32 Event Loop
事件循环含义
如果学习过QT信号与槽,或者其他消息机制,这一部分会很好上手.ESP_IDF中的事件循环机制,可以实现不同组件之间的事件传递,能够降低不同组件之间的耦合,自由组合资源.举个简单的例子理解:
A,B,C 三个节点想实现相互之间的消息传递,一种简单的方法是,A,B,C 分别不停的去访问其他节点,询问是否有新事件发生.这样势必会增加整体计算的负担,另外也会涉及到很多问题,比如何时清除事件标志,保证既能够通知到所有关心该事件的节点又能防止重复的通知.
如果这时候引入D去统一管理,会把问题极大的简化.A,B,C分别到D处登记自己关心的事件,登记完成后由D去进行问询和分发,A,B,C可以专心做自己的事情,当需要发信号时,直接发送到D,当D发现有事件发生后,会根据登记的内容和先后顺序,通知对应的节点去处理.
ESP_IDF事件循环使用过程
定义事件处理函数 esp_event_handler_t
创建一个事件循环esp_event_loop_create(),创建完成后会返回事件循环句柄(作用相当于D)
向事件循环注册事件esp_event_handler_register_with(),添加回调函数.(注册关注哪个事件,事件发生后执行哪个函数)
事件发生时,向事件循环发生通知esp_event_post_to().
// 1. Define the event handler
void run_on_event(void* handler_arg, esp_event_base_t base, int32_t id, void* event_data)
{
// Event handler logic
}
void app_main()
{
// 2. A configuration structure of type esp_event_loop_args_t is needed to specify the properties of the loop to be
// created. A handle of type esp_event_loop_handle_t is obtained, which is needed by the other APIs to reference the loop
// to perform their operations on.
esp_event_loop_args_t loop_args = {
.queue_size = ...,
.task_name = ...
.task_priority = ...,
.task_stack_size = ...,
.task_core_id = ...
};
esp_event_loop_handle_t loop_handle;
esp_event_loop_create(&loop_args, &loop_handle)
// 3. Register event handler defined in (1). MY_EVENT_BASE and MY_EVENT_ID specifies a hypothetical
// event that handler run_on_event should execute on when it gets posted to the loop.
esp_event_handler_register_with(loop_handle, MY_EVENT_BASE, MY_EVENT_ID, run_on_event, ...);
...
// 4. Post events to the loop. This queues the event on the event loop. At some point in time
// the event loop executes the event handler registered to the posted event, in this case run_on_event.
// For simplicity sake this example calls esp_event_post_to from app_main, but posting can be done from
// any other tasks (which is the more interesting use case).
esp_event_post_to(loop_handle, MY_EVENT_BASE, MY_EVENT_ID, ...);
...
// 5. Unregistering an unneeded handler
esp_event_handler_unregister_with(loop_handle, MY_EVENT_BASE, MY_EVENT_ID, run_on_event);
...
// 6. Deleting an unneeded event loop
esp_event_loop_delete(loop_handle);
}
使用事件循环注意事项
以上方法是来自新的ESP_IDF功能设计,我们在网上例程中会经常见到
esp_event_loop_init(system_event_cb_tcb, void *ctx)
这是向上兼容的比较早期的事件循环的版本,这个事件循环用于接收系统事件(如WiFi链接,具体可看system_event_info_t),另外在初始化就限定了只能有一个回调函数,功能不如现在的庞大.可以在这里查阅详情esp_event_legacy
最后更新于
这有帮助吗?