这是一篇学习笔记,跟踪按键驱动代码,仅供自己查阅。
以例子《esp-adf\examples\player\pipeline_play_sdcard_music》的源码来分析。

1. 《play_sdcard_music_example.c》主函数app_main分析

下面直接贴出主函数中和按键相关的代码。

void app_main(void)
{......ESP_LOGI(TAG, "[1.0] Initialize peripherals management");esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();esp_periph_set_handle_t set = esp_periph_set_init(&periph_cfg);//------(1)ESP_LOGI(TAG, "[1.1] Initialize and start peripherals");audio_board_key_init(set);              //------(2)audio_board_sdcard_init(set, SD_MODE_1_LINE);
......ESP_LOGI(TAG, "[ 3 ] Create and start input key service");input_key_service_info_t input_key_info[] = INPUT_KEY_DEFAULT_INFO();//------(3)input_key_service_cfg_t input_cfg = INPUT_KEY_SERVICE_DEFAULT_CONFIG();//------(4)input_cfg.handle = set;      //------(5)periph_service_handle_t input_ser = input_key_service_create(&input_cfg);//------(6)input_key_service_add_key(input_ser, input_key_info, INPUT_KEY_NUM);//------(7)periph_service_set_callback(input_ser, input_key_service_cb,(void *)board_handle);//------(8)
......
}

这里对每一行代码进行分析,跟踪。

1.1 esp_periph_set_handle_t set = esp_periph_set_init(&periph_cfg);//------(1)

这个代码没有理解。函数的实现在《esp-adf\components\esp_peripherals\esp_peripherals.c》:

esp_periph_set_handle_t esp_periph_set_init(esp_periph_config_t *config)
{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);//TODO: Should we uninstall gpio isr service??//TODO: Because gpio need for sdcard and gpio, then install isr heregpio_install_isr_service(ESP_INTR_FLAG_LEVEL1);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;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);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;
}

1.2 audio_board_key_init(set); //------(2)

根据自己的开发板选择对应的按键IO口,我用“ESP32_A1S_Audio_Kit_v2_2”的文件替换掉“lyrat_v4_3”的文件。这样在menuconfig 配置时,直接选择 Audio HAL == lyrat_v4_3。
看看本函数的实现代码:《D:\study\esp-adf\components\audio_board\lyrat_v4_3\board.c》

esp_err_t audio_board_key_init(esp_periph_set_handle_t set)
{periph_button_cfg_t btn_cfg = {.gpio_mask =  ESP32_A1S_AUDIO_KEY1 | ESP32_A1S_AUDIO_KEY2 |ESP32_A1S_AUDIO_KEY3 |ESP32_A1S_AUDIO_KEY4 |ESP32_A1S_AUDIO_KEY5 |ESP32_A1S_AUDIO_KEY6 , //REC BTN & MODE BTN};esp_periph_handle_t button_handle = periph_button_init(&btn_cfg);AUDIO_NULL_CHECK(TAG, button_handle, return ESP_ERR_ADF_MEMORY_LACK);esp_err_t ret = ESP_OK;ret = esp_periph_start(set, button_handle);if (ret != ESP_OK) {return ret;}return ret;
}

1.3 input_key_service_info_t input_key_info[] =INPUT_KEY_DEFAULT_INFO()//------(3)

结合安可信的 ESP32-AUDIO-kit 底板按键部分原理图,可以更加清晰的理解。

通过电阻的选择,来决定使用电平值按键还是模拟值按键:
电平值按键:R55-R64 使用合适的电阻,R66-R70留空,需要6个IO口。
模拟值按键:R55-R64 留空,R66-R70 使用0R电阻,只需要1个IO口。
这个数据类型是一个结构体:

typedef struct {esp_periph_id_t  type;  /*!< ID of peripherals,--总线类型,和按键相关的总线有3种:电平总线和模拟输入总线,触摸按键总线 */int              user_id; /*!< The key's user id -- 用户自定义功能ID */int              act_id;  /*!< The key's action id -- 对应IO口 GPIO_NUM_x */
} input_key_service_info_t;
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,PERIPH_ID_LCD        = AUDIO_ELEMENT_TYPE_PERIPH + 17
} esp_periph_id_t;

