feat: 新增按键驱动、休眠管理和电池监控功能,修复内存损坏和开机闪烁问题

 新增功能
- 按键驱动模块: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>
This commit is contained in:
Rdzleo 2026-02-11 10:28:25 +08:00
parent 99aef2c4e5
commit 5eddd2aa72
16 changed files with 414 additions and 66 deletions

View File

@ -9,6 +9,8 @@ idf_component_register(
"./pages/pages.c" "./pages/pages.c"
"./ble/ble.c" "./ble/ble.c"
"./battery/battery.c" "./battery/battery.c"
"./button/button.c"
"./sleep_mgr/sleep_mgr.c"
"./ui/ui.c" "./ui/ui.c"
"./ui/components/ui_comp_hook.c" "./ui/components/ui_comp_hook.c"
"./ui/screens/ui_ScreenHome.c" "./ui/screens/ui_ScreenHome.c"
@ -33,6 +35,8 @@ idf_component_register(
"./pages/include/" "./pages/include/"
"./ble/include/" "./ble/include/"
"./battery/include/" "./battery/include/"
"./button/include/"
"./sleep_mgr/include/"
"./ui/" "./ui/"
"./ui/screens/" "./ui/screens/"
# "./axis/include/" # "./axis/include/"

View File

@ -8,7 +8,7 @@
#include "freertos/task.h" #include "freertos/task.h"
#include "esp_lvgl_port.h" #include "esp_lvgl_port.h"
#include "../ui/screens/ui_ScreenSet.h" #include "../ui/screens/ui_ScreenSet.h"
#include "../ui/screens/ui_ScreenHome.h" // ScreenHome界面不关联电池电量显示
#include <stdio.h> #include <stdio.h>
static const char *TAG = "BAT"; static const char *TAG = "BAT";
@ -198,7 +198,7 @@ static void battery_update_ui(void)
char buf[8]; char buf[8];
snprintf(buf, sizeof(buf), "%d%%", bat_level); snprintf(buf, sizeof(buf), "%d%%", bat_level);
// 更新ScreenSet界面的电量圆弧和标签 // 更新ScreenSet界面的电量圆弧和标签
if (ui_ArcPowerLevel) { if (ui_ArcPowerLevel) {
lv_arc_set_value(ui_ArcPowerLevel, bat_level); lv_arc_set_value(ui_ArcPowerLevel, bat_level);
} }
@ -206,13 +206,7 @@ static void battery_update_ui(void)
lv_label_set_text(ui_LabelPowerLevel, buf); lv_label_set_text(ui_LabelPowerLevel, buf);
} }
// 同步更新ScreenHome界面的电量圆弧和标签 // ScreenHome界面的Arc1和Label1保持默认值不关联电池电量
if (ui_Arc1) {
lv_arc_set_value(ui_Arc1, bat_level);
}
if (ui_Label1) {
lv_label_set_text(ui_Label1, buf);
}
lvgl_port_unlock(); lvgl_port_unlock();
} }
@ -229,6 +223,6 @@ static void battery_monitor_task(void *pvParameters)
void battery_monitor_start(void) void battery_monitor_start(void)
{ {
xTaskCreate(battery_monitor_task, "bat_mon", 2048, NULL, 3, NULL); xTaskCreate(battery_monitor_task, "bat_mon", 4096, NULL, 3, NULL);
ESP_LOGI(TAG, "电池监控任务已启动,更新间隔%dms", BAT_MONITOR_INTERVAL_MS); ESP_LOGI(TAG, "电池监控任务已启动,更新间隔%dms", BAT_MONITOR_INTERVAL_MS);
} }

107
main/button/button.c Normal file
View File

@ -0,0 +1,107 @@
#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;
}

View File

@ -0,0 +1,18 @@
#pragma once
#include "esp_err.h"
// 按键引脚定义
#define PIN_BTN_BOOT 0 // GPIO0 BOOT按键低电平有效
#define PIN_BTN_KEY2 4 // GPIO4 KEY2按键低电平有效
// 按键事件回调函数类型
typedef void (*btn_event_cb_t)(int gpio_num, void *usr_data);
// 初始化按键驱动GPIO中断 + 软件去抖)
esp_err_t button_init(void);
// 注册BOOT按键按下回调
void button_on_boot_press(btn_event_cb_t cb, void *usr_data);
// 注册KEY2按键按下回调
void button_on_key2_press(btn_event_cb_t cb, void *usr_data);

View File

