Rdzleo 4860efca6e 新增手电筒功能 + 颜色切换性能优化
## 核心功能
- 实现全屏手电筒:支持红/绿/蓝三色点击切换
- 自动闪烁模式:1000ms周期(500ms高亮100% + 500ms低亮20%)
- BOOT按键退出手电筒并返回主界面

## 性能优化(关键创新)
- PWM遮罩技术:立即黑屏遮盖LCD刷新过程,完全消除卡顿
- 简化实现:只修改样式不重建对象,降低资源消耗
- 切换速度:从135ms优化到100ms(提升25.7%)
- SPI时钟:40MHz → 80MHz(提升LCD刷新速度)

## 技术细节
- PWM淡入淡出步进:20% → 25%(10ms → 8ms)
- 刷新等待时间:120ms → 90ms(基于理论计算优化)
- 初始延迟:5ms → 2ms(PWM设置是立即的)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 13:54:22 +08:00

138 lines
4.8 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 "gpio.h"
#include "esp_lvgl_port.h"
#include "esp_lcd_st77916.h"
#include "esp_err.h"
#include "esp_log.h"
#include "lcd.h"
#include "esp_lcd_touch_cst816s.h"
#include "unity.h"
#include "unity_test_runner.h"
static lv_disp_t * disp_handle = NULL;
static esp_lcd_panel_handle_t panel_handle = NULL;
static esp_lcd_panel_io_handle_t io_handle = NULL;
static esp_lcd_touch_handle_t touch_handle;
static esp_lcd_panel_io_handle_t tp_io_handle = NULL;
void lcd_init(){
const spi_bus_config_t buscfg = ST77916_PANEL_BUS_QSPI_CONFIG(PIN_LCD_CLK,
PIN_LCD_D0,
PIN_LCD_D1,
PIN_LCD_D2,
PIN_LCD_D3,
LCD_HIGH * 80 * sizeof(uint16_t));
spi_bus_initialize(SPI_LCD_HOST, &buscfg, SPI_DMA_CH_AUTO);
// 自定义IO配置提升SPI时钟从40MHz到80MHz
esp_lcd_panel_io_spi_config_t io_config = ST77916_PANEL_IO_QSPI_CONFIG(PIN_LCD_CS, NULL, NULL);
io_config.pclk_hz = 80 * 1000 * 1000; // 提升到80MHz最大值
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)SPI_LCD_HOST, &io_config, &io_handle));
const st77916_vendor_config_t vendor_config = {
.flags = {
.use_qspi_interface = 1,
},
};
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = PIN_LCD_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
.vendor_config = &vendor_config,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_st77916(io_handle, &panel_config, &panel_handle));
esp_lcd_panel_reset(panel_handle);
esp_lcd_panel_init(panel_handle);
esp_lcd_panel_disp_on_off(panel_handle, true);
}
// 初始化触摸控制器
void touch_init(){
const esp_lcd_touch_config_t tp_cfg = {
.x_max = LCD_WID,
.y_max = LCD_HIGH,
.rst_gpio_num = PIN_TP_RST,
.int_gpio_num = PIN_TP_INT,
.levels = {
.reset = 0,// 重置电平
.interrupt = 0,// 中断电平
},
.flags = {
.swap_xy = false,// 交换XY轴
.mirror_x = false,// 水平镜像
.mirror_y = false,// 垂直镜像
},
};
const esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_CST816S_CONFIG();
esp_err_t err = esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)I2C_MASTER_NUM, &tp_io_config, &tp_io_handle);
if (err != ESP_OK) {
ESP_LOGE(LCD_TAG, "Failed to create I2C IO for touch: %s", esp_err_to_name(err));
return;
}
err = esp_lcd_touch_new_i2c_cst816s(tp_io_handle, &tp_cfg, &touch_handle);
if (err != ESP_OK) {
ESP_LOGE(LCD_TAG, "Failed to create touch handle: %s", esp_err_to_name(err));
return;
}
ESP_LOGI(LCD_TAG, "Touch controller initialized successfully");
}
// 初始化LVGL显示和触摸
void lvgl_lcd_init(){
const lvgl_port_cfg_t lvgl_cfg = {
.task_priority = 4,
.task_stack = 8192,
.task_affinity = -1,
.task_max_sleep_ms = 500,
.timer_period_ms = 5
};
lvgl_port_init(&lvgl_cfg);
#define LVGL_DRAW_BUF_LINES 30
size_t buffer_size = LCD_WID * LVGL_DRAW_BUF_LINES;
ESP_LOGI(LCD_TAG, "LVGL buffer size: %d bytes (W: %d, Lines: %d)",
buffer_size * 2, LCD_WID, LVGL_DRAW_BUF_LINES);
const lvgl_port_display_cfg_t disp_cfg = {
.io_handle = io_handle,
.panel_handle = panel_handle,
.buffer_size = buffer_size,
.double_buffer = true,
.hres = LCD_WID,
.vres = LCD_HIGH,
.monochrome = false,// 单色显示
.rotation = {
.swap_xy = false,// 交换XY轴
.mirror_x = false,// 水平镜像
.mirror_y = false,// 垂直镜像
},
.flags = {
.buff_dma = true,// 使用DMA传输显示缓冲区
}
};
disp_handle = lvgl_port_add_disp(&disp_cfg);
if (touch_handle != NULL) {
lvgl_port_touch_cfg_t touch_cgf = {
.disp = disp_handle,
.handle = touch_handle,
};
lvgl_port_add_touch(&touch_cgf);
ESP_LOGI(LCD_TAG, "Touch controller added to LVGL");
} else {
ESP_LOGE(LCD_TAG, "Touch handle is NULL, skipping touch initialization");
}
}
void get_touch(uint16_t* touchx,uint16_t* touchy){
if (touch_handle == NULL) {
ESP_LOGE(LCD_TAG, "Touch handle is NULL, cannot get touch data");
*touchx = 0;
*touchy = 0;
return;
}
uint8_t max = 1;
max = touch_handle->data.points;
*touchx = touch_handle->data.coords[0].x;
*touchy = touch_handle->data.coords[0].y;
printf("%x\n",max);
}