Rdzleo 5eddd2aa72 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>
2026-02-11 10:28:25 +08:00

227 lines
8.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "driver/i2c.h"
#include "driver/spi_master.h"
#include "esp_err.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_flash.h"
#include "esp_check.h"
#include "nvs_flash.h"
#include "lv_demos.h"
#include "string.h"
#include "gpio.h"
#include "wifi.h"
#include "lcd.h"
#include "temp.h"
#include "fatfs.h"
#include "pages.h"
#include "ble.h"
#include "battery.h"
#include "button.h"
#include "sleep_mgr.h"
#include "ui/ui.h"
// #include "axis.h"
// #include "esp_bt.h"
// #include "esp_mac.h"
// #include "esp_gap_ble_api.h"
// #include "esp_gattc_api.h"
// #include "esp_gatt_defs.h"
// #include "esp_bt_main.h"
// #include "esp_log.h"
// #include "esp_system.h"
// #include "esp_bt_defs.h"
// #include "freertos/FreeRTOS.h"
// esp_err_t spi_init(void){
// spi_bus_config_t spi_conf = {
// .sclk_io_num = PIN_LCD_CLK,
// .data0_io_num = PIN_LCD_D0,
// .data1_io_num = PIN_LCD_D1,
// .data2_io_num = PIN_LCD_D2,
// .data3_io_num = PIN_LCD_D3,
// .max_transfer_sz = 4096,
// .flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_QUAD,
// };
// esp_err_t err = spi_bus_initialize(SPI_LCD_HOST,&spi_conf, SPI_DMA_CH_AUTO);
// spi_device_interface_config_t devcfg = {
// .command_bits = 8,
// .address_bits = 24,
// .mode = 0,
// .clock_speed_hz = 10000000,
// .spics_io_num = PIN_LCD_CS,
// .queue_size = 1,
// .cs_ena_posttrans = 0,
// .flags = SPI_DEVICE_HALFDUPLEX,
// };
// err = spi_bus_add_device(SPI_LCD_HOST, &devcfg, &spi_lcd_handle);
// return err;
// }
// 初始化I2C
esp_err_t i2c_init(void){
i2c_config_t i2c_conf = {
.scl_io_num = PIN_NUM_SCL,
.sda_io_num = PIN_NUM_SDA,
.mode = I2C_MODE_MASTER,
.master.clk_speed = I2C_MASTER_FREQ_HZ,
};
i2c_param_config(I2C_MASTER_NUM,&i2c_conf);
return i2c_driver_install(I2C_MASTER_NUM, i2c_conf.mode,0,0, 0);
}
// esp_err_t i2c_master_write_slave(uint8_t slave_addr, uint8_t *data_w, size_t size_w) {
// i2c_cmd_handle_t cmd = i2c_cmd_link_create();
// i2c_master_start(cmd);
// i2c_master_write_byte(cmd, (slave_addr << 1) | I2C_MASTER_WRITE, true);
// i2c_master_write(cmd, data_w, size_w, true);
// i2c_master_stop(cmd);
// esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 100);
// i2c_cmd_link_delete(cmd);
// return ret;
// }
// esp_err_t i2c_master_read_slave(uint8_t slave_addr,uint8_t order, uint8_t *data_r, size_t size_r) {
// i2c_cmd_handle_t cmd = i2c_cmd_link_create();
// i2c_master_start(cmd);
// i2c_master_write_byte(cmd, (slave_addr << 1) | I2C_MASTER_WRITE, true);
// i2c_master_write_byte(cmd,order,true);
// i2c_master_start(cmd);
// i2c_master_write_byte(cmd, (slave_addr << 1) | I2C_MASTER_READ, true);
// i2c_master_read(cmd, data_r, size_r, true);
// i2c_master_stop(cmd);
// esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 100);
// i2c_cmd_link_delete(cmd);
// return ret;
// }
// 初始化NVS
void nvs_init(){
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());// 擦除NVS分区
ret = nvs_flash_init();// 初始化NVS
}
ESP_ERROR_CHECK(ret);// 检查NVS初始化是否成功
// 添加默认图片路径设置
// ============================================================================
nvs_handle_t nvs_handle;
esp_err_t err = nvs_open("config", NVS_READWRITE, &nvs_handle);// 打开NVS配置文件
if (err == ESP_OK) {
size_t imgname_len;// 图片路径长度
err = nvs_get_str(nvs_handle, "img_filename", NULL, &imgname_len);// 获取当前图片路径长度
if (err != ESP_OK) {
// 设置默认图片路径(与放入 spiffs_image 的文件名一致)
const char* default_img = "default.jpg";// 默认图片文件名
err = nvs_set_str(nvs_handle, "img_filename", default_img);// 设置默认图片路径
if (err == ESP_OK) {
nvs_commit(nvs_handle);
ESP_LOGI("NVS", "Set default image: %s", default_img);// 设置默认图片路径
}
}
nvs_close(nvs_handle);// 关闭NVS配置文件
}
// ============================================================================
// nvs_handle_t nvs_handle;
// esp_err_t err;
// err = nvs_open("config", NVS_READWRITE, &nvs_handle);
// if (err != ESP_OK) printf("创建config失败\n");
// int32_t brightness = 80;
// const char* wifi_ssid = "MyWiFi";
// const char* img_filename = "face_1762059331906.jpg";
// err = nvs_set_i32(nvs_handle, "brightness", brightness);
// if (err != ESP_OK) goto close_handle;
// err = nvs_set_str(nvs_handle, "wifi_ssid", wifi_ssid);
// if (err != ESP_OK) goto close_handle;
// err = nvs_set_str(nvs_handle, "img_filename", img_filename);
// if (err != ESP_OK) goto close_handle;
// err = nvs_commit(nvs_handle);
// close_handle:
// nvs_close(nvs_handle);
}
void app_main(void)
{
i2c_init();
ESP_LOGI("MAIN", "1. I2C已初始化");// I2C已初始化
nvs_init();
ESP_LOGI("MAIN", "2. NVS已初始化");// NVS已初始化
lcd_init();
ESP_LOGI("MAIN", "3. LCD已初始化");// LCD已初始化
touch_init();
ESP_LOGI("MAIN", "4. 触摸控制器已初始化");// 触摸控制器已初始化
lvgl_lcd_init();
ESP_LOGI("MAIN", "5. LVGL已初始化");// LVGL已初始化
// LVGL任务创建后下一个tick即运行利用这段时间初始化文件系统
fatfs_init();
ESP_LOGI("MAIN", "6. FATFS文件系统已初始化");// FATFS已初始化
fatfs_remove_nullData("/spiflash");// 移除空数据
fatfs_list_all_filenames("/spiflash",false);// 列出所有文件名
ESP_LOGI("MAIN", "7. SPIFFS处理完成");// SPIFFS处理完成
// =====================================================================
// 显示SquareLine Studio生成的UI界面
ui_init(); // 初始化UI含JPEG解码
ESP_LOGI("MAIN", "8. SquareLine UI已初始化");// SquareLine UI已初始化
// 等待LVGL完成屏幕切换和首帧渲染彻底避免开机闪烁
// ui_init()会创建所有屏幕并加载ScreenHome包括
// 1. JPEG解码约210ms
// 2. 屏幕对象创建和切换
// 3. QSPI传输首帧到LCD约100ms
// 增加到150ms确保所有渲染完成后再点亮背光
vTaskDelay(pdMS_TO_TICKS(150));
// UI渲染完成后再点亮背光避免开机闪烁旧画面
pwm_init();
ESP_LOGI("MAIN", "9. PWM背光已初始化");// PWM背光已初始化
// 初始化电池ADC检测并启动监控任务
ESP_ERROR_CHECK(battery_init());
ESP_LOGI("MAIN", "10. 电池ADC已初始化");
battery_monitor_start();
ESP_LOGI("MAIN", "11. 电池监控任务已启动");
// 初始化按键驱动
ESP_ERROR_CHECK(button_init());
ESP_LOGI("MAIN", "12. 按键已初始化");
// 初始化休眠管理器依赖按键和UI必须最后初始化
sleep_mgr_init();
ESP_LOGI("MAIN", "13. 休眠管理器已初始化");
ESP_LOGI("MAIN", "系统初始化完成成功!");// 系统初始化完成成功
// =====================================================================
// // 优先显示测试屏幕
// app_test_display();
// ESP_LOGI("MAIN", "Test screen displayed");
// //=====================================================================
// // // 启动图片循环显示任务
// xTaskCreate(img_loop_task, "img_loop_task", 8192, NULL, 5, NULL);
// ESP_LOGI("MAIN", "图片循环显示任务已启动");
// ESP_LOGI("MAIN", "任务将每3秒循环显示SPIFFS中的所有图片");
// //=====================================================================
// 注释掉静态图片显示,使用任务自动切换
// app_img_display();// 显示图片
// //=====================================================================
}