Files
iot-bedroom-environment-con…/components/lvgl_st7735s_use/lvgl_st7735s_use.c
Wang Beihong a0febb1e5b feat: 智能家居控制系统 v1.0 初始版本
- 环境监测:温湿度/光照/空气质量传感器采集
- 智能控制:时间段/降温/通风三种自动模式
- 闹钟系统:3个闹钟+温和唤醒功能
- 远程控制:MQTT双向通信
- 本地显示:LVGL图形界面
- 双MCU架构,FreeRTOS 10任务并行
- 完整的1250行README文档
2026-02-07 23:04:28 +08:00

237 lines
8.7 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 <stdio.h>
#include "lvgl_st7735s_use.h"
#include "driver/gpio.h"
#include "driver/spi_master.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_lcd_panel_io.h"
#include "esp_lcd_panel_vendor.h"
#include "esp_lcd_panel_ops.h"
#include "esp_lvgl_port.h" // 包含LVGL端口头文件用于LVGL与ESP硬件的接口
#include "ui_display.h" // 添加新UI界面的头文件
static const char *TAG = "lvgl_st7735s_use"; // 用于日志输出的标签,便于调试时识别日志来源
/* LCD IO和面板句柄 */
// lcd_io: LCD面板IO句柄用于与LCD进行通信
// lcd_panel: LCD面板句柄用于控制LCD的各种操作
static esp_lcd_panel_io_handle_t lcd_io = NULL;
static esp_lcd_panel_handle_t lcd_panel = NULL;
/* LVGL显示和触摸 */
// lvgl_disp: LVGL显示设备句柄用于LVGL库与显示设备的交互
static lv_display_t *lvgl_disp = NULL;
/**
* @brief 初始化LCD硬件和SPI接口
*
* 该函数负责初始化LCD所需的GPIO、SPI总线并配置LCD面板
* 包括背光控制、SPI总线配置、面板IO配置和面板驱动安装
*
* @return esp_err_t 初始化结果ESP_OK表示成功
*/
static esp_err_t app_lcd_init(void)
{
esp_err_t ret = ESP_OK;
/* LCD背光配置 */
// 配置背光GPIO为输出模式用于控制LCD的背光开关
gpio_config_t bk_gpio_config = {
.mode = GPIO_MODE_OUTPUT, // 设置GPIO为输出模式
.pin_bit_mask = 1ULL << EXAMPLE_LCD_GPIO_BL // 设置背光GPIO引脚
};
ESP_ERROR_CHECK(gpio_config(&bk_gpio_config)); // 应用GPIO配置并检查错误
/* LCD初始化 */
ESP_LOGD(TAG, "初始化SPI总线"); // 输出调试日志
// 配置SPI总线参数包括时钟、数据线和最大传输大小
const spi_bus_config_t buscfg = {
.sclk_io_num = EXAMPLE_LCD_GPIO_SCLK, // SPI时钟引脚
.mosi_io_num = EXAMPLE_LCD_GPIO_MOSI, // SPI主输出从输入引脚
.miso_io_num = GPIO_NUM_NC, // 未使用MISO引脚
.quadwp_io_num = GPIO_NUM_NC, // 未使用WP引脚
.quadhd_io_num = GPIO_NUM_NC, // 未使用HD引脚
.max_transfer_sz = EXAMPLE_LCD_H_RES * EXAMPLE_LCD_DRAW_BUFF_HEIGHT * sizeof(uint16_t), // 最大传输大小
};
// 初始化SPI总线使用DMA自动分配通道
ESP_RETURN_ON_ERROR(spi_bus_initialize(EXAMPLE_LCD_SPI_NUM, &buscfg, SPI_DMA_CH_AUTO), TAG, "SPI初始化失败");
ESP_LOGD(TAG, "安装面板IO");
// 配置LCD面板IO的SPI参数
const esp_lcd_panel_io_spi_config_t io_config = {
.dc_gpio_num = EXAMPLE_LCD_GPIO_DC, // 数据/命令选择引脚
.cs_gpio_num = EXAMPLE_LCD_GPIO_CS, // 片选引脚
.pclk_hz = EXAMPLE_LCD_PIXEL_CLK_HZ, // 像素时钟频率
.lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS, // 命令位数
.lcd_param_bits = EXAMPLE_LCD_PARAM_BITS, // 参数位数
.spi_mode = 3, // SPI模式
.trans_queue_depth = 10, // 传输队列深度
};
// 创建LCD面板IO用于SPI通信
ESP_GOTO_ON_ERROR(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)EXAMPLE_LCD_SPI_NUM, &io_config, &lcd_io), err, TAG, "创建面板IO失败");
ESP_LOGD(TAG, "安装LCD驱动");
// 配置LCD面板设备参数
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = EXAMPLE_LCD_GPIO_RST, // 复位引脚
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(6, 0, 0)
.rgb_endian = LCD_RGB_ENDIAN_RGB, // RGB字节序旧版本
#else
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR, // RGB元素顺序新版本
#endif
.bits_per_pixel = EXAMPLE_LCD_BITS_PER_PIXEL, // 每像素位数
};
// 创建ST7789 LCD面板驱动
ESP_GOTO_ON_ERROR(esp_lcd_new_panel_st7789(lcd_io, &panel_config, &lcd_panel), err, TAG, "创建面板失败");
// 复位LCD面板
esp_lcd_panel_reset(lcd_panel);
// 初始化LCD面板
esp_lcd_panel_init(lcd_panel);
// 设置显示窗口,确保使用正确的分辨率(偏移)
esp_lcd_panel_set_gap(lcd_panel, 1, 26);
// 反转颜色
esp_lcd_panel_invert_color(lcd_panel, true);
// 打开LCD显示
esp_lcd_panel_disp_on_off(lcd_panel, true);
/* 打开LCD背光 */
ESP_ERROR_CHECK(gpio_set_level(EXAMPLE_LCD_GPIO_BL, EXAMPLE_LCD_BL_ON_LEVEL));
return ret;
// 错误处理标签,用于清理资源
err:
if (lcd_panel) {
esp_lcd_panel_del(lcd_panel); // 删除面板
}
if (lcd_io) {
esp_lcd_panel_io_del(lcd_io); // 删除面板IO
}
spi_bus_free(EXAMPLE_LCD_SPI_NUM); // 释放SPI总线资源
return ret;
}
/**
* @brief 初始化LVGL图形库
*
* 该函数负责初始化LVGL库并配置显示设备
* 包括LVGL任务配置、显示缓冲区配置和旋转设置
*
* @return esp_err_t 初始化结果ESP_OK表示成功
*/
static esp_err_t app_lvgl_init(void)
{
/* 初始化LVGL */
// 配置LVGL任务参数
const lvgl_port_cfg_t lvgl_cfg = {
.task_priority = 4, /* LVGL任务优先级数值越高优先级越高 */
.task_stack = 4096, /* LVGL任务堆栈大小单位为字节 */
.task_affinity = -1, /* LVGL任务绑定核心-1表示不绑定特定核心 */
.task_max_sleep_ms = 500, /* LVGL任务最大睡眠时间单位为毫秒 */
.timer_period_ms = 5 /* LVGL定时器周期单位为毫秒用于处理动画和输入 */
};
// 初始化LVGL端口
ESP_RETURN_ON_ERROR(lvgl_port_init(&lvgl_cfg), TAG, "LVGL端口初始化失败");
/* 添加LCD屏幕 */
ESP_LOGD(TAG, "添加LCD屏幕");
// 配置LVGL显示设备参数
const lvgl_port_display_cfg_t disp_cfg = {
.io_handle = lcd_io, // LCD面板IO句柄
.panel_handle = lcd_panel, // LCD面板句柄
.buffer_size = EXAMPLE_LCD_H_RES * EXAMPLE_LCD_DRAW_BUFF_HEIGHT, // 缓冲区大小
.double_buffer = EXAMPLE_LCD_DRAW_BUFF_DOUBLE, // 是否使用双缓冲
.hres = EXAMPLE_LCD_H_RES, // 水平分辨率
.vres = EXAMPLE_LCD_V_RES, // 垂直分辨率
.monochrome = false, // 是否为单色显示
#if LVGL_VERSION_MAJOR >= 9
.color_format = LV_COLOR_FORMAT_RGB565, // 颜色格式LVGL v9及以上
#endif
.rotation = { // 旋转设置
.swap_xy = 1, // 交换X和Y轴以实现横向显示
.mirror_x = 1, // 是否水平镜像
.mirror_y = 0, // 是否垂直镜像
},
.flags = { // 标志位
.buff_dma = true, // 是否使用DMA缓冲区
#if LVGL_VERSION_MAJOR >= 9
.swap_bytes = false, // 是否交换字节序LVGL v9及以上
#endif
}
};
// 添加LVGL显示设备
lvgl_disp = lvgl_port_add_disp(&disp_cfg);
return ESP_OK;
}
/**
* @brief 创建并显示LVGL主界面
*
* 该函数负责创建LVGL的用户界面元素包括图像、标签和按钮
* 并设置它们的位置和属性
*/
static void app_main_display(void)
{
// 获取当前活动屏幕对象
lv_obj_t *scr = lv_scr_act();
/* 任务锁定 */
// 锁定LVGL任务防止在创建UI对象时被中断
lvgl_port_lock(0);
/* 设置屏幕背景为黑色 */
lv_obj_set_style_bg_color(scr, lv_color_white(), 0);
lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0);
/* 创建标签 */
// 创建标签对象
lv_obj_t *label = lv_label_create(scr);
// 设置标签文本为"ESP32C3-LVGL"
lv_label_set_text(label, "ESP32C3-LVGL1");
// 设置标签文本颜色为白色
lv_obj_set_style_text_color(label, lv_color_black(), 0);
// 设置标签文本字体大小为更小的字体
lv_obj_set_style_text_font(label, &lv_font_unscii_8, 0);
// 设置标签位置在屏幕中心
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
/* 任务解锁 */
// 解锁LVGL任务
lvgl_port_unlock();
}
/**
* @brief 启动LVGL演示程序
*
* 该函数是程序的入口点负责初始化LCD硬件、LVGL库并显示主界面
*/
void start_lvgl_demo(void)
{
/* LCD硬件初始化 */
// 初始化LCD硬件和SPI接口
ESP_ERROR_CHECK(app_lcd_init());
/* LVGL初始化 */
// 初始化LVGL图形库
ESP_ERROR_CHECK(app_lvgl_init());
/* 显示LVGL对象 */
// 创建并显示LVGL主界面
// app_main_display();
/* 显示LVGL对象 - 使用新的UI界面初始化函数 */
ui_display_init();
}