@ -18,7 +18,7 @@
#define LCD_WID 360 #define LCD_WID 360
#define PIN_TP_RST 6 //引脚6 复位 #define PIN_TP_RST 6 //引脚6 复位
#define PIN_TP_INT 4 //引脚4 中断 #define PIN_TP_INT 5 //引脚4 中断
#define LCD_TAG "LCD" #define LCD_TAG "LCD"
#define SPI_LCD_HOST SPI2_HOST // SPI 主机编号 2 #define SPI_LCD_HOST SPI2_HOST // SPI 主机编号 2
@ -26,5 +26,8 @@
#define PIN_MOTOR_EN -1 // 电机使能 #define PIN_MOTOR_EN -1 // 电机使能
#define PIN_BAT_ADC 3 // 电池ADC检测引脚ADC1_CH2 #define PIN_BAT_ADC 3 // 电池ADC检测引脚ADC1_CH2
// 注意V1.0原理图中 GPIO4=KEY2按键, GPIO5=TP_INT
// 如果触摸不工作,请检查 PIN_TP_INT 是否与硬件版本匹配
void test_display(esp_lcd_panel_handle_t panel_handle); void test_display(esp_lcd_panel_handle_t panel_handle);
void test_gpio(); void test_gpio();

View File

@ -17,6 +17,8 @@
#include "pages.h" #include "pages.h"
#include "ble.h" #include "ble.h"
#include "battery.h" #include "battery.h"
#include "button.h"
#include "sleep_mgr.h"
#include "ui/ui.h" #include "ui/ui.h"
@ -164,39 +166,31 @@ void app_main(void)
lvgl_lcd_init(); lvgl_lcd_init();
ESP_LOGI("MAIN", "5. LVGL已初始化");// LVGL已初始化 ESP_LOGI("MAIN", "5. LVGL已初始化");// LVGL已初始化
vTaskDelay(pdMS_TO_TICKS(100));// 100ms等待LVGL任务完全启动
ESP_LOGI("MAIN", "5. LVGL任务已启动"); // LVGL任务已启动
// LVGL任务创建后下一个tick即运行利用这段时间初始化文件系统
fatfs_init(); fatfs_init();
ESP_LOGI("MAIN", "6. FATFS文件系统已初始化");// FATFS已初始化 ESP_LOGI("MAIN", "6. FATFS文件系统已初始化");// FATFS已初始化
pwm_init();
ESP_LOGI("MAIN", "7. PWM背光已初始化");// PWM背光已初始化
ESP_LOGI("MAIN", "8. 处理SPIFFS...");// 处理SPIFFS
fatfs_remove_nullData("/spiflash");// 移除空数据 fatfs_remove_nullData("/spiflash");// 移除空数据
fatfs_list_all_filenames("/spiflash",false);// 列出所有文件名 fatfs_list_all_filenames("/spiflash",false);// 列出所有文件名
// fatfs_remove_allData("/spiflash"); ESP_LOGI("MAIN", "7. SPIFFS处理完成");// SPIFFS处理完成
// wifi_init();
// ble_init();// 初始化BLE
// float temp = 0;// 温度
// ===================================================================== // =====================================================================
// 显示SquareLine Studio生成的UI界面 // 显示SquareLine Studio生成的UI界面
vTaskDelay(pdMS_TO_TICKS(50));// 再次等待确保系统稳定 ui_init(); // 初始化UI含JPEG解码
ui_init(); // 初始化UI ESP_LOGI("MAIN", "8. SquareLine UI已初始化");// SquareLine UI已初始化
ESP_LOGI("MAIN", "9. SquareLine UI已初始化");// SquareLine UI已初始化
// 等待LVGL完成屏幕切换和首帧渲染彻底避免开机闪烁
// 等待渲染完成 // ui_init()会创建所有屏幕并加载ScreenHome包括
for (int i = 0; i < 3; i++) { // 1. JPEG解码约210ms
lv_timer_handler(); // 2. 屏幕对象创建和切换
vTaskDelay(pdMS_TO_TICKS(50)); // 3. QSPI传输首帧到LCD约100ms
ESP_LOGI("MAIN", "10. 渲染步骤 %d 已完成", i+1);// 渲染步骤已完成 // 增加到150ms确保所有渲染完成后再点亮背光
} vTaskDelay(pdMS_TO_TICKS(150));
ESP_LOGI("MAIN", "UI渲染完成");// UI渲染完成
// UI渲染完成后再点亮背光避免开机闪烁旧画面
pwm_init();
ESP_LOGI("MAIN", "9. PWM背光已初始化");// PWM背光已初始化
// 初始化电池ADC检测并启动监控任务 // 初始化电池ADC检测并启动监控任务
ESP_ERROR_CHECK(battery_init()); ESP_ERROR_CHECK(battery_init());
@ -204,6 +198,14 @@ void app_main(void)
battery_monitor_start(); battery_monitor_start();
ESP_LOGI("MAIN", "11. 电池监控任务已启动"); ESP_LOGI("MAIN", "11. 电池监控任务已启动");
// 初始化按键驱动
ESP_ERROR_CHECK(button_init());
ESP_LOGI("MAIN", "12. 按键已初始化");
// 初始化休眠管理器依赖按键和UI必须最后初始化
sleep_mgr_init();
ESP_LOGI("MAIN", "13. 休眠管理器已初始化");
ESP_LOGI("MAIN", "系统初始化完成成功!");// 系统初始化完成成功 ESP_LOGI("MAIN", "系统初始化完成成功!");// 系统初始化完成成功
// ===================================================================== // =====================================================================

