299 lines
12 KiB
C
299 lines
12 KiB
C
#include "driver/i2c.h"
|
||
#include "driver/spi_master.h"
|
||
#include "esp_err.h"
|
||
#include "esp_log.h"
|
||
#include "esp_pm.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 "ui/screens/ui_ScreenSet.h"
|
||
#include "ui/screens/ui_ScreenImg.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;
|
||
// }
|
||
|
||
// BOOT按键按下处理:低功耗模式下只唤醒屏幕,正常模式下返回ScreenHome
|
||
void boot_btn_handler(int gpio_num, void *usr_data) {
|
||
// 检查屏幕是否关闭(低功耗模式)
|
||
bool screen_was_off = sleep_mgr_is_screen_off();
|
||
|
||
if (screen_was_off) {
|
||
// 低功耗模式下:只唤醒屏幕,不切换界面
|
||
ESP_LOGI("BTN_HANDLER", "BOOT按键:低功耗模式,仅唤醒屏幕");
|
||
sleep_mgr_notify_activity(); // 唤醒屏幕,恢复亮度
|
||
} else {
|
||
// 正常模式下:返回ScreenHome界面
|
||
ESP_LOGI("BTN_HANDLER", "BOOT按键:正常模式,返回ScreenHome");
|
||
|
||
// 检查当前是否在ScreenImg界面,如果是则先隐藏ContainerDle
|
||
lv_obj_t *current_screen = lv_scr_act();
|
||
if (current_screen == ui_ScreenImg) {
|
||
ui_ScreenImg_hide_delete_container();
|
||
ESP_LOGI("BTN_HANDLER", "从ScreenImg离开,已隐藏ContainerDle");
|
||
}
|
||
|
||
// 先通知活动
|
||
sleep_mgr_notify_activity();
|
||
|
||
// 退出手电筒(会降亮度到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);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 初始化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已初始化
|
||
|
||
// 配置 Power Management(低功耗管理)
|
||
esp_pm_config_t pm_config = {
|
||
.max_freq_mhz = 160, // 最大频率 160MHz(与当前CPU频率一致)
|
||
.min_freq_mhz = 40, // 最小频率 40MHz(保证LVGL正常刷新)
|
||
.light_sleep_enable = true // 启用自动 Light Sleep
|
||
};
|
||
esp_err_t pm_err = esp_pm_configure(&pm_config);
|
||
if (pm_err == ESP_OK) {
|
||
ESP_LOGI("MAIN", "2.1 Power Management已启用:40-160MHz动态频率 + 自动Light Sleep");
|
||
} else {
|
||
ESP_LOGW("MAIN", "2.1 Power Management启用失败:%s", esp_err_to_name(pm_err));
|
||
}
|
||
|
||
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. 按键已初始化");
|
||
|
||
// 注册BOOT按键回调:返回ScreenHome界面
|
||
extern void boot_btn_handler(int gpio_num, void *usr_data);
|
||
button_on_boot_press(boot_btn_handler, NULL);
|
||
ESP_LOGI("MAIN", "12.1 BOOT按键回调已注册");
|
||
|
||
// 初始化休眠管理器(依赖按键和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();// 显示图片
|
||
// //=====================================================================
|
||
}
|