给结构体数组input_key_info[]赋予初始值 INPUT_KEY_DEFAULT_INFO()
这是一个宏定义,具体如下:

......   //这里全部使用电平值按键
#define BUTTON_REC_ID             GPIO_NUM_36   //KEY1
#define BUTTON_MODE_ID            GPIO_NUM_19   //KEY3
#define BUTTON_SET_ID             GPIO_NUM_5   //KEY2 -- old==GPIO_NUM_13
#define BUTTON_PLAY_ID            GPIO_NUM_23   //KEY4
#define BUTTON_VOLUP_ID           GPIO_NUM_18   //KEY5
#define BUTTON_VOLDOWN_ID         GPIO_NUM_36    //KEY6 -- old==GPIO_NUM_5
......
#define INPUT_KEY_DEFAULT_INFO() {                      \{                                                  \.type = PERIPH_ID_BUTTON,                       \.user_id = INPUT_KEY_USER_ID_REC,               \.act_id = BUTTON_REC_ID,                        \},                                                  \{                                                   \.type = PERIPH_ID_BUTTON,                       \.user_id = INPUT_KEY_USER_ID_MODE,              \.act_id = BUTTON_MODE_ID,                       \},                                                  \{                                                   \.type = PERIPH_ID_BUTTON,                        \.user_id = INPUT_KEY_USER_ID_SET,               \.act_id = BUTTON_SET_ID,                        \},                                                  \{                                                   \.type = PERIPH_ID_BUTTON,                        \.user_id = INPUT_KEY_USER_ID_PLAY,              \.act_id = BUTTON_PLAY_ID,                       \},                                                  \{                                                   \.type = PERIPH_ID_BUTTON,                        \.user_id = INPUT_KEY_USER_ID_VOLUP,             \.act_id = BUTTON_VOLUP_ID,                      \},                                                  \{                                                   \.type = PERIPH_ID_BUTTON,                        \.user_id = INPUT_KEY_USER_ID_VOLDOWN,           \.act_id = BUTTON_VOLDOWN_ID,                    \}                                                   \
}

1.4 input_key_service_cfg_t input_cfg = INPUT_KEY_SERVICE_DEFAULT_CONFIG();//------(4)

input_cfg.handle = set; //------(5)
(4)(5)行共同对input_cfg 进行初始化。
set这个句柄我看不懂。

这个是按键服务配置结构体,看看里面包含了哪些内容:

// <esp-adf\components\esp_peripherals\esp_peripherals.c>
typedef struct esp_periph_sets {EventGroupHandle_t                              state_event_bits;xSemaphoreHandle                                lock;int                                             task_stack;int                                             task_prio;int                                             task_core;audio_thread_t                                  audio_thread;bool                                            ext_stack;bool                                            run;esp_periph_event_t                              event_handle;STAILQ_HEAD(esp_periph_list_item, esp_periph)   periph_list;
} esp_periph_set_t;
// <esp-adf\components\esp_peripherals\include\esp_peripherals.h>
typedef struct esp_periph_sets *esp_periph_set_handle_t;
//<esp-adf\components\input_key_service\include\input_key_service.h>
typedef struct {periph_service_config_t based_cfg; /*!< Peripheral service configuration  */esp_periph_set_handle_t handle;    /*!< Peripheral set handle */
} input_key_service_cfg_t;
#define INPUT_KEY_SERVICE_DEFAULT_CONFIG() {             \.based_cfg = {                                       \.task_stack = INPUT_KEY_SERVICE_TASK_STACK_SIZE, \.task_prio = INPUT_KEY_SERVICE_TASK_PRIORITY,    \.task_core = INPUT_KEY_SERVICE_TASK_ON_CORE,     \.extern_stack = false                            \}                                                    \
}

1.5 periph_service_handle_t input_ser = input_key_service_create(&input_cfg);//------(6)

创建按键服务句柄,函数实现在《esp-adf\components\input_key_service\input_key_service.c》。