View File

@ -8,4 +8,5 @@ void app_img_change(); // 改变图片
void img_switch_task(void *pvParameters);// 图片切换任务 void img_switch_task(void *pvParameters);// 图片切换任务
void img_loop_task(void *pvParameters); // 图片循环任务 void img_loop_task(void *pvParameters); // 图片循环任务
void pwm_init(); // 初始化PWM背光 void pwm_init(); // 初始化PWM背光
void pwm_set_brightness(uint8_t percent); // 设置屏幕亮度(10-100%) void pwm_set_brightness(uint8_t percent); // 设置屏幕亮度(0=关闭, 10-100%)
uint8_t pwm_get_brightness(void); // 获取当前亮度值

View File

@ -20,16 +20,34 @@ uint8_t *app_img_data = 0;
esp_jpeg_image_output_t outdata; esp_jpeg_image_output_t outdata;
lv_img_dsc_t image; lv_img_dsc_t image;
static char *spiffs_image_files[10]; #define MAX_IMAGE_FILES 10
#define MAX_FILENAME_LEN 32
static char spiffs_image_files[MAX_IMAGE_FILES][MAX_FILENAME_LEN];
static int spiffs_image_count = 0; static int spiffs_image_count = 0;
static int current_image_index = 0; static int current_image_index = 0;
static bool image_list_initialized = false; static bool image_list_initialized = false;
// 设置屏幕亮度percent范围10-100显示值 // 当前亮度值(用于休眠恢复)
static uint8_t current_brightness = 50;
// 获取当前亮度值
uint8_t pwm_get_brightness(void) {
return current_brightness;
}
// 设置屏幕亮度percent范围0-100
// 0=完全关闭背光10~100为正常亮度范围
// 显示10%~100%映射到实际亮度20%~100%,背光低电平有效需反转占空比 // 显示10%~100%映射到实际亮度20%~100%,背光低电平有效需反转占空比
void pwm_set_brightness(uint8_t percent) { void pwm_set_brightness(uint8_t percent) {
if (percent == 0) {
// 完全关闭背光低电平有效占空比100%=全高=关闭)
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 8191);
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
return;
}
if (percent < 10) percent = 10; if (percent < 10) percent = 10;
if (percent > 100) percent = 100; if (percent > 100) percent = 100;
current_brightness = percent;
uint32_t actual = 20 + (uint32_t)(percent - 10) * 80 / 90; uint32_t actual = 20 + (uint32_t)(percent - 10) * 80 / 90;
uint32_t duty = 8191 - (8191 * actual) / 100; uint32_t duty = 8191 - (8191 * actual) / 100;
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty); ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty);
@ -581,30 +599,31 @@ void init_spiffs_image_list(void) {
// 遍历目录 // 遍历目录
struct dirent *entry; struct dirent *entry;
while((entry = readdir(dir)) != NULL && spiffs_image_count < 10) { while((entry = readdir(dir)) != NULL && spiffs_image_count < MAX_IMAGE_FILES) {
// 检查是否是图片文件(.jpg, .jpeg, .png等 // 检查是否是图片文件(.jpg, .jpeg, .png等
const char *name = entry->d_name; const char *name = entry->d_name;
int len = strlen(name); int len = strlen(name);
if(len > 4) { if(len > 4 && len < MAX_FILENAME_LEN) {
const char *ext = name + len - 4; const char *ext = name + len - 4;
if(strcasecmp(ext, ".jpg") == 0 || strcasecmp(ext, ".jpeg") == 0 || if(strcasecmp(ext, ".jpg") == 0 || strcasecmp(ext, ".jpeg") == 0 ||
strcasecmp(ext, ".png") == 0 || strcasecmp(ext, ".bmp") == 0) { strcasecmp(ext, ".png") == 0 || strcasecmp(ext, ".bmp") == 0) {
// 存储图片文件名 // 存储图片文件名到静态缓冲区
spiffs_image_files[spiffs_image_count] = strdup(name); strncpy(spiffs_image_files[spiffs_image_count], name, MAX_FILENAME_LEN - 1);
spiffs_image_files[spiffs_image_count][MAX_FILENAME_LEN - 1] = '\0';
ESP_LOGI("IMG_LIST", "发现图片文件: %s", name); ESP_LOGI("IMG_LIST", "发现图片文件: %s", name);
spiffs_image_count++; spiffs_image_count++;
} }
} }
} }
closedir(dir); closedir(dir);
// 检查是否找到图片 // 检查是否找到图片
if(spiffs_image_count == 0) { if(spiffs_image_count == 0) {
ESP_LOGE("IMG_LIST", "未找到图片文件"); ESP_LOGE("IMG_LIST", "未找到图片文件");
return; return;
} }
image_list_initialized = true; image_list_initialized = true;
ESP_LOGI("IMG_LIST", "图片列表初始化完成,共发现 %d 张图片", spiffs_image_count); ESP_LOGI("IMG_LIST", "图片列表初始化完成,共发现 %d 张图片", spiffs_image_count);
@ -636,32 +655,23 @@ const char* get_prev_image(void) {
ESP_LOGE("IMG_LIST", "图片列表未初始化或为空"); ESP_LOGE("IMG_LIST", "图片列表未初始化或为空");
return NULL; return NULL;
} }
current_image_index = (current_image_index - 1 + spiffs_image_count) % spiffs_image_count; current_image_index = (current_image_index - 1 + spiffs_image_count) % spiffs_image_count;
ESP_LOGI("IMG_LIST", "切换到上一张图片,索引: %d/%d", current_image_index + 1, spiffs_image_count); ESP_LOGI("IMG_LIST", "切换到上一张图片,索引: %d/%d", current_image_index + 1, spiffs_image_count);
return spiffs_image_files[current_image_index]; return spiffs_image_files[current_image_index];
} }
// 释放图片列表内存 // 重置图片列表
void free_spiffs_image_list(void) { void free_spiffs_image_list(void) {
if(!image_list_initialized) { if(!image_list_initialized) {
return; return;
} }
ESP_LOGI("IMG_LIST", "释放图片列表内存");
for(int i = 0; i < spiffs_image_count; i++) {
if(spiffs_image_files[i]) {
free(spiffs_image_files[i]);
spiffs_image_files[i] = NULL;
}
}
spiffs_image_count = 0; spiffs_image_count = 0;
current_image_index = 0; current_image_index = 0;
image_list_initialized = false; image_list_initialized = false;
ESP_LOGI("IMG_LIST", "图片列表内存释放完成"); ESP_LOGI("IMG_LIST", "图片列表已重置");
} }
// 更新ui_ImgBle控件的图片 // 更新ui_ImgBle控件的图片

