2. 开发环境搭建:从MCU到模拟器,把LVGL跑起来
说实话,很多初学者在LVGL上栽跟头,不是因为库本身难,而是环境没搭好。我见过有人花了一周时间在STM32上折腾LVGL,结果发现是时钟配置错了。所以这一章,咱们就把环境搭建这件事彻底讲透。
2.1 两种开发路径,你该怎么选?
LVGL的开发环境,说白了就两条路:MCU实机移植和PC模拟器。我个人的建议是——先模拟器,后MCU。为什么?
- 模拟器:编译快、调试方便、不用反复烧录。适合UI原型验证和功能开发。
- MCU:贴近真实硬件,涉及驱动、内存、帧率优化。适合产品化阶段。
我自己做项目时,通常先在模拟器上把界面逻辑调通,再移植到STM32上做性能调优。这样效率最高。
核心原则:UI逻辑在模拟器上开发,硬件适配在MCU上完成。两者互补,不是替代关系。
2.2 基于模拟器的LVGL环境搭建(PC模拟器)
模拟器我用得最多的是SDL2 + LVGL的方案,跨平台、稳定、调试方便。下面以Windows + VS Code为例,带你走一遍。
2.2.1 准备工作
- 安装 VS Code(或CLion、VS Studio)
- 安装 CMake(3.16以上)
- 安装 MinGW-w64 或 MSVC 编译器
- 下载 SDL2 开发库(Windows版)
2.2.2 克隆LVGL官方模拟器项目
git clone https://github.com/lvgl/lv_port_pc_eclipse.git
cd lv_port_pc_eclipse
这个项目已经帮你配好了LVGL + SDL2的基础框架。你只需要改几个路径就行。
2.2.3 配置CMakeLists.txt
找到 CMakeLists.txt,设置SDL2的路径:
set(SDL2_DIR "C:/SDL2-2.26.3/cmake")
find_package(SDL2 REQUIRED)
2.2.4 编译运行
mkdir build && cd build
cmake ..
make
./lv_sim
如果一切顺利,你会看到一个LVGL的演示界面弹出来。嗯,到这里,你的模拟器环境就搭好了。
小技巧:如果编译报SDL2找不到,检查一下环境变量。我遇到过好几次,都是路径写错了。
2.3 基于MCU的LVGL移植(以STM32为例)
模拟器跑通了,接下来就是真刀真枪的MCU移植。我以STM32F429 + 480x272 RGB屏为例,这是最常见的组合。
2.3.1 移植的核心步骤
- 准备裸机工程:用STM32CubeMX生成一个基础工程,开启LTDC、DMA2D、SDRAM(如果外挂)。
- 下载LVGL源码:从GitHub拉取
lvgl和lv_drivers。 - 配置lv_conf.h:这是LVGL的“总开关”。
- 实现显示驱动:把画点、刷屏函数挂到LVGL上。
- 实现输入驱动:触摸屏或按键。
- 配置心跳和内存:提供系统时钟和内存分配。
2.3.2 lv_conf.h 关键配置
#define LV_COLOR_DEPTH 16
#define LV_HOR_RES_MAX 480
#define LV_VER_RES_MAX 272
#define LV_DPI_DEF 100
#define LV_MEM_CUSTOM 0
#define LV_USE_DMA2D 1
这里要注意:LV_USE_DMA2D 一定要开。STM32F4系列有硬件2D加速,不开就浪费了。我早期项目没开这个,帧率只有15fps,开了之后直接飙到45fps。
2.3.3 显示驱动实现(简化版)
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
// 将color_p数据通过LTDC刷到屏幕区域
HAL_LTDC_Color_Fill(&hltdc, area->x1, area->y1, area->x2, area->y2, (uint32_t)color_p);
lv_disp_flush_ready(disp_drv);
}
这个函数是LVGL和硬件的桥梁。每次LVGL需要刷新屏幕时,就会调用它。
2.3.4 触摸驱动实现
static void touch_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
// 读取触摸IC(如FT5x06)的坐标
data->point.x = touch_x;
data->point.y = touch_y;
data->state = touch_pressed ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
}
我曾经踩过的坑:触摸坐标和屏幕坐标方向不一致。比如触摸X对应屏幕Y。记得做坐标映射,否则点哪里都不对。
2.4 工程结构解析
不管你是用模拟器还是MCU,LVGL的工程结构都差不多。我画了一张图,帮你理清关系。
2.5 工程目录结构(典型)
一个标准的LVGL工程,目录结构大致如下:
project/
├── lvgl/ # LVGL核心源码
│ ├── src/ # 核心库
│ ├── lv_conf.h # 配置文件
│ └── lvgl.h # 主头文件
├── lv_drivers/ # 官方驱动
│ ├── display/ # 显示驱动
│ ├── indev/ # 输入驱动
│ └── lv_drv_conf.h # 驱动配置
├── main.c # 主函数
├── CMakeLists.txt # 编译配置
└── README.md
这个结构很清晰。你只需要关注 lv_conf.h 和 lv_drv_conf.h 两个配置文件,以及自己写的 main.c。
2.6 常见问题与避坑
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 编译报错:lv_conf.h not found | 路径未包含 | 在CMake或IDE中添加 lvgl/ 路径 |
| 屏幕花屏 | LTDC时序不对 | 检查HBP、HFP、VBP、VFP参数 |
| 触摸无反应 | I2C地址或中断配置错误 | 用逻辑分析仪抓I2C波形 |
| 帧率低 | 未开启DMA2D | 设置 LV_USE_DMA2D = 1 |
我曾经踩过的坑:有一次移植LVGL到STM32F429,屏幕一直闪。查了两天,最后发现是SDRAM的时序配置不对,导致LVGL的缓冲区数据被破坏。所以,先确保SDRAM读写稳定,再跑LVGL。
2.7 小结
这一章我们做了三件事:
- 在PC上搭建了LVGL模拟器环境,方便快速开发UI。
- 在STM32上完成了LVGL的移植,包括显示和触摸驱动。
- 解析了LVGL的工程结构,让你知道每个文件是干什么的。
环境搭好了,下一步就是真正开始写UI了。别急,先把今天的内容消化掉。如果你在搭建过程中遇到问题,回头看看上面的表格,大部分坑我都帮你踩过了。