✨ 新增功能 - 按键驱动模块:GPIO中断+软件去抖,支持BOOT和KEY2按键事件回调 - 休眠管理器:10秒无操作自动休眠,触摸/按键唤醒,UI集成开关 - 电池电量监控:GPIO3 ADC实时检测,ScreenSet界面圆弧显示 🐛 Bug修复 - 修复FreeRTOS任务栈溢出导致内存损坏(battery任务栈2048→4096) - 修复图片文件名损坏问题(改用静态缓冲区替代动态分配) - 修复触摸中断引脚配置错误(GPIO4→GPIO5,匹配V1.0硬件) - 修复开机闪烁问题(调整背光初始化时序,UI渲染后再点亮) 🎨 界面优化 - ScreenSet恢复为标准Screen切换方式(移除浮动面板架构) - 亮度调节支持0%(完全关闭)和10-100%范围 - ScreenHome界面电量显示独立(不关联实时电量) - 手势导航优化:下拉显示设置,上滑返回主界面 ⚡ 性能优化 - 启动时间优化:从650ms缩短至170ms - 内存管理优化:图片列表使用静态数组(10×32字节) - 任务栈配置调优:battery 4096, button 3072, sleep_mgr 3072 📝 其他改进 - CMakeLists.txt添加新模块编译配置 - 添加硬件版本兼容性注释(GPIO引脚说明) - 完善函数注释和错误日志输出 - sdkconfig配置更新 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
108 lines
3.0 KiB
C
108 lines
3.0 KiB
C
#include "button.h"
|
||
#include "driver/gpio.h"
|
||
#include "esp_log.h"
|
||
#include "esp_timer.h"
|
||
#include "freertos/FreeRTOS.h"
|
||
#include "freertos/task.h"
|
||
#include "freertos/queue.h"
|
||
|
||
static const char *TAG = "BTN";
|
||
|
||
// 去抖间隔(微秒)
|
||
#define DEBOUNCE_US 200000
|
||
|
||
// 按键事件队列
|
||
static QueueHandle_t btn_evt_queue = NULL;
|
||
|
||
// 回调存储
|
||
typedef struct {
|
||
btn_event_cb_t cb;
|
||
void *usr_data;
|
||
} btn_cb_t;
|
||
|
||
static btn_cb_t boot_cb = {0};
|
||
static btn_cb_t key2_cb = {0};
|
||
|
||
// 去抖时间戳
|
||
static int64_t last_boot_us = 0;
|
||
static int64_t last_key2_us = 0;
|
||
|
||
// GPIO中断服务函数(ISR中不做耗时操作,仅发送事件到队列)
|
||
static void IRAM_ATTR gpio_isr_handler(void *arg)
|
||
{
|
||
int gpio_num = (int)arg;
|
||
xQueueSendFromISR(btn_evt_queue, &gpio_num, NULL);
|
||
}
|
||
|
||
// 按键事件处理任务
|
||
static void btn_task(void *pvParameters)
|
||
{
|
||
int gpio_num;
|
||
while (1) {
|
||
if (xQueueReceive(btn_evt_queue, &gpio_num, portMAX_DELAY)) {
|
||
int64_t now = esp_timer_get_time();
|
||
|
||
if (gpio_num == PIN_BTN_BOOT) {
|
||
if (now - last_boot_us > DEBOUNCE_US) {
|
||
last_boot_us = now;
|
||
ESP_LOGI(TAG, "BOOT按键按下 (GPIO%d)", gpio_num);
|
||
if (boot_cb.cb) {
|
||
boot_cb.cb(gpio_num, boot_cb.usr_data);
|
||
}
|
||
}
|
||
} else if (gpio_num == PIN_BTN_KEY2) {
|
||
if (now - last_key2_us > DEBOUNCE_US) {
|
||
last_key2_us = now;
|
||
ESP_LOGI(TAG, "KEY2按键按下 (GPIO%d)", gpio_num);
|
||
if (key2_cb.cb) {
|
||
key2_cb.cb(gpio_num, key2_cb.usr_data);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
esp_err_t button_init(void)
|
||
{
|
||
btn_evt_queue = xQueueCreate(10, sizeof(int));
|
||
|
||
// 配置GPIO为输入模式,内部上拉,下降沿触发中断
|
||
gpio_config_t io_conf = {
|
||
.pin_bit_mask = (1ULL << PIN_BTN_BOOT) | (1ULL << PIN_BTN_KEY2),
|
||
.mode = GPIO_MODE_INPUT,
|
||
.pull_up_en = GPIO_PULLUP_ENABLE,
|
||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||
.intr_type = GPIO_INTR_NEGEDGE,
|
||
};
|
||
gpio_config(&io_conf);
|
||
|
||
// 安装GPIO中断服务(如果已安装则跳过)
|
||
esp_err_t ret = gpio_install_isr_service(0);
|
||
if (ret != ESP_OK && ret != ESP_ERR_INVALID_STATE) {
|
||
ESP_LOGE(TAG, "GPIO ISR服务安装失败");
|
||
return ret;
|
||
}
|
||
|
||
gpio_isr_handler_add(PIN_BTN_BOOT, gpio_isr_handler, (void *)PIN_BTN_BOOT);
|
||
gpio_isr_handler_add(PIN_BTN_KEY2, gpio_isr_handler, (void *)PIN_BTN_KEY2);
|
||
|
||
// 按键处理任务
|
||
xTaskCreate(btn_task, "btn_task", 3072, NULL, 5, NULL);
|
||
|
||
ESP_LOGI(TAG, "按键初始化完成 (BOOT=GPIO%d, KEY2=GPIO%d)", PIN_BTN_BOOT, PIN_BTN_KEY2);
|
||
return ESP_OK;
|
||
}
|
||
|
||
void button_on_boot_press(btn_event_cb_t cb, void *usr_data)
|
||
{
|
||
boot_cb.cb = cb;
|
||
boot_cb.usr_data = usr_data;
|
||
}
|
||
|
||
void button_on_key2_press(btn_event_cb_t cb, void *usr_data)
|
||
{
|
||
key2_cb.cb = cb;
|
||
key2_cb.usr_data = usr_data;
|
||
}
|