认识完ADF的pipeline,element和event之后,继续学习peripyh外设接口,也是非常重要的ADF的接口,本节以按键为例子。
本节参考源文件在adf/compoments/esp_peripherals目录
event接口广泛使用在各个接口,对event接口的认识非常重要。
一,esp32外设接口 periph
1,adf关于外设结构体的定义
esp_periph成员:
- tag:外设的标签,每个外设都有一个唯一的标签
- disable:布尔值,外设是否使能。
- periph_id:外设的id号,是在
esp_periph.h
文件中定义的元素 - init,run,destroy:是外设的相关函数
- state:外设工作状态
- data:外设对应的具体的外设结构体指针,如button结构体指针。
- event:外设的event接口,回调函数
- entries:指向下一个外设
esp_periph_set实际上一个管理所有外设对象的任务
- evengroup:事件标志组。
- lock:信号量。
- freertos任务配置。
- periph_event:外设事件。
- list:以esp_periph为成员的单链表。
periph_id:
/**
* @brief Peripheral Identify, this must be unique for each peripheral added to the peripherals list
*/
typedef enum {
PERIPH_ID_BUTTON = AUDIO_ELEMENT_TYPE_PERIPH + 1,
PERIPH_ID_TOUCH = AUDIO_ELEMENT_TYPE_PERIPH + 2,
PERIPH_ID_SDCARD = AUDIO_ELEMENT_TYPE_PERIPH + 3,
PERIPH_ID_WIFI = AUDIO_ELEMENT_TYPE_PERIPH + 4,
PERIPH_ID_FLASH = AUDIO_ELEMENT_TYPE_PERIPH + 5,
PERIPH_ID_AUXIN = AUDIO_ELEMENT_TYPE_PERIPH + 6,
PERIPH_ID_ADC = AUDIO_ELEMENT_TYPE_PERIPH + 7,
PERIPH_ID_CONSOLE = AUDIO_ELEMENT_TYPE_PERIPH + 8,
PERIPH_ID_BLUETOOTH = AUDIO_ELEMENT_TYPE_PERIPH + 9,
PERIPH_ID_LED = AUDIO_ELEMENT_TYPE_PERIPH + 10,
PERIPH_ID_SPIFFS = AUDIO_ELEMENT_TYPE_PERIPH + 11,
PERIPH_ID_ADC_BTN = AUDIO_ELEMENT_TYPE_PERIPH + 12,
PERIPH_ID_IS31FL3216 = AUDIO_ELEMENT_TYPE_PERIPH + 13,
PERIPH_ID_GPIO_ISR = AUDIO_ELEMENT_TYPE_PERIPH + 14,
PERIPH_ID_WS2812 = AUDIO_ELEMENT_TYPE_PERIPH + 15,
PERIPH_ID_AW2013 = AUDIO_ELEMENT_TYPE_PERIPH + 16
} esp_periph_id_t;
二,button外设
button外设接口逻辑框图:(参考periph_button.h
)
periph_button_cfg_t
是用户来配置periph_button
的结构体,用户可以配置的是按键的gpio和长按的时间。
button外设初始化逻辑图:
先初始化一个esp_periph
接口,然后再初始化esp_button_handle
,最后将button_item添加到list,当然这些都是ADF帮我们做好的。
三,用户代码
用户代码的逻辑是:初始化esp_periph_set,根据esp_periph_set创建esp_periph,esp_button_handle,初始化一个单链表,然后创建一个event事件接口,设置外设event的监听者。在任务中监听事件的消息,并根据消息内容作出动作。
初始化代码:
//初始化默认外设接口
esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();
esp_periph_set_handle_t set = esp_periph_set_init(&periph_cfg);
//初始化按键外设
ESP_LOGI(TAG, "[1.1] Initialize keys on board");
audio_board_key_init(set);
//创建event接口
ESP_LOGI(TAG, "[ 1.2 ] Set up event listener");
audio_event_iface_cfg_t evt_cfg = AUDIO_EVENT_IFACE_DEFAULT_CFG();
audio_event_iface_handle_t evt = audio_event_iface_init(&evt_cfg);
//监听按键的事件
ESP_LOGI(TAG, "[1.3] Listening event from button peripherals");
audio_event_iface_set_listener(esp_periph_set_get_event_iface(set), evt);
处理代码:
audio_event_iface_listen();
会使任务进入阻塞态直到接收到event的消息。
audio_event_iface_msg_t msg;
esp_err_t ret = audio_event_iface_listen(evt, &msg, portMAX_DELAY);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "[ * ] Event interface error : %d", ret);
continue;
}
if ((msg.source_type == PERIPH_ID_TOUCH || msg.source_type == PERIPH_ID_BUTTON || msg.source_type == PERIPH_ID_ADC_BTN)
&& (msg.cmd == PERIPH_TOUCH_TAP || msg.cmd == PERIPH_BUTTON_PRESSED || msg.cmd == PERIPH_ADC_BUTTON_PRESSED)) {
if ((int) msg.data == get_input_play_id()){
ESP_LOGI(TAG, "GPIO_NUM_23");
}
else if((int) msg.data == get_input_volup_id()){
ESP_LOGI(TAG, "GPIO_NUM_18");
}
else if((int) msg.data == get_input_voldown_id()){
ESP_LOGI(TAG, "GPIO_NUM_5");
}
}
msg结构体定义如下:
- cmd:命令的id,也就是event的id,这里是
button_event_id
- data:这里存放的是按键按下对应的gpio号
- source:指向periph_button_handle
- source_type:event源的类型,外设event的类型定义在
periph_id
根据这些信息用户就可以作出相应的以上动作
/**
* Event message
*/
typedef struct {
int cmd; /*!< Command id */
void *data; /*!< Data pointer */
int data_len; /*!< Data length */
void *source; /*!< Source event */
int source_type; /*!< Source type (To know where it came from) */
bool need_free_data; /*!< Need to free data pointer after the event has been processed */
} audio_event_iface_msg_t;