目录
- 外设集合管理API
- esp_periph_set_init
- esp_periph_set_destroy
- esp_periph_set_stop_all
- esp_periph_set_get_by_id
- esp_periph_set_get_event_iface
- esp_periph_set_register_callback
- esp_periph_set_get_queue
- esp_periph_set_list_init
- esp_periph_set_list_run
- esp_periph_set_list_destroy
- esp_periph_remove_from_set
- esp_periph_alloc_periph_id
- esp_periph_set_change_waiting_time
外设集合管理API
esp_periph_set_init
功能描述:初始化外设集合,创建管理外设的数据结构和相关资源。
函数原型:
/**
* @brief 初始化外设集合
*
* @param[in] config 外设集合配置参数
*
* @return 成功:返回外设集合句柄
* 失败:返回NULL
*/
esp_periph_set_handle_t esp_periph_set_init(esp_periph_config_t *config)
{
/* 初始化重要变量 */
esp_err_t ret = ESP_OK;
esp_periph_set_t *periph_sets = NULL;
int _err_step = 1; // 用于跟踪初始化进度的阶段计数器
/* 使用链式执行分配关键资源,失败则出错 */
bool _success = (
(periph_sets = audio_calloc(1, sizeof(esp_periph_set_t))) && _err_step++ &&
(periph_sets->state_event_bits = xEventGroupCreate()) && _err_step++ &&
(periph_sets->lock = mutex_create()) && _err_step++
);
AUDIO_MEM_CHECK(TAG, _success, {
goto _periph_init_failed;
});
/* 初始化外设对象的链表结构,用于存储所有注册的外设 */
STAILQ_INIT(&periph_sets->periph_list);
/* 安装GPIO中断服务,优先级设为LEVEL2 */
ret = gpio_install_isr_service(ESP_INTR_FLAG_LEVEL2);
if (ret == ESP_ERR_NOT_FOUND) {
ESP_LOGE(TAG, "No free interrupt found with ESP_INTR_FLAG_LEVEL2");
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0))
ESP_LOGE(TAG, "Select an available interrupt level based on the interrupt table below");
esp_intr_dump(stdout);
#endif // ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
}
/* 配置外设集合状态和运行参数 */
periph_sets->run = false; // 初始为非运行状态
xEventGroupClearBits(periph_sets->state_event_bits, STARTED_BIT); // 清除已启动标志
xEventGroupSetBits(periph_sets->state_event_bits, STOPPED_BIT); // 设置已停止标志
/* 从用户配置中读取任务参数 */
periph_sets->task_stack = config->task_stack; // 任务栈大小
periph_sets->task_prio = config->task_prio; // 任务优先级
periph_sets->task_core = config->task_core; // 指定运行核心
periph_sets->ext_stack = config->extern_stack; // 是否使用外部RAM
/* 初始化事件处理接口 */
audio_event_iface_cfg_t event_cfg = AUDIO_EVENT_IFACE_DEFAULT_CFG();
event_cfg.queue_set_size = 0; // 不使用队列集
event_cfg.context = periph_sets; // 上下文为外设集合
event_cfg.on_cmd = process_peripheral_event; // 设置外设事件处理回调
periph_sets->event_handle.iface = audio_event_iface_init(&event_cfg);
periph_sets->periph_dynamic_id = PERIPH_ID_CUSTOM_BASE; // 设置自定义外设id的起始id
/* 验证事件接口初始化结果并设置超时时间 */
AUDIO_MEM_CHECK(TAG, periph_sets->event_handle.iface, goto _periph_init_failed);
audio_event_iface_set_cmd_waiting_timeout(periph_sets->event_handle.iface, DEFAULT_ESP_PERIPH_WAIT_TICK);
return periph_sets;
_periph_init_failed:
/* 错误处理:释放已分配的所有资源 */
if (periph_sets) {
mutex_destroy(periph_sets->lock);
vEventGroupDelete(periph_sets->state_event_bits);
if (periph_sets->event_handle.iface) {
audio_event_iface_destroy(periph_sets->event_handle.iface);
}
audio_free(periph_sets);
periph_sets = NULL;
}
return NULL;
}
参数说明:
config
:外设集合配置参数,类型为esp_periph_config_t
task_stack
:服务任务栈大小,建议值为4KB(4096),过小可能导致栈溢出task_prio
:服务任务优先级,建议值为5,范围为1-25,值越大优先级越高task_core
:服务任务运行核心,范围为0-1,表示运行在核心0或桃1上extern_stack
:是否使用外部RAM分配栈,默认为false
返回值:
- 成功:返回外设集合句柄,类型为
esp_periph_set_handle_t
- 失败:返回
NULL
,通常是由于内存分配失败
调用示例:
// 使用默认配置初始化外设集合
esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();
esp_periph_set_handle_t set = esp_periph_set_init(&periph_cfg);
if (set == NULL) {
ESP_LOGE(TAG, "Failed to init periph set");
return ESP_FAIL;
}
初始化时序图:
下图展示了esp_periph_set_init
函数的执行流程和关键步骤之间的交互关系:
这个时序图直观展示了初始化过程中的关键步骤,包括资源分配、状态设置、事件系统初始化和错误处理策略。
esp_periph_set_destroy
功能描述:销毁外设集合,释放相关资源。
函数原型:
/**
* @brief 销毁外设集合
*
* @param[in] periph_set_handle 外设集合句柄
*
* @return 成功:ESP_OK
* 失败:ESP_FAIL
*/
esp_err_t esp_periph_set_destroy(esp_periph_set_handle_t periph_set_handle)
{
/* 参数检查 */
if (periph_set_handle == NULL) {
AUDIO_ERROR(TAG, "Peripherals have not been initialized");
return ESP_FAIL;
}
/* 停止运行并等待外设完全停止 */
periph_set_handle->run = false; // 设置运行标志为关闭状态
esp_periph_wait_for_stop(periph_set_handle, portMAX_DELAY); // 无限期等待外设停止
/* 遍历并安全清空所有外设 */
esp_periph_handle_t item, tmp;
STAILQ_FOREACH_SAFE(item, &periph_set_handle->periph_list, entries, tmp) {
STAILQ_REMOVE(&periph_set_handle->periph_list, item, esp_periph, entries); // 从链表移除
audio_free(item->tag); // 释放外设标签内存
audio_free(item); // 释放外设对象内存
}
/* 释放系统资源 */
mutex_destroy(periph_set_handle->lock); // 释放互斥锁
vEventGroupDelete(periph_set_handle->state_event_bits); // 释放事件组
gpio_uninstall_isr_service(); // 卸载GPIO中断服务
audio_event_iface_destroy(periph_set_handle->event_handle.iface); // 释放事件接口
/* 释放外设集合本身并置空句柄 */
audio_free(periph_set_handle);
periph_set_handle = NULL; // 将句柄设置为空
return ESP_OK;
}
参数说明:
periph_set_handle
:外设集合句柄,通过esp_periph_set_init
获得
返回值:
- 成功:返回
ESP_OK
- 失败:返回
ESP_FAIL
调用示例:
// 销毁外设集合
esp_err_t ret = esp_periph_set_destroy(set);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to destroy periph set");
}
销毁时序图:
下面的时序图展示了esp_periph_set_destroy
函数的执行流程和资源释放顺序:
这个时序图直观展示了销毁过程中的资源释放顺序,包括停止外设运行、清空外设链表、释放系统资源以及错误处理策略。
esp_periph_set_stop_all
功能描述:停止外设集合中的所有外设。
函数原型:
/**
* @brief 停止集合中的所有外设
*
* @details 通过设置每个外设的disabled标志为true来停止所有外设。
* 当外设的disabled标志为true时,外设将在其处理循环中检测到此标志并停止运行。
* 与esp_periph_set_destroy不同,此函数仅禁用外设,不会释放资源。
*
* @param[in] periph_set_handle 外设集合句柄
*
* @return 成功:ESP_OK
* 失败:ESP_FAIL 参数无效(periph_set_handle为NULL)
*/
esp_err_t esp_periph_set_stop_all(esp_periph_set_handle_t periph_set_handle)
{
/* 参数检查 */
if (periph_set_handle == NULL) {
AUDIO_ERROR(TAG, "Peripherals have not been initialized");
return ESP_FAIL;
}
/* 遍历外设链表并设置禁用标志 */
esp_periph_handle_t periph;
STAILQ_FOREACH(periph, &periph_set_handle->periph_list, entries) {
periph->disabled = true; // 设置禁用标志,使外设在下一轮循环中停止
}
return ESP_OK;
}
参数说明:
periph_set_handle
:外设集合句柄,通过esp_periph_set_init
获得
返回值:
- 成功:返回
ESP_OK
- 失败:返回
ESP_FAIL
调用示例:
// 停止所有外设
esp_err_t ret = esp_periph_set_stop_all(set);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to stop all peripherals");
}
停止外设时序图:
这个时序图展示了esp_periph_set_stop_all
函数的执行流程,包括参数检查、遍历外设链表、禁用每个外设以及返回结果。
esp_periph_set_get_by_id
功能描述:通过外设ID查找外设集合中的外设句柄。
函数原型:
/**
* @brief 通过外设ID查找外设句柄
*
* @details 遍历外设集合中的链表,查找与指定ID匹配的外设。
* 此函数会在查找过程中对外设链表加锁,以保证线程安全。
* 如果找到匹配的外设,则返回其句柄;否则返回NULL。
*
* @param[in] periph_set_handle 外设集合句柄
* @param[in] periph_id 要查找的外设ID
*
* @return 成功:返回匹配的外设句柄
* 失败:返回NULL(参数无效或未找到指定ID的外设)
*/
esp_periph_handle_t esp_periph_set_get_by_id(esp_periph_set_handle_t periph_set_handle, int periph_id)
{
/* 参数检查 */
esp_periph_handle_t periph;
if (periph_set_handle == NULL) {
AUDIO_ERROR(TAG, "Peripherals have not been initialized");
return NULL;
}
/* 加锁并遍历链表查找外设 */
mutex_lock(periph_set_handle->lock);
STAILQ_FOREACH(periph, &periph_set_handle->periph_list, entries) {
if (periph->periph_id == periph_id) {
mutex_unlock(periph_set_handle->lock);
return periph; // 找到匹配的外设,返回其句柄
}
}
/* 未找到匹配的外设 */
ESP_LOGD(TAG, "Periph id %d not found", periph_id);
mutex_unlock(periph_set_handle->lock);
return NULL;
}
参数说明:
periph_set_handle
:外设集合句柄,通过esp_periph_set_init
获得periph_id
:要查找的外设ID,可以是预定义的esp_periph_id_t
枚举值或自定义的外设ID
返回值:
- 成功:返回匹配的外设句柄
- 失败:返回
NULL
(参数无效或未找到指定ID的外设)
调用示例:
// 获取按钮外设句柄
esp_periph_handle_t button = esp_periph_set_get_by_id(set, PERIPH_ID_BUTTON);
if (button != NULL) {
// 对按钮外设进行操作
esp_periph_stop(button);
} else {
ESP_LOGE(TAG, "Button peripheral not found");
}
查找外设时序图:
这个时序图展示了esp_periph_set_get_by_id
函数的执行流程,包括参数检查、加锁操作、遍历外设链表查找匹配ID的外设、释放锁以及返回结果。
esp_periph_set_get_event_iface
功能描述:获取外设集合的事件接口句柄。
函数原型:
/**
* @brief 获取外设集合的事件接口句柄
*
* @details 返回外设集合内部使用的事件接口句柄,应用程序可以使用此接口直接访问事件系统。
* 通过此接口,应用程序可以监听和处理所有外设产生的事件。
*
* @param[in] periph_set_handle 外设集合句柄
*
* @return 返回事件接口句柄(audio_event_iface_handle_t)
*/
audio_event_iface_handle_t esp_periph_set_get_event_iface(esp_periph_set_handle_t periph_set_handle)
{
return periph_set_handle->event_handle.iface;
}
参数说明:
periph_set_handle
:外设集合句柄,通过esp_periph_set_init
获得
返回值:
- 返回事件接口句柄(audio_event_iface_handle_t)
调用示例:
// 获取外设集合的事件接口
audio_event_iface_handle_t evt = esp_periph_set_get_event_iface(set);
if (evt) {
// 使用事件接口处理外设事件
audio_event_iface_msg_t msg;
esp_err_t ret = audio_event_iface_listen(evt, &msg, portMAX_DELAY);
if (ret == ESP_OK) {
// 处理事件...
}
}
获取事件接口时序图:
这个时序图展示了esp_periph_set_get_event_iface
函数的执行流程,以及应用程序如何使用获取到的事件接口来监听和处理外设事件。
esp_periph_set_register_callback
功能描述:为外设集合注册事件回调函数,当有外设事件发生时会调用该回调。
函数原型:
/**
* @brief 注册外设集合的事件回调函数
*
* @details 为外设集合设置一个全局事件处理回调函数。当外设产生事件时,
* 除了通过事件接口发送事件外,还会调用此回调函数进行额外处理。
* 这使应用程序可以集中处理所有外设事件。
*
* @param[in] periph_set_handle 外设集合句柄
* @param[in] cb 事件回调函数
* @param[in] user_context 用户上下文指针,会在回调函数中传递
*
* @return 成功:ESP_OK
* 失败:ESP_FAIL(参数无效)
*/
esp_err_t esp_periph_set_register_callback(esp_periph_set_handle_t periph_set_handle, esp_periph_event_handle_t cb, void *user_context)
{
if (periph_set_handle == NULL) {
return ESP_FAIL;
} else {
periph_set_handle->event_handle.cb = cb;
periph_set_handle->event_handle.user_ctx = user_context;
return ESP_OK;
}
}
参数说明:
periph_set_handle
:外设集合句柄,通过esp_periph_set_init
获得cb
:事件回调函数,函数原型为esp_err_t (*esp_periph_event_handle_t)(audio_event_iface_msg_t *event, void *context)
user_context
:用户上下文指针,会在回调函数中传递给应用程序
返回值:
- 成功:返回
ESP_OK
- 失败:返回
ESP_FAIL
(参数无效)
调用示例:
// 定义事件回调函数
static esp_err_t periph_event_handler(audio_event_iface_msg_t *event, void *context)
{
// 处理不同类型的外设事件
switch (event->source_type) {
case PERIPH_ID_BUTTON:
// 处理按钮事件...
break;
case PERIPH_ID_TOUCH:
// 处理触摸事件...
break;
default:
break;
}
return ESP_OK;
}
// 注册回调函数
esp_err_t ret = esp_periph_set_register_callback(set, periph_event_handler, NULL);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to register peripheral event callback");
}
注册回调时序图:
这个时序图展示了esp_periph_set_register_callback
函数的执行流程,包括参数检查、设置回调函数和上下文,以及回调函数在外设事件发生时的调用过程。
esp_periph_set_get_queue
功能描述:获取外设集合使用的事件队列句柄,可用于直接访问和处理事件队列。
函数原型:
/**
* @brief 获取外设集合的事件队列句柄
*
* @details 返回外设集合内部事件接口使用的队列句柄。应用程序可以使用此队列句柄
* 直接访问事件队列,例如在需要与其他队列一起使用 xQueueSelectFromSet
* 进行多队列监听的场景。
*
* @param[in] periph_set_handle 外设集合句柄
*
* @return 返回队列句柄(QueueHandle_t)
*/
QueueHandle_t esp_periph_set_get_queue(esp_periph_set_handle_t periph_set_handle)
{
return audio_event_iface_get_queue_handle(periph_set_handle->event_handle.iface);
}
参数说明:
periph_set_handle
:外设集合句柄,通过esp_periph_set_init
获得
返回值:
- 返回外设集合使用的事件队列句柄(QueueHandle_t)
调用示例:
// 获取外设集合的队列句柄
QueueHandle_t periph_queue = esp_periph_set_get_queue(set);
if (periph_queue) {
// 使用队列句柄进行操作
// 例如:与其他队列一起使用
QueueSetHandle_t queue_set = xQueueCreateSet(10);
xQueueAddToSet(periph_queue, queue_set);
// 从队列集合中等待事件
QueueSetMemberHandle_t active_member = xQueueSelectFromSet(queue_set, portMAX_DELAY);
if (active_member == periph_queue) {
// 处理外设事件...
}
}
获取队列时序图:
这个时序图展示了esp_periph_set_get_queue
函数的执行流程,以及应用程序如何使用获取到的队列句柄进行进一步操作。
esp_periph_set_list_init
功能描述:初始化外设集合中的所有外设,适用于无任务模式的外设集合。
函数原型:
/**
* @brief 初始化外设集合中的所有外设
*
* @details 遍历外设集合中的所有外设,并调用每个外设的初始化函数。
* 此函数专为无任务模式的外设集合设计,即在创建外设集合时
* 未指定任务栈大小(task_stack = 0)的情况。
* 在无任务模式下,应用程序需要手动调用此函数进行初始化。
*
* @param[in] periph_set 外设集合句柄
*
* @return 成功:ESP_OK
* 失败:ESP_FAIL
*/
esp_err_t esp_periph_set_list_init(esp_periph_set_handle_t periph_set)
{
esp_periph_handle_t periph;
STAILQ_FOREACH(periph, &periph_set->periph_list, entries) {
if (periph->init) {
periph->init(periph);
}
}
return ESP_OK;
}
参数说明:
periph_set
:外设集合句柄,通过esp_periph_set_init
获得
返回值:
- 成功:返回
ESP_OK
- 失败:返回
ESP_FAIL
调用示例:
// 创建无任务模式的外设集合
esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();
periph_cfg.task_stack = 0; // 设置为无任务模式
esp_periph_set_handle_t set = esp_periph_set_init(&periph_cfg);
// 添加外设
esp_periph_handle_t button = periph_button_init(&button_cfg);
esp_periph_start(set, button);
// 手动初始化所有外设
esp_err_t ret = esp_periph_set_list_init(set);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize peripherals");
}
// 在主循环中手动运行外设
while (1) {
audio_event_iface_msg_t msg;
// 从某处获取消息...
esp_periph_set_list_run(set, msg);
vTaskDelay(10 / portTICK_PERIOD_MS);
}
初始化列表时序图:
这个时序图展示了esp_periph_set_list_init
函数的执行流程,包括遍历外设链表并调用每个外设的初始化函数。此函数专为无任务模式的外设集合设计,允许应用程序手动控制外设的初始化过程。
esp_periph_set_list_run
功能描述:运行外设集合中的所有外设,处理指定的事件消息,适用于无任务模式的外设集合。
函数原型:
/**
* @brief 运行外设集合中的所有外设
*
* @details 遍历外设集合中的所有外设,并调用每个外设的运行函数处理指定的消息。
* 此函数专为无任务模式的外设集合设计,需要在应用程序的主循环中
* 定期调用,以确保外设能正常处理事件。
*
* @param[in] periph_set 外设集合句柄
* @param[in] msg 要处理的事件消息
*
* @return 成功:ESP_OK
* 失败:ESP_FAIL
*/
esp_err_t esp_periph_set_list_run(esp_periph_set_handle_t periph_set, audio_event_iface_msg_t msg)
{
esp_periph_handle_t periph;
STAILQ_FOREACH(periph, &periph_set->periph_list, entries) {
if (periph->run) {
periph->run(periph, &msg);
}
}
return ESP_OK;
}
参数说明:
periph_set
:外设集合句柄,通过esp_periph_set_init
获得msg
:要处理的事件消息,包含命令、数据和源信息
返回值:
- 成功:返回
ESP_OK
- 失败:返回
ESP_FAIL
调用示例:
// 创建无任务模式的外设集合
esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();
periph_cfg.task_stack = 0; // 设置为无任务模式
esp_periph_set_handle_t set = esp_periph_set_init(&periph_cfg);
// 添加外设并初始化
esp_periph_handle_t button = periph_button_init(&button_cfg);
esp_periph_start(set, button);
esp_periph_set_list_init(set);
// 获取事件接口和队列
audio_event_iface_handle_t evt = esp_periph_set_get_event_iface(set);
QueueHandle_t queue = esp_periph_set_get_queue(set);
// 在主循环中手动运行外设
while (1) {
audio_event_iface_msg_t msg;
// 从队列中获取消息
if (xQueueReceive(queue, &msg, portMAX_DELAY) == pdTRUE) {
// 调用所有外设的运行函数处理消息
esp_periph_set_list_run(set, msg);
// 处理消息后的其他操作...
}
}
运行列表时序图:
这个时序图展示了esp_periph_set_list_run
函数的执行流程,包括如何从队列中获取消息并遍历外设链表调用每个外设的运行函数处理消息。此函数与esp_periph_set_list_init
配合使用,实现无任务模式下的外设运行控制。
esp_periph_set_list_destroy
功能描述:销毁外设集合中的所有外设,适用于无任务模式的外设集合。
函数原型:
/**
* @brief 销毁外设集合中的所有外设
*
* @details 遍历外设集合中的所有外设,并调用每个外设的销毁函数。
* 此函数专为无任务模式的外设集合设计,在应用程序需要
* 手动释放外设资源时使用。注意这不会释放外设集合本身的资源,
* 只是调用每个外设的销毁函数。
*
* @param[in] periph_set 外设集合句柄
*
* @return 成功:ESP_OK
* 失败:ESP_FAIL
*/
esp_err_t esp_periph_set_list_destroy(esp_periph_set_handle_t periph_set)
{
esp_periph_handle_t periph;
STAILQ_FOREACH(periph, &periph_set->periph_list, entries) {
if (periph->destroy) {
periph->destroy(periph);
}
}
return ESP_OK;
}
参数说明:
periph_set
:外设集合句柄,通过esp_periph_set_init
获得
返回值:
- 成功:返回
ESP_OK
- 失败:返回
ESP_FAIL
调用示例:
// 创建无任务模式的外设集合
esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();
periph_cfg.task_stack = 0; // 设置为无任务模式
esp_periph_set_handle_t set = esp_periph_set_init(&periph_cfg);
// 添加外设并初始化
esp_periph_handle_t button = periph_button_init(&button_cfg);
esp_periph_start(set, button);
esp_periph_set_list_init(set);
// 使用外设进行操作...
// 应用程序结束时销毁外设
esp_periph_set_list_destroy(set);
// 完全释放外设集合资源
esp_periph_set_destroy(set);
销毁列表时序图:
这个时序图展示了esp_periph_set_list_destroy
函数的执行流程,包括遍历外设链表并调用每个外设的销毁函数。此函数与esp_periph_set_list_init
和esp_periph_set_list_run
配合使用,完成无任务模式下外设的完整生命周期管理。
注意:与esp_periph_set_destroy
不同,此函数仅调用外设的销毁函数,不会释放外设集合本身的资源或从链表中移除外设。完全释放外设集合的资源需要调用esp_periph_set_destroy
函数。
esp_periph_remove_from_set
功能描述:从外设集合中移除指定的外设,并取消其事件注册。
函数原型:
/**
* @brief 从外设集合中移除指定的外设
*
* @details 将指定的外设从外设集合的链表中移除,并取消其事件注册。
* 注意这不会销毁外设或释放其资源,只是从集合中移除其引用。
* 如果需要销毁外设,应在调用此函数前手动调用外设的销毁函数。
*
* @param[in] periph_set_handle 外设集合句柄
* @param[in] periph 要移除的外设句柄
*
* @return 成功:ESP_OK
* 失败:ESP_FAIL
*/
esp_err_t esp_periph_remove_from_set(esp_periph_set_handle_t periph_set_handle, esp_periph_handle_t periph)
{
STAILQ_REMOVE(&periph_set_handle->periph_list, periph, esp_periph, entries);
esp_periph_register_on_events(periph, NULL);
return ESP_OK;
}
参数说明:
periph_set_handle
:外设集合句柄,通过esp_periph_set_init
获得periph
:要从集合中移除的外设句柄
返回值:
- 成功:返回
ESP_OK
- 失败:返回
ESP_FAIL
调用示例:
// 创建外设集合
esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();
esp_periph_set_handle_t set = esp_periph_set_init(&periph_cfg);
// 添加外设
esp_periph_handle_t button = periph_button_init(&button_cfg);
esp_periph_start(set, button);
// 使用外设...
// 如果需要先停止外设
esp_periph_stop(button);
// 从集合中移除外设
esp_periph_remove_from_set(set, button);
// 如果需要,手动销毁外设
// 注意:在某些情况下,外设可能需要先调用其销毁函数
// button->destroy(button);
移除外设时序图:
这个时序图展示了esp_periph_remove_from_set
函数的执行流程,包括从外设链表中移除外设并取消其事件注册的过程。
注意:此函数只从外设集合中移除外设的引用,不会销毁外设或释放其资源。如果需要完全清理外设资源,应先停止外设,然后手动调用其销毁函数,最后再从集合中移除。
esp_periph_alloc_periph_id
功能描述:为自定义外设分配唯一的外设 ID。
函数原型:
/**
* @brief 为自定义外设分配唯一的外设 ID
*
* @details 从外设集合的动态 ID 计数器中分配一个新的唯一 ID。
* 当创建自定义外设时,如果不想使用预定义的 ID,可以使用此函数
* 获取唯一的 ID。所有自定义外设的 ID 都从 PERIPH_ID_CUSTOM_BASE 开始递增。
*
* @param[in] periph_set_handle 外设集合句柄
* @param[out] periph_id 用于存储分配的外设 ID 的指针
*
* @return 成功:ESP_OK
* 失败:ESP_FAIL(当参数无效时)
*/
esp_err_t esp_periph_alloc_periph_id(esp_periph_set_handle_t periph_set_handle, int *periph_id)
{
if ((periph_set_handle == NULL) || (periph_id == NULL)) {
AUDIO_ERROR(TAG, "Invalid parameters: periph_set_handle or periph_id is NULL");
return ESP_FAIL;
}
*periph_id = periph_set_handle->periph_dynamic_id++;
return ESP_OK;
}
参数说明:
periph_set_handle
:外设集合句柄,通过esp_periph_set_init
获得periph_id
:输出参数,用于存储分配的外设 ID
返回值:
- 成功:返回
ESP_OK
- 失败:返回
ESP_FAIL
(当参数无效时)
调用示例:
// 创建外设集合
esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();
esp_periph_set_handle_t set = esp_periph_set_init(&periph_cfg);
// 为自定义外设分配 ID
int my_periph_id;
esp_err_t ret = esp_periph_alloc_periph_id(set, &my_periph_id);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to allocate peripheral ID");
return;
}
// 使用分配的 ID 创建自定义外设
esp_periph_handle_t my_periph = esp_periph_create(my_periph_id, "my_custom_periph");
if (my_periph == NULL) {
ESP_LOGE(TAG, "Failed to create custom peripheral");
return;
}
// 设置外设函数
esp_periph_set_function(my_periph, my_init_cb, my_run_cb, my_destroy_cb);
// 启动外设
esp_periph_start(set, my_periph);
分配 ID 时序图:
这个时序图展示了esp_periph_alloc_periph_id
函数的执行流程,包括如何从外设集合中分配唯一 ID 并在后续创建自定义外设的过程。
注意:使用此函数分配的 ID 都是从PERIPH_ID_CUSTOM_BASE
开始递增的值,确保不会与预定义的外设 ID 冲突。这对于开发自定义外设非常有用,特别是当需要在运行时动态创建多个自定义外设时。
esp_periph_set_change_waiting_time
功能描述:更改外设集合的命令等待超时时间。
函数原型:
/**
* @brief 更改外设集合的命令等待超时时间
*
* @details 设置外设集合事件接口的命令等待超时时间。
* 在外设任务循环中,当没有命令需要处理时,任务会等待一段时间。
* 这个函数允许调整这个等待时间,以平衡响应速度和系统资源消耗。
*
* @param[in] periph_set_handle 外设集合句柄
* @param[in] time_ms 等待时间,单位为毫秒
*
* @return 成功:ESP_OK
*/
esp_err_t esp_periph_set_change_waiting_time(esp_periph_set_handle_t periph_set_handle, int time_ms)
{
audio_event_iface_set_cmd_waiting_timeout(esp_periph_set_get_event_iface(periph_set_handle), time_ms / portTICK_RATE_MS);
return ESP_OK;
}
参数说明:
periph_set_handle
:外设集合句柄,通过esp_periph_set_init
获得time_ms
:新的等待超时时间,单位为毫秒
返回值:
- 成功:返回
ESP_OK
调用示例:
// 创建外设集合
esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();
esp_periph_set_handle_t set = esp_periph_set_init(&periph_cfg);
// 添加外设
esp_periph_handle_t button = periph_button_init(&button_cfg);
esp_periph_start(set, button);
// 调整命令等待超时时间为 100 毫秒
esp_periph_set_change_waiting_time(set, 100);
// 对于需要更快响应的场景,可以设置更短的等待时间
esp_periph_set_change_waiting_time(set, 10); // 10 毫秒
// 对于需要节省系统资源的场景,可以设置更长的等待时间
esp_periph_set_change_waiting_time(set, 500); // 500 毫秒
更改等待时间时序图:
这个时序图展示了esp_periph_set_change_waiting_time
函数的执行流程,包括如何获取事件接口并设置新的命令等待超时时间。
注意:调整等待时间是一种平衡响应速度和系统资源消耗的方法。较短的等待时间可以提高外设响应速度,但会增加 CPU 使用率;较长的等待时间可以降低 CPU 使用率,但可能会影响外设响应的实时性。