periph_service_handle_t input_key_service_create(input_key_service_cfg_t *input_key_config)
{AUDIO_NULL_CHECK(TAG, input_key_config, return NULL);periph_service_config_t *input_cfg = &input_key_config->based_cfg;periph_service_config_t service_cfg = {.task_stack = input_cfg->task_stack,.task_prio  = input_cfg->task_prio,.task_core  = input_cfg->task_core,.extern_stack = input_cfg->extern_stack,.task_func  = input_key_service_task,.service_start = input_key_service_start,.service_stop = input_key_service_stop,.service_destroy = input_key_service_destroy,.service_ioctl = NULL,.service_name = "input_key_service",};input_key_service_t *input_key_ser = NULL;periph_service_handle_t input_key_handle = NULL;input_key_ser = (input_key_service_t *)audio_calloc(1, sizeof(input_key_service_t));AUDIO_NULL_CHECK(TAG, input_key_ser, goto _create_service_failed);if (input_key_config->handle) {input_key_ser->periph_set_handle = input_key_config->handle;} else {ESP_LOGE(TAG, "peripherals set handle is NULL");free(input_key_ser);return NULL;}input_key_ser->ser_state = PERIPH_SERVICE_STATE_UNKNOWN;STAILQ_INIT(&input_key_ser->input_info_list);service_cfg.user_data = (void *)input_key_ser;input_key_handle = periph_service_create(&service_cfg);AUDIO_NULL_CHECK(TAG, input_key_handle, goto _create_service_failed);return input_key_handle;_create_service_failed:if (input_key_handle) {audio_free(input_key_handle);input_key_handle = NULL;}if (input_key_ser) {audio_free(input_key_ser);input_key_ser = NULL;}return NULL;
}

1.6 input_key_service_add_key(input_ser, input_key_info, INPUT_KEY_NUM);//------(7)

把包含6个按键信息的数组input_key_info添加到按键服务函数中。
《esp-adf\components\input_key_service\input_key_service.c》

esp_err_t input_key_service_add_key(periph_service_handle_t input_key_handle, input_key_service_info_t *input_key_info, int add_key_num)
{AUDIO_NULL_CHECK(TAG, input_key_handle, return ESP_ERR_INVALID_ARG);AUDIO_NULL_CHECK(TAG, input_key_info, return ESP_ERR_INVALID_ARG);if (add_key_num <= 0) {return ESP_FAIL;}input_key_service_t *input_key_ser = periph_service_get_data(input_key_handle);AUDIO_NULL_CHECK(TAG, input_key_ser, return ESP_FAIL);for (int i = 0; i < add_key_num; i++) {input_key_node_t *input_key_node = (input_key_node_t *)audio_calloc(1, sizeof(input_key_node_t));AUDIO_NULL_CHECK(TAG, input_key_node, return ESP_FAIL);memcpy(&input_key_node->input_key_info, &input_key_info[i], sizeof(input_key_service_info_t));STAILQ_INSERT_TAIL(&input_key_ser->input_info_list, input_key_node, entries);}return ESP_OK;
}

