Skip to content

时间循环库

ESP32的系统API

事件循环库 - ESP32 - — ESP-IDF 编程指南 latest 文档 (espressif.com)

事件循环库使组件能够声明事件,允许其他组件注册处理程序(即在事件发生时执行的代码片段)。在其他组件状态变化时附加所需的行为。(可以理解为软件层面的中断)

当某个高级库要使用 Wi-Fi 库时,它可以直接订阅 ESP32 Wi-Fi 编程模型,对有关事件做出相应。

使用流程

  1. 定义一个函数,并在事件发布到事件循环中时运行该函数。此函数被称为事件处理程序,应具有与 esp_event_handler_t 同类型的签名。
c
typedef void (*esp_event_handler_t)(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
  1. 调用 esp_event_loop_create() 创建事件循环,该函数输出类型为 esp_event_loop_handle_t 的循环句柄,使用此 API 创建的事件循环称为用户事件循环。另有一种特殊事件循环,请参阅 默认事件循环
c
esp_err_t esp_event_loop_create(const esp_event_loop_args_t* event_loop_args, 
                                esp_event_loop_handle_t* event_loop)
  1. 调用 esp_event_handler_register_with() 将事件处理程序注册到循环中。处理程序可以注册到多个循环中,请参阅 注册处理程序注意事项
c
esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, 
                                          esp_event_base_t event_base,
                                          int32_t event_id, 
                                          esp_event_handler_t event_handler, 
                                          void* event_handler_arg)
esp_err_t esp_event_handler_instance_register_with(esp_event_loop_handle_t event_loop, 
                                                   esp_event_base_t event_base, 
                                                   int32_t event_id, 
                                                   esp_event_handler_t event_handler, 
                                                   void *event_handler_arg,
                                                   esp_event_handler_instance_t *instance);

event_loop: 要注册的事件组

event_base: base是一个字符串用于标识

event_id: 一个数字

event_handler: 处理函数

event_handler_arg: 传递给处理函数的参数

instance: 一般为NULL, 一个传出参数

这一个函数实际是创建了一个

c
/// Event posted to the event queue
typedef struct esp_event_post_instance {
#if CONFIG_ESP_EVENT_POST_FROM_ISR
    bool data_allocated;                                             /**< indicates whether data is allocated from heap */
    bool data_set;                                                   /**< indicates if data is null */
#endif
    esp_event_base_t base;                                           /**< the event base 事件的基类 */
    int32_t id;                                                      /**< the event id 事件的id*/
    esp_event_post_data_t data;                                      /**< data associated with the event 事件的数据*/
} esp_event_post_instance_t;
  1. 事件源调用 esp_event_post_to() 将事件发布到事件循环中。
c
esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, 
                            esp_event_base_t event_base, 
                            int32_t event_id,
                            const void* event_data, 
                            size_t event_data_size, 
                            TickType_t ticks_to_wait)
  1. 调用 esp_event_handler_unregister_with() ,组件可以在事件循环中取消注册事件处理程序。

  2. 调用 esp_event_loop_delete() 删除不再需要的事件循环。

事件定义与事件声明

如前所述,事件标识符由两部分组成:事件根基和事件 ID。事件根基标识独立的事件组;事件 ID 标识组中的特定事件。可以将事件根基和事件 ID 类比为人的姓和名,姓表示一个家族,名表示家族中的某个人。

默认事件循环

是一种特殊循环,用于处理系统事件(如 Wi-Fi 事件)。用户无法使用该循环的句柄,创建、删除、注册/注销处理程序以及事件发布均通过用户事件循环 API 的变体完成,下表列出了这些变体及其对应用户事件循环。

image-20240604092531370

c
esp_event_loop_create_default();

这一个函数实际是创建了一个线程, 这一个线程实际是在读取默认事件队列

在Wifi作为AP的时候, 如果有一个新的设备接入进来, 官方的底层会写入一个事件, 使用data这一个参数传递信息, 之后事件循环会调用相应的回调函数

c
esp_err_t esp_event_handler_instance_register(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg, esp_event_handler_instance_t *instance)

Register an instance of event handler to the default loop.

This function does the same as esp_event_handler_instance_register_with, except that it registers the handler to the default event loop.

这一个是一个省略第一个参数的注册函数