初始提交卡包 USB 工程

纳入固件源码、屏幕组件、nand_xfer 工具和文档。忽略本机构建产物、sdkconfig,以及含本机路径的依赖锁。

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
zhengxin
2026-10-13 21:54:50 +08:00
co-authored by Cursor
commit 851e347cf5
260 changed files with 269349 additions and 0 deletions
+171
View File
@@ -0,0 +1,171 @@
/*****************************************************include files **************************************************************************/
#include "screen_brightness.h"
#include "LVGL/lvgl_init.h"
#include "ui.h"
/******************************************************* variable declaration ************************************************************************/
/*
* 亮度模型:UI/BLE 的 0~100% 线性映射到面板 PWM [BRIGHTNESS_PWM_MIN, BRIGHTNESS_PWM_MAX]。
* 选 55 作为下限:约 21.5% 全量程,且 (255-55)=200,duty = 55 + percent*2,0~100 与整数 PWM 一一对应、无除法舍入误差。
* 若硬件需其它暗场门限,只改 BRIGHTNESS_PWM_MIN(需保持 SPAN 与映射公式一致或同步改除法)。
*/
#define BRIGHTNESS_PWM_MIN 55
#define BRIGHTNESS_PWM_MAX 255
#define BRIGHTNESS_PWM_SPAN (BRIGHTNESS_PWM_MAX - BRIGHTNESS_PWM_MIN)
// 当前面板 PWM(BRIGHTNESS_PWM_MIN~BRIGHTNESS_PWM_MAX);未读 NVS 前取中间偏亮,避免明显过暗
uint8_t g_current_brightness = (uint8_t)(BRIGHTNESS_PWM_MIN + BRIGHTNESS_PWM_SPAN * 3 / 4);
static bool g_brightness_dirty = false;
static uint8_t g_brightness_commit_pending = 0;
static TimerHandle_t g_brightness_commit_timer = NULL;
/******************************************************* functions declaration ************************************************************************/
void save_brightness_to_nvs(uint8_t value); /* forward declaration for timer callback */
void commit_brightness_if_dirty(void);
extern esp_err_t panel_qspi_amoled_set_brightness(esp_lcd_panel_handle_t panel, uint8_t brightness);
/******************************************************* functions definition ************************************************************************/
// 保存亮度到 NVS
void save_brightness_to_nvs(uint8_t value)
{
nvs_handle_t my_handle;
esp_err_t err = nvs_open("system_cfg", NVS_READWRITE, &my_handle);
if (err == ESP_OK)
{
nvs_set_u8(my_handle, "brightness", value);
nvs_commit(my_handle);
nvs_close(my_handle);
// ESP_LOGI("NVS", "亮度已保存: %d", value);
}
}
static void brightness_commit_timer_cb(TimerHandle_t xTimer)
{
(void)xTimer;
save_brightness_to_nvs(g_brightness_commit_pending);
}
// 从 NVS 读取亮度
void load_brightness_from_nvs(void)
{
nvs_handle_t my_handle;
esp_err_t err = nvs_open("system_cfg", NVS_READONLY, &my_handle);
if (err == ESP_OK)
{
uint8_t saved_val = 0;
if (nvs_get_u8(my_handle, "brightness", &saved_val) == ESP_OK)
{
g_current_brightness = saved_val;
if (g_current_brightness < BRIGHTNESS_PWM_MIN)
g_current_brightness = BRIGHTNESS_PWM_MIN;
if (g_current_brightness > BRIGHTNESS_PWM_MAX)
g_current_brightness = BRIGHTNESS_PWM_MAX;
ESP_LOGI("NVS", "加载保存的亮度: %d", g_current_brightness);
}
nvs_close(my_handle);
}
}
// ================= 对外接口 =================
// 设置亮度 (供 UI 和 BLE 调用)
// 参数 percent: 0-100,0 对应 PWM_MIN、100 对应 PWM_MAX
void set_system_brightness(int percent)
{
if (percent < 0)
percent = 0;
if (percent > 100)
percent = 100;
uint8_t duty = (uint8_t)(BRIGHTNESS_PWM_MIN + ((unsigned)percent * BRIGHTNESS_PWM_SPAN) / 100U);
// 3. 应用到硬件
if (panel_handle)
{
panel_qspi_amoled_set_brightness(panel_handle, duty);
}
// 4. 更新全局变量并保存
if (g_current_brightness != duty)
{
g_current_brightness = duty;
g_brightness_dirty = true;
request_brightness_slider_sync();
}
/* BLE/UI 共用:有变更时经定时器落盘 NVS(避免在回调里同步写) */
commit_brightness_if_dirty();
}
/* 退出亮度界面时调用:只写一次 NVS,避免频繁保存导致不稳定 */
void commit_brightness_if_dirty(void)
{
if (!g_brightness_dirty)
return;
g_brightness_commit_pending = g_current_brightness;
g_brightness_dirty = false;
/* NVS 写放到 timer 任务上下文,避免在 LVGL 点击事件回调里同步写导致崩溃 */
if (g_brightness_commit_timer == NULL)
{
g_brightness_commit_timer = xTimerCreate("brightness_commit_tmr",
pdMS_TO_TICKS(50),
pdFALSE,
NULL,
brightness_commit_timer_cb);
}
if (g_brightness_commit_timer)
{
xTimerStop(g_brightness_commit_timer, 0);
if (xTimerStart(g_brightness_commit_timer, 0) != pdPASS)
{
/* 定时器队列满等异常时仍落盘,避免已清 dirty 却永不写入 NVS */
save_brightness_to_nvs(g_brightness_commit_pending);
}
}
else
{
/* xTimerCreate 失败(如堆不足)时直接写 NVS,否则与蓝牙路径行为不一致 */
save_brightness_to_nvs(g_brightness_commit_pending);
}
}
// 获取当前亮度百分比 (供 UI 初始化滑块与 BLE 查询,0~100)
int get_system_brightness_percent(void)
{
unsigned d = g_current_brightness;
if (d <= BRIGHTNESS_PWM_MIN)
return 0;
if (d >= BRIGHTNESS_PWM_MAX)
return 100;
return (int)((d - BRIGHTNESS_PWM_MIN) * 100U / BRIGHTNESS_PWM_SPAN);
}
// 【核心函数 2】设置是否阻止休眠 (例如 OTA 时调用 set_block_sleep(true))
void set_block_auto_sleep(bool block)
{
block_auto_sleep = block;
if (block)
{
system_keep_alive(); // 阻止时顺便刷新一下时间
}
}
/* 亮度滑动条同步:将设置页滑动条与当前系统亮度对齐 */
void request_brightness_slider_sync(void)
{
extern lv_ui guider_ui;
extern int get_system_brightness_percent(void);
int percent = get_system_brightness_percent();
if (guider_ui.screen_set_slider_light != NULL &&
lv_obj_is_valid(guider_ui.screen_set_slider_light)) {
lv_slider_set_value(guider_ui.screen_set_slider_light, percent, LV_ANIM_OFF);
}
}
+20
View File
@@ -0,0 +1,20 @@
#ifndef __SCREEN_BRIGHTNESS_H__
#define __SCREEN_BRIGHTNESS_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "config.h"
extern uint8_t g_current_brightness;
/** percent: 0~100,与滑动条/BLE 一致;0→PWM 下限、100→PWM 上限(见 screen_brightness.c) */
void set_system_brightness(int percent);
/** 有亮度脏标记时写 NVS(内部 50ms 防抖定时器);供退出设置页等场景也可直接调用 */
void commit_brightness_if_dirty(void);
#ifdef __cplusplus
}
#endif
#endif
+237
View File
@@ -0,0 +1,237 @@
#include "screen_init.h"
#include "config.h"
#include "LVGL/lvgl_init.h"
#include "driver/i2c_master.h"
const char *TAG_LVGL = "lvgl_init";//打印标签
#if EXAMPLE_USE_TOUCH
esp_lcd_touch_handle_t tp = NULL;
bool is_anim_paused = false;
i2c_master_bus_handle_t touch_bus_handle_touch; // 定义触摸屏I2C总线句柄(全局,供BMI270共享)
#endif
static void read_lcd_id(esp_lcd_panel_io_handle_t read_io)
{
uint8_t id_buf[3] = {0};
esp_err_t ret = esp_lcd_panel_io_rx_param(read_io, 0x03000400, id_buf, 3);
if (ret == ESP_OK) {
ESP_LOGI(TAG_LVGL, "LCD ID: %02X %02X %02X", id_buf[0], id_buf[1], id_buf[2]);
} else {
ESP_LOGE(TAG_LVGL, "Read ID failed: %s", esp_err_to_name(ret));
}
uint8_t id1 = 0;
uint8_t id2 = 0;
uint8_t id3 = 0;
esp_err_t ret1 = esp_lcd_panel_io_rx_param(read_io, 0x0300DA00, &id1, 1);
esp_err_t ret2 = esp_lcd_panel_io_rx_param(read_io, 0x0300DB00, &id2, 1);
esp_err_t ret3 = esp_lcd_panel_io_rx_param(read_io, 0x0300DC00, &id3, 1);
if (ret1 == ESP_OK && ret2 == ESP_OK && ret3 == ESP_OK) {
ESP_LOGI(TAG_LVGL, "LCD RDID: %02X %02X %02X", id1, id2, id3);
} else {
ESP_LOGE(TAG_LVGL, "Read RDID failed: %s %s %s",
esp_err_to_name(ret1), esp_err_to_name(ret2), esp_err_to_name(ret3));
}
}
/*
const qspi_amoled_lcd_init_cmd_t lcd_init_cmds[13] = {
{0xFE, (uint8_t[]){0x00}, 1, 0},
{0xC4, (uint8_t[]){0x80}, 1, 0},
{0x35, (uint8_t[]){0x00}, 1, 0},
{0x3A, (uint8_t[]){0x77}, 1, 0},
{0x53, (uint8_t[]){0x20}, 1, 0},
{0x51, (uint8_t[]){0x00}, 1, 0},
{0x63, (uint8_t[]){0xFF}, 1, 0},
{0x2A, (uint8_t[]){0x00, 0x16, 0x01, 0xAF}, 4, 0},
{0x2B, (uint8_t[]){0x00, 0x00, 0x01, 0xF5}, 4, 0},
{0x11, (uint8_t[]){0x00}, 0, 120},
{0x29, (uint8_t[]){0x00}, 0, 60},
{0x58, (uint8_t[]){0x07}, 1, 10},
{0x36, (uint8_t[]){0xA8}, 1, 0},
};
*/
const qspi_amoled_lcd_init_cmd_t lcd_init_cmds[] = {
// 0x11: 退出睡眠模式(Sleep Out),之后延时 60ms
{0x11, (uint8_t[]){0x00}, 0, 60},
// 0x2A: 列地址范围 0~239(0x00 0x00 ~ 0x00 0xEF)
{0x2A, (uint8_t[]){0x00, 0x00, 0x00, 0xEF}, 4, 0},
// 0x2B: 行地址范围 0~295(0x00 0x00 ~ 0x01 0x27)
{0x2B, (uint8_t[]){0x00, 0x00, 0x01, 0x27}, 4, 0},
// 0x44: 撕裂效应行(TE Line)设为 295
{0x44, (uint8_t[]){0x01, 0x27}, 2, 0},
// 0x3A: 像素格式(Pixel Format)0x55(通常为 16bit/18bit)
{0x3A, (uint8_t[]){0x55}, 1, 0},
// 0x35: TE 信号控制,0x00 = 关闭
{0x35, (uint8_t[]){0x00}, 1, 0},
// 0x53: 亮度控制寄存器,设为 0x20
{0x53, (uint8_t[]){0x20}, 1, 0},
// 0x51: 亮度值设为最高 0xFF,之后延时 60ms 再开启显示
{0x51, (uint8_t[]){0xFF}, 1, 60},
// 0x29: 开启显示(Display On),无需额外延时
{0x29, (uint8_t[]){0x00}, 0, 0},
};
// QSPI AMOLED供应商配置
qspi_amoled_vendor_config_t vendor_config =
{
.init_cmds = lcd_init_cmds,
.init_cmds_size = sizeof(lcd_init_cmds) / sizeof(lcd_init_cmds[0]),
.flags =
{
.use_qspi_interface = 1,
},
};
// LCD面板配置
const esp_lcd_panel_dev_config_t panel_config =
{
.reset_gpio_num = EXAMPLE_PIN_NUM_LCD_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER,
.bits_per_pixel = LCD_BIT_PER_PIXEL,
.vendor_config = &vendor_config,
};
extern esp_lcd_panel_io_handle_t io_handle;
void read_co5300_response(void) {
}
esp_err_t app_lcd_init(void)//QSPI初始化
{
esp_err_t ret = ESP_OK;
ESP_LOGI(TAG_LVGL, "Initialize QSPI bus");
// 使用原始的SPI总线最大传输大小,确保稳定传输
const spi_bus_config_t buscfg = QSPI_AMOLED_PANEL_BUS_QSPI_CONFIG(EXAMPLE_PIN_NUM_LCD_PCLK,
EXAMPLE_PIN_NUM_LCD_DATA0,
EXAMPLE_PIN_NUM_LCD_DATA1,
EXAMPLE_PIN_NUM_LCD_DATA2,
EXAMPLE_PIN_NUM_LCD_DATA3,
(EXAMPLE_LCD_H_RES * EXAMPLE_LVGL_BUF_HEIGHT * LCD_BIT_PER_PIXEL / 8) + 64);
ESP_ERROR_CHECK(spi_bus_initialize(LCD_HOST, &buscfg, SPI_DMA_CH_AUTO));
ESP_LOGI(TAG_LVGL, "Install panel IO");
esp_lcd_panel_io_spi_config_t io_config = {
.cs_gpio_num = EXAMPLE_PIN_NUM_LCD_CS,
.dc_gpio_num = -1,
.spi_mode = AMOLED_QSPI_MODE,
.pclk_hz = AMOLED_QSPI_MAX_PCLK,
.trans_queue_depth = 3,
.on_color_trans_done = example_notify_lvgl_flush_ready,
.user_ctx = NULL,
.lcd_cmd_bits = 32,
.lcd_param_bits = 8,
.flags = {
.quad_mode = true,
},
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_HOST, &io_config, &io_handle));
ESP_LOGI(TAG_LVGL, "Install QSPI_AMOLED panel driver");
ESP_ERROR_CHECK(esp_lcd_new_panel_qspi_amoled(io_handle, &panel_config, &panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_set_gap(panel_handle, EXAMPLE_LCD_X_GAP, EXAMPLE_LCD_Y_GAP));
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
/* 初始化时设置亮度为0,避免白光闪烁,等待 UI 加载后渐变亮屏 */
esp_err_t br = panel_qspi_amoled_set_brightness(panel_handle,100);
//uint8_t read_buf[3] = {0}; // RDDID 返回 3 个字节
/*
// 发送读指令 0x04,读取 3 个字节的回应数据
esp_err_t ret2 = esp_lcd_panel_io_rx_param(io_handle, 0x04, read_buf, 3);
if (ret2 == ESP_OK) {
ESP_LOGI("TAG", "读取回应成功!ID1: 0x%02X, ID2: 0x%02X, ID3: 0x%02X",
read_buf[0], read_buf[1], read_buf[2]);
// 根据数据手册,正常回应通常为:33h, 10h, 00h 或 33h, 11h, 00h
} else {
ESP_LOGE("TAG", "读取回应失败:%s", esp_err_to_name(ret2));
}*/
//read_lcd_id(io_handle);
//ESP_LOGI(TAG_LVGL,"br=%d",br);
//uint8_t blue_color[] = {0x00, 0x00, 0xFF};
//esp_err_t brt =panel_qspi_amoled_draw_bitmap(panel_handle, 0, 0, EXAMPLE_LCD_H_RES - 1, EXAMPLE_LCD_V_RES - 1, blue_color);
/*
if (br != ESP_OK)
{
ESP_LOGE(TAG_LVGL, "panel_qspi_amoled_set_brightness failed: %s", esp_err_to_name(br));
}
else
{
ESP_LOGI(TAG_LVGL, "Screen brightness set to 0 (等待 UI 加载后渐变亮屏)");
}
*/
/* Register done callback */
//ESP_ERROR_CHECK(esp_lcd_panel_io_register_event_callbacks(io_handle, &cbs, disp));
return ret;
}
esp_err_t app_touch_init(void)
{
ESP_LOGI(TAG_LVGL, "初始化 I2C 总线 (新驱动模式)");
// 1. 配置 I2C 总线
i2c_master_bus_config_t i2c_bus_config = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = TOUCH_HOST,
.scl_io_num = EXAMPLE_PIN_NUM_TOUCH_SCL,
.sda_io_num = EXAMPLE_PIN_NUM_TOUCH_SDA,
.glitch_ignore_cnt = 7,
.flags.enable_internal_pullup = true,
};
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &touch_bus_handle_touch));
// 2. 配置触摸面板 IO(这里会自动适配新驱动)
esp_lcd_panel_io_handle_t tp_io_handle = NULL;
const esp_lcd_panel_io_i2c_config_t tp_io_config = {
.dev_addr = 0x15, // CST816/CST820 的默认地址,根据实际修改
.on_color_trans_done = NULL,
.user_ctx = NULL,
.control_phase_bytes = 1,
.dc_bit_offset = 0,
.lcd_cmd_bits = 8,
.lcd_param_bits = 8,
.scl_speed_hz = 400 * 1000,
.flags = {
.disable_control_phase = 1,
}};
// 使用新总线句柄创建 IO
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(touch_bus_handle_touch, &tp_io_config, &tp_io_handle));
// 3. 配置触摸芯片参数
const esp_lcd_touch_config_t tp_cfg = {
.x_max = EXAMPLE_LCD_H_RES,
.y_max = EXAMPLE_LCD_V_RES,
.rst_gpio_num = EXAMPLE_PIN_NUM_TOUCH_RST,
.int_gpio_num = EXAMPLE_PIN_NUM_TOUCH_INT,
.levels = {
.reset = 0,
.interrupt = 0,
},
.flags = {
.swap_xy = 1,
.mirror_x = 0,
.mirror_y = 1,
},
};
ESP_LOGI(TAG_LVGL, "创建触摸控制器句柄");
return esp_lcd_touch_new_i2c(tp_io_handle, &tp_cfg, &tp);
}
+21
View File
@@ -0,0 +1,21 @@
#ifndef __SCREEN_INIT_H__
#define __SCREEN_INIT_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "config.h"
extern const esp_lcd_panel_dev_config_t panel_config;
extern const char *TAG_LVGL ;
esp_err_t app_lcd_init(void);
#ifdef __cplusplus
}
#endif
#endif
+177
View File
@@ -0,0 +1,177 @@
/*****************************************************include files **************************************************************************/
#include "screen_sleep.h"
#include "ui/generated/events_init.h"
#include "ui/ui.h"
#define AUTO_SLEEP_DEFAULT_MS 0//默认休眠时间
/******************************************************* variable declaration ************************************************************************/
static uint32_t g_auto_sleep_timeout_ms = AUTO_SLEEP_DEFAULT_MS;
// 初始化为当前开机时间
int64_t last_activity_timestamp = 0; //最后一次用户活动的时间戳
static bool g_sleep_timeout_dirty = false; //休眠时间是否被改过但是没有写入NVS
static uint32_t g_sleep_commit_pending_ms = 0; //待提交到NVS的休眠时间缓存值
/* ===== 休眠设置 NVS 提交:离开休眠界面时写一次 ===== */
static TimerHandle_t g_sleep_commit_timer = NULL; //创建了freeRTOS的软件定时器句柄
extern volatile bool is_system_sleeping; //系统睡眠标记
extern bool block_auto_sleep ; //是否阻止自动休眠
extern int current_page_idx ; //当前页面索引
/******************************************************* functions declaration ************************************************************************/
static void save_timeout_to_nvs(uint32_t ms);
static void sleep_commit_timer_cb(TimerHandle_t xTimer);
/******************************************************* functions definition ************************************************************************/
// 【新增】从 NVS 加载休眠时间
void load_timeout_from_nvs(void)//从nvs加载休眠时间
{
nvs_handle_t my_handle;
esp_err_t err = nvs_open("system_cfg", NVS_READONLY, &my_handle);
if (err != ESP_OK)
{
ESP_LOGW("NVS", "打开 system_cfg 失败: %s,休眠时间使用默认 %lu ms",
esp_err_to_name(err), (unsigned long)AUTO_SLEEP_DEFAULT_MS);
g_auto_sleep_timeout_ms = AUTO_SLEEP_DEFAULT_MS;
system_keep_alive();
return;
}
uint32_t saved_val = 0;
if (nvs_get_u32(my_handle, "sleep_ms", &saved_val) == ESP_OK)
{
g_auto_sleep_timeout_ms = saved_val;
ESP_LOGI("NVS", "从 NVS 加载休眠时间: %lu ms", (unsigned long)g_auto_sleep_timeout_ms);
}
else
{
g_auto_sleep_timeout_ms = AUTO_SLEEP_DEFAULT_MS;
ESP_LOGW("NVS", "未找到 sleep_ms,使用默认 %lu ms", (unsigned long)AUTO_SLEEP_DEFAULT_MS);
}
nvs_close(my_handle);
/* 以完成 NVS 加载时刻为空闲计时起点,避免 last_activity 长期为 0 误判超时 */
system_keep_alive();
}
// 【新增】保存设置到 NVS
static void save_timeout_to_nvs(uint32_t ms)//保存休眠时间到nvs
{
nvs_handle_t my_handle;
esp_err_t err = nvs_open("system_cfg", NVS_READWRITE, &my_handle);
if (err == ESP_OK)
{
nvs_set_u32(my_handle, "sleep_ms", ms);
nvs_commit(my_handle); // 提交保存
nvs_close(my_handle);
ESP_LOGI("NVS", "休眠时间已保存: %lu ms", (unsigned long)ms);
}
else
{
ESP_LOGE("NVS", "无法打开 NVS 保存设置");
}
}
void persist_auto_sleep_timeout_ms_now(uint32_t ms)
{
if (g_sleep_commit_timer != NULL)
{
xTimerStop(g_sleep_commit_timer, pdMS_TO_TICKS(100));
}
g_auto_sleep_timeout_ms = ms;
g_sleep_timeout_dirty = false;
g_sleep_commit_pending_ms = ms;
system_keep_alive();
save_timeout_to_nvs(ms);
}
// 2. 【新增】设置超时时间的函数 (提供给按钮调用)
// 输入 0 代表永不休眠 设置自动休眠时间
void set_auto_sleep_timeout(uint32_t ms)
{
if (g_auto_sleep_timeout_ms == ms) {
return;
}
g_auto_sleep_timeout_ms = ms;
system_keep_alive();
ESP_LOGI("PM", "休眠设置更新: %lu ms (mark dirty)", (unsigned long)ms);
g_sleep_timeout_dirty = true;
}
// 【核心函数 1】系统保活:任何操作都应该调用这个函数
void system_keep_alive(void)//更新当前的活动时间戳
{
last_activity_timestamp = esp_timer_get_time() / 1000; // 更新为当前时间(ms)
}
//获取自动休眠时间
uint32_t get_auto_sleep_timeout(void)
{
return g_auto_sleep_timeout_ms;
}
//如果脏标记被设置过之后 发送自动休眠时间
void commit_auto_sleep_timeout_if_dirty(void)
{
if (!g_sleep_timeout_dirty)
return;
g_sleep_commit_pending_ms = g_auto_sleep_timeout_ms;
g_sleep_timeout_dirty = false;
/* 真正的 NVS 写放到 timer 回调里,避免在 LVGL 事件栈上下文里写 NVS */
if (g_sleep_commit_timer == NULL)
{
g_sleep_commit_timer = xTimerCreate("sleep_commit_tmr",
pdMS_TO_TICKS(50),
pdFALSE,
NULL,
sleep_commit_timer_cb);
}
if (g_sleep_commit_timer)
{
if (xTimerStart(g_sleep_commit_timer, 0) != pdPASS)
{
save_timeout_to_nvs(g_sleep_commit_pending_ms);
}
}
else
{
save_timeout_to_nvs(g_sleep_commit_pending_ms);
}
}
static void sleep_commit_timer_cb(TimerHandle_t xTimer)
{
(void)xTimer;
save_timeout_to_nvs(g_sleep_commit_pending_ms);
}
void auto_sleep_checker_cb(lv_timer_t *timer)
{
// 如果已经在睡觉,或者被阻止,或者设置为 0 (永不),直接返回
if (is_system_sleeping || block_auto_sleep || g_auto_sleep_timeout_ms == 0)
{
return;
}
int64_t now = esp_timer_get_time() / 1000;
// 使用变量 g_auto_sleep_timeout_ms 替代原来的 30000
if ((now - last_activity_timestamp) > g_auto_sleep_timeout_ms)
{
ESP_LOGW("PM", "系统空闲超时,自动进入休眠...");
if (current_page_idx != 0)
{
ui_change_page(0, LV_SCR_LOAD_ANIM_FADE_ON);
}
toggle_sleep_mode(true);
}
}
+29
View File
@@ -0,0 +1,29 @@
#ifndef __SCREEN_SLEEP_H__
#define __SCREEN_SLEEP_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "config.h"
extern const esp_lcd_panel_dev_config_t panel_config;
extern const char *TAG_LVGL ;
esp_err_t app_lcd_init(void);
void system_keep_alive(void);
void load_timeout_from_nvs(void);
void set_auto_sleep_timeout(uint32_t ms);
uint32_t get_auto_sleep_timeout(void);
void commit_auto_sleep_timeout_if_dirty(void);
/** 立即把 ms 写入 RAM 与 NVS(停掉延迟提交定时器);用于恢复出厂等须在 esp_restart 前落盘的场景 */
void persist_auto_sleep_timeout_ms_now(uint32_t ms);
void auto_sleep_checker_cb(lv_timer_t *timer);
#ifdef __cplusplus
}
#endif
#endif