ESP32音频框架 ESP-ADF 添加按键外设流程代码跟踪相关推荐

  1. 乐鑫Esp32学习之旅11 入门 乐鑫esp-adf 音频框架开发,造一个蓝牙耳机,实现切换歌曲,获取歌曲信息等功能。(附带Demo)

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1. 爬坑学习新旅程,虚拟机搭建esp32开发环境,打印 " ...

  2. 乐鑫Esp32学习之旅 23 安信可 esp32-a1s 音频开发板移植最新 esp-adf 音频框架,小试牛刀如何实现在线文字转语音播放。

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1. 爬坑学习新旅程,虚拟机搭建esp32开发环境,打印 " ...

  3. Android 抛弃原生MediaPlayer 使用音频框架 StarrySky

    前言 最近用原生MediaPlayer 各种无法解决的问题 于是找第三方优秀框架 推荐 音频框架 StarrySky 亲测效果极佳 是满意的效果! StarrySky音频框架 项目依赖 需要在工程的b ...

  4. Arduino ESP32 WIFI 蓝牙模式触控按键切换

    Arduino ESP32 WIFI &蓝牙模式触控按键切换 相关篇<Arduino ESP32自带触摸传感器功能测试> <ESP32电容式触摸传感器引脚实例> ESP ...

  5. android定制化软件修改或添加按键驱动的核心操作步骤讲解

    最近在Amlogic方案的定制化android软件上,做了添加按键的驱动工作,也熟悉了按键的基本流程,现在把核心步骤给总结如下: 1.基本流程: ./表示android源代码目录,按键属于输入设备,支 ...

  6. esp32录音功能开发_使用ESP32音频采样

    本文概述 ESP32是下一代的, 具有WiFi和蓝牙功能的微控制器.它是总部位于上海的Espressif的继任者, ESP8266微控制器是非常受欢迎的产品, 并且对于爱好者来说是革命性的产品. ES ...

  7. Android音频框架之一 详解audioPolicy流程及HAL驱动加载与配置

    前言 此音频架构梳理笔记.主要是因工作上需要在 Android8.1 以上版本中,增加 snd-aloop 虚拟声卡做前期准备工作, 本篇文章提纲挈领的把音频框架主线梳理清晰,通过这篇文章能够清晰如下 ...

  8. Android下添加新的自定义键值和按键处理流程【转】

    本文转载自: Android下添加新的自定义键值和按键处理流程 说出来不怕大家笑话,我写这篇博客的原因在于前几天去一个小公司面试Android系统工程师,然后在面试的时候对方的技术总监问了我一个问题, ...

  9. 网易云信实时音频框架背后:算法优化带来产品体验全面提升

    2018年10月19日,LiveVideoStackCon音视频技术大会在北京召开.本届会议以"技术开启新'视'界"为主题,汇集资深的音视频技术工程师,探讨在音频.视频.图像等技术 ...

  10. Android音频框架笔记 - 下篇

    原址 六.HAL层 6-1.Audio HAL层,其实包括了audio.xxx.so 和 audiopolicy.so等.从前述的总框架图,也有写,代码库路径也有写. 具体运行时so对象图,对于aud ...

最新文章

  1. 图森未来完成2.15亿美元D轮融资,将拓展无人驾驶运输服务
  2. 强烈推荐一款完全免费的绿色JRE+Tomcat+MySQL集成开发工具 - JTM
  3. es6 匿名函数求阶乘
  4. love2d杂记9--光照效果
  5. 使用canvas绘制楼梯(canvas直线绘制练习)
  6. 在MySQL上使用带密码的GlassFish JDBC安全性
  7. dbutils java_Dbutils工具类的使用
  8. PostgreSQL 9.6 IO Hang问题浅析与优化
  9. 只需三种手段,将传统的网站的性能提高 24%!
  10. 搭建james邮件服务器
  11. 大学计算机应用基础模拟试题,《大学计算机应用基础》模拟试题.doc
  12. 定时开关机cmd命令
  13. java项目目录_Java项目目录解释
  14. 有序表归并算法(数据结构学习笔记)
  15. Chrome的最小字体12px限制最终解决办法
  16. 对图标的坐标轴进行调整
  17. matlab磁铁模拟,用matlab 模拟环形磁铁的磁场分布
  18. golang mongodb 聚合(Aggregate) github.com/qiniu/qmgo框架
  19. colorkey口红怎么样_colorkey小众品牌口红唇釉效果好吗 – 爱分享
  20. GAT 算法原理介绍与源码分析

热门文章

  1. 山大软件项目管理复习整理
  2. pynq z1+ov5640
  3. vp9 prob 详细分析
  4. Spring技术发展及框架设计
  5. 注册表:基本概念和reg文件
  6. 去哪儿网前端架构师司徒正美:如何挑选适合的前端框架?
  7. 电磁屏蔽技术的三种主要方法
  8. ps考证分数是用电脑改的吗
  9. sublime text3格式化代码快捷键
  10. matlab测绘 求坐标系,MATLAB在测绘80与2000坐标系转换中的应用