第一章 LVGL概述与环境搭建
1.1 LVGL是什么
LVGL,全称Light and Versatile Graphics Library,是一个开源的嵌入式图形库。说白了,它就是一套专门给资源受限的嵌入式设备用的UI框架。你想想看,一个只有几百KB内存的MCU,也能跑出流畅的动画和漂亮的界面,这就是LVGL的厉害之处。
我最早接触LVGL是在2019年,当时一个智能家居项目需要做触摸屏界面。传统的方案要么太臃肿,要么太简陋。LVGL正好卡在中间——功能丰富,但资源消耗又控制得很好。
LVGL的核心特性包括:
- 轻量级:最低配置只需要16KB RAM和64KB Flash
- 丰富的控件:按钮、滑块、图表、列表等30+内置控件
- 硬件加速:支持帧缓冲和DMA2D加速
- 多语言支持:UTF-8编码,轻松支持中文
- 动画系统:内置缓动函数,动画流畅自然
- 输入设备抽象:触摸、按键、编码器都能用
一句话总结:LVGL就是嵌入式界的Qt,但比Qt轻得多。
1.2 为什么选择LVGL
市面上嵌入式GUI方案不少,比如emWin、TouchGFX、LittlevGL(LVGL的前身)。为什么我推荐LVGL?
先看一个对比:
| 特性 | LVGL | emWin | TouchGFX |
|---|---|---|---|
| 开源免费 | ✅ MIT协议 | ❌ 商业授权 | ❌ 商业授权 |
| 最低RAM需求 | 16KB | 32KB | 64KB |
| 内置控件数 | 30+ | 20+ | 25+ |
| 社区活跃度 | 极高 | 低 | 中 |
| 学习曲线 | 平缓 | 中等 | 陡峭 |
我在项目中遇到过几次选型失误。有一次选了某商业GUI库,结果芯片涨价,项目预算被砍,授权费成了大问题。从那以后,我选方案第一原则就是——开源优先。LVGL的MIT协议意味着你可以随意商用,没有任何后顾之忧。
另外,LVGL的社区非常活跃。GitHub上3万+星标,遇到问题基本都能搜到答案。你想想看,一个闭源库出了问题,你只能等厂商回复;而LVGL的问题,可能当天就有人帮你解决了。
我的建议:如果你的项目需要快速迭代、成本敏感、团队规模不大,LVGL是首选。如果项目对实时性要求极高(比如汽车仪表盘),可以考虑TouchGFX,但代价是硬件成本更高。
1.3 LVGL源码获取
获取LVGL源码很简单,我一般用两种方式:
- GitHub直接下载:访问
https://github.com/lvgl/lvgl,选择Release版本下载 - Git克隆:
git clone https://github.com/lvgl/lvgl.git
这里有个坑,我曾经踩过——不要直接拉master分支。master分支是开发版,可能有不稳定的API。我建议拉最新的稳定版tag,比如v8.3.x或v9.x。
LVGL的源码结构大致如下:
lvgl/
├── src/ # 核心源码
│ ├── core/ # 核心对象和事件
│ ├── draw/ # 绘制引擎
│ ├── font/ # 字体处理
│ ├── hal/ # 硬件抽象层
│ ├── misc/ # 工具函数
│ ├── widgets/ # 控件库
│ └── layouts/ # 布局管理
├── examples/ # 示例代码
├── docs/ # 文档
└── lv_conf_template.h # 配置文件模板
注意:lv_conf.h是LVGL的配置文件,必须根据你的硬件资源裁剪。默认配置是为PC模拟器准备的,直接用在MCU上会爆内存。后面我会详细讲怎么配置。
1.4 开发环境搭建
搭建环境分两种情况:MCU和MPU。我分别说一下。
1.4.1 MCU环境搭建
MCU环境我一般用STM32CubeIDE或Keil。以STM32为例,步骤很简单:
- 用STM32CubeMX生成基础工程,配置好时钟和GPIO
- 把LVGL源码复制到工程目录
- 配置lv_conf.h,打开LV_USE_DEMO等宏
- 实现显示驱动和触摸驱动
- 在主循环中调用lv_timer_handler()
显示驱动的核心代码就这几行:
// 显示缓冲区
static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf[LV_HOR_RES_MAX * 10];
// 初始化显示缓冲区
lv_disp_draw_buf_init(&draw_buf, buf, NULL, LV_HOR_RES_MAX * 10);
// 注册显示驱动
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.flush_cb = my_flush_callback;
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register(&disp_drv);
嗯,这里要注意——flush_cb函数里一定要调用lv_disp_flush_ready(),否则画面会卡死。我刚开始做的时候忘了这步,折腾了一下午。
1.4.2 MPU环境搭建
MPU环境就简单多了。我一般用Linux + SDL模拟器,直接在PC上开发调试,最后再移植到目标板。
PC模拟器搭建步骤:
- 安装SDL2库:
sudo apt install libsdl2-dev - 下载LVGL的PC模拟器工程:
git clone https://github.com/lvgl/lv_port_pc_eclipse.git - 用CMake编译:
mkdir build && cd build && cmake .. && make - 运行:
./demo
我个人习惯先在PC上把UI布局和交互逻辑调好,再移植到MCU。这样效率高很多,不用每次烧录看效果。
效率技巧:在PC模拟器上开发时,可以用lvgl的在线字体转换工具生成自定义字体,省去在MCU上调试字体的麻烦。
1.5 LVGL知识体系总览
为了让你对LVGL有个整体认识,我画了张图:
这张图展示了LVGL的层次结构。从下往上,每一层都依赖下一层。你想想看,如果硬件抽象层没写好,上面的控件再漂亮也显示不出来。所以我的建议是——先搞定显示驱动和触摸驱动,再谈UI设计。
1.6 本章小结
这一章我们聊了LVGL是什么、为什么选它、怎么获取源码、以及怎么搭建开发环境。说白了,LVGL就是嵌入式UI开发的一把利器,用好了能大幅提升开发效率。
我个人觉得,LVGL最大的优势不是技术本身,而是它的社区生态。你遇到的大部分问题,别人都遇到过。多逛逛GitHub Issues和论坛,能少走很多弯路。