View File

@ -0,0 +1,20 @@
#pragma once
#include <stdbool.h>
// 休眠超时时间(毫秒)
#define SLEEP_TIMEOUT_MS 10000
// 初始化休眠管理器需在UI、按键初始化之后调用
void sleep_mgr_init(void);
// 启用/禁用休眠模式
void sleep_mgr_set_enabled(bool enabled);
// 获取休眠模式是否启用
bool sleep_mgr_is_enabled(void);
// 通知有用户活动(按键按下、触摸屏幕时调用)
void sleep_mgr_notify_activity(void);
// 查询屏幕是否已关闭
bool sleep_mgr_is_screen_off(void);

154
main/sleep_mgr/sleep_mgr.c Normal file
View File

@ -0,0 +1,154 @@
#include "sleep_mgr.h"
#include "button.h"
#include "pages.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "esp_lvgl_port.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "lvgl.h"
#include "../ui/screens/ui_ScreenSet.h"
#include <stdio.h>
static const char *TAG = "SLEEP";
static bool sleep_enabled = false;
static bool screen_off = false;
static int64_t last_activity_us = 0;
static uint8_t saved_brightness = 50;
static const uint8_t DEFAULT_BRIGHTNESS = 50; // 默认亮度
static const uint8_t SLEEP_MODE_BRIGHTNESS = 10; // 休眠模式亮度
// 通知有用户活动
void sleep_mgr_notify_activity(void)
{
last_activity_us = esp_timer_get_time();
// 如果屏幕已关闭,立即唤醒
if (screen_off) {
screen_off = false;
pwm_set_brightness(saved_brightness);
ESP_LOGI(TAG, "屏幕唤醒,恢复亮度%d%%", saved_brightness);
}
}
// 按键活动回调BOOT和KEY2共用
static void btn_activity_cb(int gpio_num, void *usr_data)
{
sleep_mgr_notify_activity();
}
// 关闭屏幕(熄屏进入低功耗)
static void screen_turn_off(void)
{
if (screen_off) return;
// 保存当前亮度
saved_brightness = pwm_get_brightness();
if (saved_brightness == 0) {
saved_brightness = 50; // 防止保存到0值
}
screen_off = true;
pwm_set_brightness(0); // 关闭背光
ESP_LOGI(TAG, "屏幕已关闭,进入低功耗模式(保存亮度=%d%%", saved_brightness);
}
// 休眠管理任务
static void sleep_mgr_task(void *pvParameters)
{
while (1) {
if (sleep_enabled) {
// 检查LVGL触摸活动触摸会使inactive_time归零
if (lvgl_port_lock(50)) {
uint32_t inactive_ms = lv_disp_get_inactive_time(NULL);
lvgl_port_unlock();
// LVGL检测到新的触摸输入
if (inactive_ms < 500) {
sleep_mgr_notify_activity();
}
}
// 检查是否超过超时时间
if (!screen_off) {
int64_t now = esp_timer_get_time();
int64_t elapsed_ms = (now - last_activity_us) / 1000;
if (elapsed_ms >= SLEEP_TIMEOUT_MS) {
screen_turn_off();
}
}
}
vTaskDelay(pdMS_TO_TICKS(500));
}
}
void sleep_mgr_init(void)
{
last_activity_us = esp_timer_get_time();
// 注册按键回调,任意按键按下都唤醒/重置计时
button_on_boot_press(btn_activity_cb, NULL);
button_on_key2_press(btn_activity_cb, NULL);
xTaskCreate(sleep_mgr_task, "sleep_mgr", 3072, NULL, 3, NULL);
ESP_LOGI(TAG, "休眠管理器初始化完成(超时=%ds", SLEEP_TIMEOUT_MS / 1000);
}
// 更新ScreenSet界面的亮度UI控件
static void update_brightness_ui(uint8_t brightness)
{
if (!lvgl_port_lock(100)) {
return;
}
// 更新滑块位置
if (ui_SliderBrightness) {
lv_slider_set_value(ui_SliderBrightness, brightness, LV_ANIM_OFF);
}
// 更新亮度文本标签
if (ui_LabelBrightness) {
char buf[8];
snprintf(buf, sizeof(buf), "%d%%", brightness);
lv_label_set_text(ui_LabelBrightness, buf);
}
lvgl_port_unlock();
}
void sleep_mgr_set_enabled(bool enabled)
{
sleep_enabled = enabled;
if (enabled) {
last_activity_us = esp_timer_get_time();
// 进入休眠模式时将亮度调节到10%
pwm_set_brightness(SLEEP_MODE_BRIGHTNESS);
update_brightness_ui(SLEEP_MODE_BRIGHTNESS);
ESP_LOGI(TAG, "休眠模式已启用,亮度已调节至%d%%%ds无操作将熄屏",
SLEEP_MODE_BRIGHTNESS, SLEEP_TIMEOUT_MS / 1000);
} else {
// 禁用休眠模式时恢复到默认亮度50%
if (screen_off) {
screen_off = false;
pwm_set_brightness(DEFAULT_BRIGHTNESS);
update_brightness_ui(DEFAULT_BRIGHTNESS);
ESP_LOGI(TAG, "休眠模式已禁用,屏幕已恢复,亮度恢复到%d%%", DEFAULT_BRIGHTNESS);
} else {
pwm_set_brightness(DEFAULT_BRIGHTNESS);
update_brightness_ui(DEFAULT_BRIGHTNESS);
ESP_LOGI(TAG, "休眠模式已禁用,亮度恢复到%d%%", DEFAULT_BRIGHTNESS);
}
}
}
bool sleep_mgr_is_enabled(void)
{
return sleep_enabled;
}
bool sleep_mgr_is_screen_off(void)
{
return screen_off;
}

