From c36c2bfa08ccac6aa374346d467ec82cf797abd7 Mon Sep 17 00:00:00 2001 From: Rdzleo Date: Thu, 12 Feb 2026 10:08:40 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E8=A7=A3=E5=86=B3=E4=BA=86=E4=BD=8E?= =?UTF-8?q?=E5=8A=9F=E8=80=97=E6=97=B6=E5=B1=8F=E5=B9=95=E6=AE=8B=E5=BD=B1?= =?UTF-8?q?=EF=BC=88=E5=9C=A8=E5=85=B3=E9=97=AD=E8=83=8C=E5=85=89=E5=89=8D?= =?UTF-8?q?=EF=BC=8C=E5=85=88=E5=B0=86LCD=20GRAM=E6=B8=85=E7=A9=BA?= =?UTF-8?q?=E4=B8=BA=E9=BB=91=E8=89=B2=EF=BC=89=EF=BC=9B=202=E3=80=81?= =?UTF-8?q?=E6=89=8B=E7=94=B5=E7=AD=92=E5=88=87=E6=8D=A2=E5=88=B0Home?= =?UTF-8?q?=E7=95=8C=E9=9D=A2=E7=9E=AC=E9=97=B4=E9=97=AA=E7=83=81=E9=97=AE?= =?UTF-8?q?=E9=A2=98=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/lcd/include/lcd.h | 3 ++- main/lcd/lcd.c | 25 ++++++++++++++++++ main/main.c | 23 ++++++++++++++--- main/sleep_mgr/sleep_mgr.c | 13 +++++++++- main/ui/screens/ui_ScreenSet.c | 47 +++++++++++++++++++++++++--------- main/ui/screens/ui_ScreenSet.h | 3 ++- sdkconfig | 21 +++++++++++++-- 7 files changed, 115 insertions(+), 20 deletions(-) diff --git a/main/lcd/include/lcd.h b/main/lcd/include/lcd.h index 38fa60c..3d3176b 100644 --- a/main/lcd/include/lcd.h +++ b/main/lcd/include/lcd.h @@ -5,4 +5,5 @@ void lcd_init(); void lvgl_lcd_init(); void touch_init(); -void get_touch(uint16_t* touchx,uint16_t* touchy); \ No newline at end of file +void get_touch(uint16_t* touchx,uint16_t* touchy); +void lcd_clear_screen_black(void); // 清空LCD GRAM为黑色 \ No newline at end of file diff --git a/main/lcd/lcd.c b/main/lcd/lcd.c index e5dcd4e..d001227 100644 --- a/main/lcd/lcd.c +++ b/main/lcd/lcd.c @@ -157,4 +157,29 @@ void get_touch(uint16_t* touchx,uint16_t* touchy){ *touchx = touch_handle->data.coords[0].x; *touchy = touch_handle->data.coords[0].y; printf("%x\n",max); +} + +// 清空LCD GRAM为黑色(用于低功耗熄屏前,避免残影) +void lcd_clear_screen_black(void) { + if (panel_handle == NULL) { + ESP_LOGE(LCD_TAG, "Panel handle is NULL, cannot clear screen"); + return; + } + + size_t clear_buffer_size = LCD_WID * 40; // 每次清除40行 + uint16_t *clear_buffer = heap_caps_malloc(clear_buffer_size * sizeof(uint16_t), MALLOC_CAP_DMA); + if (clear_buffer) { + memset(clear_buffer, 0, clear_buffer_size * sizeof(uint16_t)); // 填充黑色(0x0000) + + // 分批填充整个屏幕 + for (int y = 0; y < LCD_HIGH; y += 40) { + int lines = (y + 40 > LCD_HIGH) ? (LCD_HIGH - y) : 40; + esp_lcd_panel_draw_bitmap(panel_handle, 0, y, LCD_WID, y + lines, clear_buffer); + } + + heap_caps_free(clear_buffer); + ESP_LOGI(LCD_TAG, "LCD GRAM cleared to black (for low power mode)"); + } else { + ESP_LOGE(LCD_TAG, "Failed to allocate clear buffer"); + } } \ No newline at end of file diff --git a/main/main.c b/main/main.c index 671ee72..aa85961 100644 --- a/main/main.c +++ b/main/main.c @@ -85,14 +85,31 @@ void boot_btn_handler(int gpio_num, void *usr_data) { // 先通知活动 sleep_mgr_notify_activity(); - // 退出手电筒 - if (flashlight_is_active()) { - flashlight_exit(); + // 退出手电筒(会降亮度到0,但不恢复亮度) + bool was_flashlight_active = flashlight_is_active(); + uint8_t flashlight_saved_brightness = 0; + if (was_flashlight_active) { + flashlight_saved_brightness = flashlight_get_saved_brightness(); + flashlight_exit(); // 降亮度到0,删除overlay + ESP_LOGI("BTN_HANDLER", "手电筒已退出(亮度降为0)"); + + // 延迟80ms,确保overlay完全删除(至少15个刷新周期) + vTaskDelay(pdMS_TO_TICKS(80)); } // 切换到ScreenHome界面 _ui_screen_change(&ui_ScreenHome, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_ScreenHome_screen_init); ESP_LOGI("BTN_HANDLER", "已切换到ScreenHome界面"); + + // 如果刚从手电筒退出,延迟恢复亮度(等待界面渲染完成) + if (was_flashlight_active) { + // 延迟150ms等待Home界面完全渲染 + // 不使用强制刷新,让LVGL自动处理,避免多层同时重绘 + vTaskDelay(pdMS_TO_TICKS(150)); + + pwm_set_brightness(flashlight_saved_brightness); + ESP_LOGI("BTN_HANDLER", "亮度已恢复到%d%%", flashlight_saved_brightness); + } } } diff --git a/main/sleep_mgr/sleep_mgr.c b/main/sleep_mgr/sleep_mgr.c index 676ca80..04d3a7d 100644 --- a/main/sleep_mgr/sleep_mgr.c +++ b/main/sleep_mgr/sleep_mgr.c @@ -8,6 +8,7 @@ #include "freertos/task.h" #include "lvgl.h" #include "../ui/screens/ui_ScreenSet.h" +#include "../lcd/include/lcd.h" #include static const char *TAG = "SLEEP"; @@ -45,9 +46,16 @@ void sleep_mgr_notify_activity(void) ESP_LOGI(TAG, "LVGL 刷新定时器已恢复"); } + // 3. 强制刷新当前屏幕(因为GRAM被清空为黑色,需要重绘) + lv_obj_invalidate(lv_scr_act()); + ESP_LOGI(TAG, "已标记屏幕需要重绘"); + lvgl_port_unlock(); } + // 延迟50ms等待LVGL完成至少一次重绘,避免看到黑屏 + vTaskDelay(pdMS_TO_TICKS(50)); + // 恢复背光 pwm_set_brightness(saved_brightness); ESP_LOGI(TAG, "屏幕唤醒,恢复亮度%d%%", saved_brightness); @@ -91,11 +99,14 @@ static void screen_turn_off(void) lvgl_port_unlock(); } + // 清空LCD GRAM为黑色(避免关闭背光后看到残影) + lcd_clear_screen_black(); + // 关闭背光 screen_off = true; pwm_set_brightness(0); - ESP_LOGI(TAG, "屏幕已关闭(亮度=%d%%),系统进入真正低功耗模式(Light Sleep + LVGL暂停)", saved_brightness); + ESP_LOGI(TAG, "屏幕已关闭(亮度=%d%%),系统进入真正低功耗模式(Light Sleep + LVGL暂停 + LCD GRAM清空)", saved_brightness); } // 休眠管理任务 diff --git a/main/ui/screens/ui_ScreenSet.c b/main/ui/screens/ui_ScreenSet.c index 6b38909..2634df4 100644 --- a/main/ui/screens/ui_ScreenSet.c +++ b/main/ui/screens/ui_ScreenSet.c @@ -8,6 +8,8 @@ #include "../../pages/include/pages.h" #include "../../sleep_mgr/include/sleep_mgr.h" #include "esp_lvgl_port.h" // LVGL锁机制 +#include "freertos/FreeRTOS.h" +#include "freertos/task.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; @@ -159,21 +161,37 @@ static void flashlight_overlay_event_cb(lv_event_t *e) { } // 退出手电筒模式(外部调用) +// 注意:此函数不会恢复亮度,需要调用者在界面切换完成后手动恢复亮度 void flashlight_exit(void) { - // 停止闪烁定时器 - if (flashlight_timer) { - lv_timer_del(flashlight_timer); - flashlight_timer = NULL; + // 优化退出时序,避免闪烁: + // 1. 先将亮度降到0(黑屏) + pwm_set_brightness(0); + + // 2. 在LVGL锁保护下删除所有对象和定时器 + if (lvgl_port_lock(100)) { + // 停止闪烁定时器 + if (flashlight_timer) { + lv_timer_del(flashlight_timer); + flashlight_timer = NULL; + } + + // 停止淡入淡出定时器 + if (fade_timer) { + lv_timer_del(fade_timer); + fade_timer = NULL; + } + + // 删除遮罩层(此时屏幕已黑,看不到overlay删除的过程) + if (flashlight_overlay) { + lv_obj_del(flashlight_overlay); + flashlight_overlay = NULL; + } + + lvgl_port_unlock(); } - // 恢复之前的亮度 - pwm_set_brightness(saved_brightness); - - // 删除遮罩层 - if (flashlight_overlay) { - lv_obj_del(flashlight_overlay); - flashlight_overlay = NULL; - } + // 注意:不在这里恢复亮度,避免看到ScreenSet和Home界面混合显示 + // 亮度恢复由调用者(boot_btn_handler)在界面切换完成后执行 } // 查询手电筒是否激活 @@ -181,6 +199,11 @@ bool flashlight_is_active(void) { return (flashlight_overlay != NULL); } +// 获取手电筒模式前保存的亮度值 +uint8_t flashlight_get_saved_brightness(void) { + return saved_brightness; +} + // 显示手电筒模式 static void show_flashlight(void) { // 如果已经显示,则不重复创建 diff --git a/main/ui/screens/ui_ScreenSet.h b/main/ui/screens/ui_ScreenSet.h index 0acb0e5..ef78013 100644 --- a/main/ui/screens/ui_ScreenSet.h +++ b/main/ui/screens/ui_ScreenSet.h @@ -32,8 +32,9 @@ extern lv_obj_t *ui_LabelPowerLevel; // CUSTOM VARIABLES // 手电筒功能 -extern void flashlight_exit(void); // 退出手电筒模式 +extern void flashlight_exit(void); // 退出手电筒模式(不恢复亮度) extern bool flashlight_is_active(void); // 查询手电筒是否激活 +extern uint8_t flashlight_get_saved_brightness(void); // 获取手电筒模式前保存的亮度值 #ifdef __cplusplus } /*extern "C"*/ diff --git a/sdkconfig b/sdkconfig index 023258b..9789391 100644 --- a/sdkconfig +++ b/sdkconfig @@ -14,6 +14,7 @@ CONFIG_SOC_GDMA_SUPPORTED=y CONFIG_SOC_AHB_GDMA_SUPPORTED=y CONFIG_SOC_GPTIMER_SUPPORTED=y CONFIG_SOC_LCDCAM_SUPPORTED=y +CONFIG_SOC_LCDCAM_CAM_SUPPORTED=y CONFIG_SOC_LCDCAM_I80_LCD_SUPPORTED=y CONFIG_SOC_LCDCAM_RGB_LCD_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_CPU_BREAKPOINTS_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_DS_SIGNATURE_MAX_BIT_LEN=4096 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_WAKE_SUPPORTED=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_CLK_SUPPORT_APB=y CONFIG_SOC_SPI_PERIPH_NUM=3 @@ -369,6 +370,9 @@ CONFIG_SOC_BLE_DEVICE_PRIVACY_SUPPORTED=y CONFIG_SOC_BLUFI_SUPPORTED=y CONFIG_SOC_ULP_HAS_ADC=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_TOOLCHAIN="gcc" 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_ADV_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_ABORT_WHEN_ALLOCATION_FAILS is not set # 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_PSK_VERIFICATION is not set # CONFIG_ESP_TLS_INSECURE is not set +CONFIG_ESP_TLS_DYN_BUF_STRATEGY_SUPPORTED=y # end of ESP-TLS # @@ -1083,6 +1089,12 @@ CONFIG_ESP_ERR_TO_NAME_LOOKUP=y CONFIG_ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y # 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 # @@ -1403,8 +1415,11 @@ CONFIG_ESP_PHY_RF_CAL_PARTIAL=y # CONFIG_ESP_PHY_RF_CAL_NONE is not set # CONFIG_ESP_PHY_RF_CAL_FULL is not set 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_RECORD_USED_TIME is not set +CONFIG_ESP_PHY_IRAM_OPT=y +# CONFIG_ESP_PHY_DEBUG is not set # end of PHY # @@ -2084,6 +2099,7 @@ CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 # CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set # CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y +# CONFIG_MBEDTLS_SSL_KEYING_MATERIAL_EXPORT is not set CONFIG_MBEDTLS_PKCS7_C=y # end of mbedTLS v3.x related @@ -3067,6 +3083,7 @@ CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_DIS=y CONFIG_SW_COEXIST_ENABLE=y CONFIG_ESP32_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_EVENT_LOOP_PROFILING is not set CONFIG_POST_EVENTS_FROM_ISR=y