// 按键驱动模块 // BOOT(GPIO0):由board类的iot_button处理(单击/双击/长按3秒模式切换) // key_nav的1200ms长按通过iot_button_register_event_cb自定义阈值注册 // KEY2(GPIO4):由本模块的iot_button处理(单击/双击/长按1200ms) #include "dzbj_button.h" #include "key_nav.h" #include "device_mode.h" #include "iot_button.h" #include "driver/gpio.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" static const char *TAG = "DZBJ_BTN"; // KEY2 按键句柄 static button_handle_t key2_handle = NULL; // === KEY2 回调(esp_timer中执行,派发到独立任务) === static void key2_click_task(void *arg) { key_nav_key2_click(); vTaskDelete(NULL); } static void key2_double_click_task(void *arg) { key_nav_key2_double_click(); vTaskDelete(NULL); } static void key2_long_press_task(void *arg) { key_nav_key2_long_press(); vTaskDelete(NULL); } static void key2_click_cb(void *handle, void *data) { xTaskCreate(key2_click_task, "nav_kc", 3072, NULL, 5, NULL); } static void key2_double_click_cb(void *handle, void *data) { xTaskCreate(key2_double_click_task, "nav_kd", 3072, NULL, 5, NULL); } static void key2_long_press_cb(void *handle, void *data) { xTaskCreate(key2_long_press_task, "nav_kl", 3072, NULL, 5, NULL); } esp_err_t dzbj_button_init(void) { // KEY2 按键配置(iot_button_create 旧版API) button_config_t key2_cfg = { .type = BUTTON_TYPE_GPIO, .long_press_time = 1200, // 长按阈值1.2秒 .short_press_time = 300, // 双击检测窗口300ms .gpio_button_config = { .gpio_num = PIN_BTN_KEY2, .active_level = 0, // 低电平有效 }, }; key2_handle = iot_button_create(&key2_cfg); if (!key2_handle) { ESP_LOGE(TAG, "KEY2按键创建失败"); return ESP_FAIL; } // 注册KEY2事件回调(4参数版本) iot_button_register_cb(key2_handle, BUTTON_SINGLE_CLICK, key2_click_cb, NULL); iot_button_register_cb(key2_handle, BUTTON_DOUBLE_CLICK, key2_double_click_cb, NULL); iot_button_register_cb(key2_handle, BUTTON_LONG_PRESS_START, key2_long_press_cb, NULL); ESP_LOGI(TAG, "按键初始化完成 (KEY2=GPIO%d, 长按1200ms, 双击300ms)", PIN_BTN_KEY2); return ESP_OK; } // === BOOT 1200ms 长按注册(由board类调用,传入boot_button的iot_button句柄) === static void boot_long_press_1200_task(void *arg) { key_nav_boot_long_press(); vTaskDelete(NULL); } static void boot_long_press_1200_cb(void *handle, void *data) { xTaskCreate(boot_long_press_1200_task, "nav_bl", 3072, NULL, 5, NULL); } void dzbj_button_register_boot_long_press(void *boot_handle) { if (!boot_handle) return; // 注册1200ms自定义长按事件(不影响board类的3000ms模式切换) button_event_config_t evt_cfg = { .event = BUTTON_LONG_PRESS_START, .event_data = { .long_press = { .press_time = 1200, }, }, }; esp_err_t ret = iot_button_register_event_cb((button_handle_t)boot_handle, evt_cfg, boot_long_press_1200_cb, NULL); if (ret == ESP_OK) { ESP_LOGI(TAG, "BOOT 1200ms长按事件注册成功"); } else { ESP_LOGE(TAG, "BOOT 1200ms长按事件注册失败: %s", esp_err_to_name(ret)); } } // === BOOT+KEY2 组合键模式切换(BOOT 2000ms长按时检测KEY2) === // === BOOT+KEY2 组合键模式切换(BOOT 2000ms长按时检测KEY2) === static void mode_switch_task(void *arg) { ESP_LOGI(TAG, "执行模式切换..."); if (device_mode_is_badge()) { ESP_LOGI(TAG, "吧唧模式 → AI模式"); device_mode_set(DEVICE_MODE_AI); } else { ESP_LOGI(TAG, "AI模式 → 吧唧模式"); device_mode_set(DEVICE_MODE_BADGE); } // device_mode_set 内部会 esp_restart,不会执行到这里 vTaskDelete(NULL); } static void mode_switch_combo_cb(void *handle, void *data) { // esp_timer中执行,检测KEY2是否同时按下 if (gpio_get_level(PIN_BTN_KEY2) == 0) { ESP_LOGI(TAG, "BOOT+KEY2组合键2秒:触发模式切换"); xTaskCreate(mode_switch_task, "mode_sw", 2048, NULL, 5, NULL); } } void dzbj_button_register_mode_switch_combo(void *boot_handle) { if (!boot_handle) return; // 注册2000ms自定义长按事件用于组合键检测 button_event_config_t evt_cfg = { .event = BUTTON_LONG_PRESS_START, .event_data = { .long_press = { .press_time = 2000, }, }, }; esp_err_t ret = iot_button_register_event_cb((button_handle_t)boot_handle, evt_cfg, mode_switch_combo_cb, NULL); if (ret == ESP_OK) { ESP_LOGI(TAG, "BOOT+KEY2组合键模式切换注册成功(2000ms)"); } else { ESP_LOGE(TAG, "组合键注册失败: %s", esp_err_to_name(ret)); } } // 吧唧模式 BOOT 单击处理(转发到key_nav统一处理) void dzbj_boot_click_handler(void) { key_nav_boot_click(); }