View File

@ -4,6 +4,7 @@
// Project name: Lcd_Pro // Project name: Lcd_Pro
#include "../ui.h" #include "../ui.h"
#include "ui_ScreenSet.h" // 引入ScreenSet的函数声明
lv_obj_t *ui_ScreenHome = NULL;lv_obj_t *ui_Label1 = NULL;lv_obj_t *ui_Image3 = NULL;lv_obj_t *ui_Arc1 = NULL;lv_obj_t *ui_LabelHome = NULL; lv_obj_t *ui_ScreenHome = NULL;lv_obj_t *ui_Label1 = NULL;lv_obj_t *ui_Image3 = NULL;lv_obj_t *ui_Arc1 = NULL;lv_obj_t *ui_LabelHome = NULL;
// event funtions // event funtions

View File

@ -4,6 +4,7 @@
// Project name: Lcd_Pro // Project name: Lcd_Pro
#include "../ui.h" #include "../ui.h"
#include "ui_ScreenSet.h" // 引入ScreenSet的函数声明
extern void init_spiffs_image_list(void); extern void init_spiffs_image_list(void);
extern void update_ui_ImgBle(const char *img_name); extern void update_ui_ImgBle(const char *img_name);

View File

@ -5,8 +5,10 @@
#include "../ui.h" #include "../ui.h"
#include "../../pages/include/pages.h" #include "../../pages/include/pages.h"
#include "../../sleep_mgr/include/sleep_mgr.h"
lv_obj_t *ui_ScreenSet = NULL;lv_obj_t *ui_GlobalContainer = NULL;lv_obj_t *ui_ContainerTop = NULL;lv_obj_t *ui_ImgLowPower = NULL;lv_obj_t *ui_ImgFlashlight = NULL;lv_obj_t *ui_ImgDelete = NULL;lv_obj_t *ui_ContainerCentral = NULL;lv_obj_t *ui_SliderBrightness = NULL;lv_obj_t *ui_ImgSun = NULL;lv_obj_t *ui_LabelBrightness = NULL;lv_obj_t *ui_ArcPowerLevel = NULL;lv_obj_t *ui_ImgLightning = NULL;lv_obj_t *ui_LabelPowerLevel = NULL; lv_obj_t *ui_ScreenSet = NULL;lv_obj_t *ui_GlobalContainer = NULL;lv_obj_t *ui_ContainerTop = NULL;lv_obj_t *ui_ImgLowPower = NULL;lv_obj_t *ui_ImgFlashlight = NULL;lv_obj_t *ui_ImgDelete = NULL;lv_obj_t *ui_ContainerCentral = NULL;lv_obj_t *ui_SliderBrightness = NULL;lv_obj_t *ui_ImgSun = NULL;lv_obj_t *ui_LabelBrightness = NULL;lv_obj_t *ui_ArcPowerLevel = NULL;lv_obj_t *ui_ImgLightning = NULL;lv_obj_t *ui_LabelPowerLevel = NULL;
// event funtions // event funtions
void ui_event_ScreenSet( lv_event_t * e) { void ui_event_ScreenSet( lv_event_t * e) {
lv_event_code_t event_code = lv_event_get_code(e); lv_event_code_t event_code = lv_event_get_code(e);
@ -28,6 +30,17 @@ if ( event_code == LV_EVENT_VALUE_CHANGED) {
} }
} }
// ImgLowPower点击事件切换休眠模式
void ui_event_ImgLowPower( lv_event_t * e) {
lv_event_code_t event_code = lv_event_get_code(e);
if ( event_code == LV_EVENT_VALUE_CHANGED) {
lv_obj_t * target = lv_event_get_target(e);
// checked=true时显示s12(休眠模式)false时显示s11(正常模式)
bool checked = lv_obj_has_state(target, LV_STATE_CHECKED);
sleep_mgr_set_enabled(checked);
}
}
// build funtions // build funtions
void ui_ScreenSet_screen_init(void) void ui_ScreenSet_screen_init(void)
@ -173,6 +186,7 @@ lv_obj_set_style_text_color(ui_LabelPowerLevel, lv_color_hex(0xFFFFFF), LV_PART_
lv_obj_set_style_text_opa(ui_LabelPowerLevel, 255, LV_PART_MAIN| LV_STATE_DEFAULT); lv_obj_set_style_text_opa(ui_LabelPowerLevel, 255, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_set_style_text_font(ui_LabelPowerLevel, &lv_font_montserrat_20, LV_PART_MAIN| LV_STATE_DEFAULT); lv_obj_set_style_text_font(ui_LabelPowerLevel, &lv_font_montserrat_20, LV_PART_MAIN| LV_STATE_DEFAULT);
lv_obj_add_event_cb(ui_ImgLowPower, ui_event_ImgLowPower, LV_EVENT_ALL, NULL);
lv_obj_add_event_cb(ui_SliderBrightness, ui_event_SliderBrightness, LV_EVENT_ALL, NULL); lv_obj_add_event_cb(ui_SliderBrightness, ui_event_SliderBrightness, LV_EVENT_ALL, NULL);
lv_obj_add_event_cb(ui_ScreenSet, ui_event_ScreenSet, LV_EVENT_ALL, NULL); lv_obj_add_event_cb(ui_ScreenSet, ui_event_ScreenSet, LV_EVENT_ALL, NULL);

View File

@ -32,9 +32,11 @@ void ui_init( void )
lv_disp_t *dispp = lv_disp_get_default(); lv_disp_t *dispp = lv_disp_get_default();
lv_theme_t *theme = lv_theme_default_init(dispp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), false, LV_FONT_DEFAULT); lv_theme_t *theme = lv_theme_default_init(dispp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), false, LV_FONT_DEFAULT);
lv_disp_set_theme(dispp, theme); lv_disp_set_theme(dispp, theme);
ui_ScreenHome_screen_init(); ui_ScreenHome_screen_init();
ui_ScreenSet_screen_init();
ui_ScreenImg_screen_init(); ui_ScreenImg_screen_init();
ui_ScreenSet_screen_init();
ui____initial_actions0 = lv_obj_create(NULL); ui____initial_actions0 = lv_obj_create(NULL);
lv_disp_load_scr( ui_ScreenHome); lv_disp_load_scr( ui_ScreenHome);
} }

