1、按键驱动重构:从GPIO中断改为iot_button组件,支持BOOT/KEY2的单击/双击/长按6种事件; 2、新增按键导航管理器(key_nav):9种上下文状态机,统一分发按键事件到对应界面业务逻辑; 3、BLE模块改造:广播默认关闭由按键触发,新增设备间图片传输(GATT Client),支持扫描配对→MTU协商→分包发送; 4、新增6个UI界面:配对(Peiwang)、更新(Update)、发送等待(ImageShar)、接收等待(ImageReception)、发送中(Sharing)、接收中(Receiving); 5、新增电池指示器组件(battery_ui):支持多界面真实电量显示,3秒渐隐效果; 6、Home界面重构:移除手势事件,改为airhub背景图+电池指示器; 7、Img界面重构:移除触摸事件,新增删除二次确认边框机制; 8、禁用ScreenSet/ScreenChar界面(保留文件),禁用触摸初始化(保留代码可恢复); 9、sleep_mgr简化:移除ScreenSet亮度UI依赖,按键唤醒由key_nav统一处理; 10、新增9张图片资源(airhub背景、配对、传输状态、电池图标等); Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
255 lines
9.5 KiB
C
255 lines
9.5 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 "fatfs.h"
|
||
#include "pages.h"
|
||
#include "ble.h"
|
||
#include "battery.h"
|
||
#include "button.h"
|
||
#include "sleep_mgr.h"
|
||
#include "key_nav.h"
|
||
#include "ui/ui.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;
|
||
// }
|
||
|
||
// 初始化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 = 240, // 最大频率 240MHz(GIF解码需要高算力)
|
||
.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-240MHz动态频率 + 自动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/KEY2所有事件回调)
|
||
key_nav_init();
|
||
ESP_LOGI("MAIN", "12.1 按键导航已初始化");
|
||
|
||
// 初始化BLE蓝牙(仅初始化,不开始广播,由KEY2按键触发)
|
||
ble_init();
|
||
ESP_LOGI("MAIN", "13. BLE蓝牙已初始化(默认关闭广播)");
|
||
|
||
// 初始化设备间蓝牙传图模块(GATT Client)
|
||
extern void ble_transfer_init(void);
|
||
ble_transfer_init();
|
||
ESP_LOGI("MAIN", "13.1 设备间传图模块已初始化");
|
||
|
||
// 初始化休眠管理器(依赖按键和UI,必须最后初始化)
|
||
sleep_mgr_init();
|
||
ESP_LOGI("MAIN", "14. 休眠管理器已初始化");
|
||
|
||
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();// 显示图片
|
||
// //=====================================================================
|
||
}
|