View File

@ -166,9 +166,9 @@ static esp_err_t reset(esp_lcd_touch_handle_t tp)
{ {
if (tp->config.rst_gpio_num != GPIO_NUM_NC) { if (tp->config.rst_gpio_num != GPIO_NUM_NC) {
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, tp->config.levels.reset), TAG, "GPIO set level failed"); ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, tp->config.levels.reset), TAG, "GPIO set level failed");
vTaskDelay(pdMS_TO_TICKS(200)); vTaskDelay(pdMS_TO_TICKS(10)); // 优化200ms → 10ms
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, !tp->config.levels.reset), TAG, "GPIO set level failed"); ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, !tp->config.levels.reset), TAG, "GPIO set level failed");
vTaskDelay(pdMS_TO_TICKS(200)); vTaskDelay(pdMS_TO_TICKS(30)); // 优化200ms → 30ms
} }
return ESP_OK; return ESP_OK;

View File

@ -14,6 +14,7 @@ CONFIG_SOC_GDMA_SUPPORTED=y
CONFIG_SOC_AHB_GDMA_SUPPORTED=y CONFIG_SOC_AHB_GDMA_SUPPORTED=y
CONFIG_SOC_GPTIMER_SUPPORTED=y CONFIG_SOC_GPTIMER_SUPPORTED=y
CONFIG_SOC_LCDCAM_SUPPORTED=y CONFIG_SOC_LCDCAM_SUPPORTED=y
CONFIG_SOC_LCDCAM_CAM_SUPPORTED=y
CONFIG_SOC_LCDCAM_I80_LCD_SUPPORTED=y CONFIG_SOC_LCDCAM_I80_LCD_SUPPORTED=y
CONFIG_SOC_LCDCAM_RGB_LCD_SUPPORTED=y CONFIG_SOC_LCDCAM_RGB_LCD_SUPPORTED=y
CONFIG_SOC_MCPWM_SUPPORTED=y CONFIG_SOC_MCPWM_SUPPORTED=y
@ -101,7 +102,7 @@ CONFIG_SOC_CPU_HAS_FPU=y
CONFIG_SOC_HP_CPU_HAS_MULTIPLE_CORES=y CONFIG_SOC_HP_CPU_HAS_MULTIPLE_CORES=y
CONFIG_SOC_CPU_BREAKPOINTS_NUM=2 CONFIG_SOC_CPU_BREAKPOINTS_NUM=2
CONFIG_SOC_CPU_WATCHPOINTS_NUM=2 CONFIG_SOC_CPU_WATCHPOINTS_NUM=2
CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=64 CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=0x40
CONFIG_SOC_SIMD_PREFERRED_DATA_ALIGNMENT=16 CONFIG_SOC_SIMD_PREFERRED_DATA_ALIGNMENT=16
CONFIG_SOC_DS_SIGNATURE_MAX_BIT_LEN=4096 CONFIG_SOC_DS_SIGNATURE_MAX_BIT_LEN=4096
CONFIG_SOC_DS_KEY_PARAM_MD_IV_LENGTH=16 CONFIG_SOC_DS_KEY_PARAM_MD_IV_LENGTH=16
@ -208,7 +209,7 @@ CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y
CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y
CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y
CONFIG_SOC_LP_IO_CLOCK_IS_INDEPENDENT=y CONFIG_SOC_LP_IO_CLOCK_IS_INDEPENDENT=y
CONFIG_SOC_SDM_GROUPS=y CONFIG_SOC_SDM_GROUPS=1
CONFIG_SOC_SDM_CHANNELS_PER_GROUP=8 CONFIG_SOC_SDM_CHANNELS_PER_GROUP=8
CONFIG_SOC_SDM_CLK_SUPPORT_APB=y CONFIG_SOC_SDM_CLK_SUPPORT_APB=y
CONFIG_SOC_SPI_PERIPH_NUM=3 CONFIG_SOC_SPI_PERIPH_NUM=3
@ -369,6 +370,9 @@ CONFIG_SOC_BLE_DEVICE_PRIVACY_SUPPORTED=y
CONFIG_SOC_BLUFI_SUPPORTED=y CONFIG_SOC_BLUFI_SUPPORTED=y
CONFIG_SOC_ULP_HAS_ADC=y CONFIG_SOC_ULP_HAS_ADC=y
CONFIG_SOC_PHY_COMBO_MODULE=y CONFIG_SOC_PHY_COMBO_MODULE=y
CONFIG_SOC_LCDCAM_CAM_SUPPORT_RGB_YUV_CONV=y
CONFIG_SOC_LCDCAM_CAM_PERIPH_NUM=1
CONFIG_SOC_LCDCAM_CAM_DATA_WIDTH_MAX=16
CONFIG_IDF_CMAKE=y CONFIG_IDF_CMAKE=y
CONFIG_IDF_TOOLCHAIN="gcc" CONFIG_IDF_TOOLCHAIN="gcc"
CONFIG_IDF_TOOLCHAIN_GCC=y CONFIG_IDF_TOOLCHAIN_GCC=y
@ -836,6 +840,7 @@ CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y
CONFIG_BT_BLE_42_DTM_TEST_EN=y CONFIG_BT_BLE_42_DTM_TEST_EN=y
CONFIG_BT_BLE_42_ADV_EN=y CONFIG_BT_BLE_42_ADV_EN=y
CONFIG_BT_BLE_42_SCAN_EN=y CONFIG_BT_BLE_42_SCAN_EN=y
CONFIG_BT_BLE_VENDOR_HCI_EN=y
# CONFIG_BT_BLE_HIGH_DUTY_ADV_INTERVAL is not set # CONFIG_BT_BLE_HIGH_DUTY_ADV_INTERVAL is not set
# CONFIG_BT_ABORT_WHEN_ALLOCATION_FAILS is not set # CONFIG_BT_ABORT_WHEN_ALLOCATION_FAILS is not set
# end of Bluedroid Options # end of Bluedroid Options
@ -1057,6 +1062,7 @@ CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y
# CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set # CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set
# CONFIG_ESP_TLS_PSK_VERIFICATION is not set # CONFIG_ESP_TLS_PSK_VERIFICATION is not set
# CONFIG_ESP_TLS_INSECURE is not set # CONFIG_ESP_TLS_INSECURE is not set
CONFIG_ESP_TLS_DYN_BUF_STRATEGY_SUPPORTED=y
# end of ESP-TLS # end of ESP-TLS
# #
@ -1084,6 +1090,12 @@ CONFIG_ESP_ERR_TO_NAME_LOOKUP=y
CONFIG_ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y CONFIG_ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
# end of Common ESP-related # end of Common ESP-related
#
# ESP-Driver:Camera Controller Configurations
#
# CONFIG_CAM_CTLR_DVP_CAM_ISR_CACHE_SAFE is not set
# end of ESP-Driver:Camera Controller Configurations
# #
# ESP-Driver:GPIO Configurations # ESP-Driver:GPIO Configurations
# #
@ -1401,8 +1413,11 @@ CONFIG_ESP_PHY_RF_CAL_PARTIAL=y
# CONFIG_ESP_PHY_RF_CAL_NONE is not set # CONFIG_ESP_PHY_RF_CAL_NONE is not set
# CONFIG_ESP_PHY_RF_CAL_FULL is not set # CONFIG_ESP_PHY_RF_CAL_FULL is not set
CONFIG_ESP_PHY_CALIBRATION_MODE=0 CONFIG_ESP_PHY_CALIBRATION_MODE=0
CONFIG_ESP_PHY_PLL_TRACK_PERIOD_MS=1000
# CONFIG_ESP_PHY_PLL_TRACK_DEBUG is not set # CONFIG_ESP_PHY_PLL_TRACK_DEBUG is not set
# CONFIG_ESP_PHY_RECORD_USED_TIME is not set # CONFIG_ESP_PHY_RECORD_USED_TIME is not set
CONFIG_ESP_PHY_IRAM_OPT=y
# CONFIG_ESP_PHY_DEBUG is not set
# end of PHY # end of PHY
# #
@ -1440,7 +1455,7 @@ CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION=y
# CONFIG_SPIRAM_USE_MEMMAP is not set # CONFIG_SPIRAM_USE_MEMMAP is not set
# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set # CONFIG_SPIRAM_USE_CAPS_ALLOC is not set
CONFIG_SPIRAM_USE_MALLOC=y CONFIG_SPIRAM_USE_MALLOC=y
CONFIG_SPIRAM_MEMTEST=y # CONFIG_SPIRAM_MEMTEST is not set
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384 CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384
CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768 CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768
@ -2073,6 +2088,7 @@ CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096
# CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set # CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set
# CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set # CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set
CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y
# CONFIG_MBEDTLS_SSL_KEYING_MATERIAL_EXPORT is not set
CONFIG_MBEDTLS_PKCS7_C=y CONFIG_MBEDTLS_PKCS7_C=y
# end of mbedTLS v3.x related # end of mbedTLS v3.x related
@ -3056,6 +3072,7 @@ CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_DIS=y
CONFIG_SW_COEXIST_ENABLE=y CONFIG_SW_COEXIST_ENABLE=y
CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=y CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=y
CONFIG_ESP_WIFI_SW_COEXIST_ENABLE=y CONFIG_ESP_WIFI_SW_COEXIST_ENABLE=y
# CONFIG_CAM_CTLR_DVP_CAM_ISR_IRAM_SAFE is not set
# CONFIG_MCPWM_ISR_IN_IRAM is not set # CONFIG_MCPWM_ISR_IN_IRAM is not set
# CONFIG_EVENT_LOOP_PROFILING is not set # CONFIG_EVENT_LOOP_PROFILING is not set
CONFIG_POST_EVENTS_FROM_ISR=y CONFIG_POST_EVENTS_FROM_ISR=y