一、前言
随着物联网设备和智能终端的发展,越来越多的嵌入式设备开始追求 精美的 GUI 界面。
但 MCU 资源有限,如何在几百 KB 的 Flash 和几十 KB 的 RAM 上跑出流畅的界面?
传统方案:
-
Qt、GTK+ → 功能强大,但太重,MCU 带不动
-
TouchGFX → 功能不错,但封闭,移植灵活性差
-
LVGL → 轻量 + 高效 + 开源 + 社区活跃,直接碾压同类方案
结论:
如果你要在 STM32、ESP32、NXP、Linux 上做 GUI,LVGL 是首选!
二、LVGL 简介
1. 什么是 LVGL?
LVGL(Light and Versatile Graphics Library) 是一款开源的 轻量级嵌入式 GUI 框架,主要用于低功耗 MCU、RTOS 和小型 Linux 系统。
2. LVGL 特点
特点 | 说明 |
---|---|
轻量高效 | 在 STM32F4(180MHz)+ 64KB RAM 上,依然能实现 60FPS 流畅动画 |
跨平台 | 支持 MCU、RTOS、Linux、Windows、ESP32、Raspberry Pi |
功能强大 | 内置按钮、滑条、表格、图表、动画、触控支持 |
高度可定制 | 开关各种功能、颜色深度、缓存策略 |
生态完善 | SquareLine Studio、LVGL Simulator、丰富 Demo |
三、LVGL 架构原理
一句话总结:
LVGL 提供 UI 组件和渲染引擎,但显示驱动和触摸驱动需要你移植。
1. 系统架构图
┌──────────────────────────────┐
│ 应用层 (UI 应用逻辑) │
└───────────▲──────────────────┘
│
┌───────────┴──────────────┐
│ LVGL 核心库 │
│ • 界面组件(按钮、列表) │
│ • 样式引擎(CSS-like) │
│ • 动画管理 │
│ • 事件驱动 │
└───────────▲──────────────┘
│
┌───────────┴──────────────┐
│ 显示驱动层 + 输入驱动层 │
│ • TFT/LCD 显示刷新 │
│ • 触摸/按键输入 │
└───────────▲──────────────┘
│
┌───────────┴──────────────┐
│ 硬件(MCU + LCD) │
└──────────────────────────┘
四、开发环境准备
项目 | 选择 |
---|---|
硬件 | STM32F4/F7/H7、ESP32、NXP、RK 系列 |
IDE | STM32CubeIDE / Keil / VSCode / PlatformIO |
操作系统 | 裸机 / FreeRTOS / RT-Thread |
屏幕 | TFT LCD / OLED / IPS / SPI 屏 |
LVGL 版本 | 最新 v9.x 推荐 |
下载 LVGL:
五、LVGL 移植步骤(以 STM32 + FreeRTOS 为例)
1. 添加 LVGL 源码
-
将
lvgl
文件夹拷贝到工程目录 -
在工程中添加头文件路径:
#include "lvgl.h"
2. 配置 LVGL
-
修改
lv_conf.h
#define LV_COLOR_DEPTH 16 // RGB565
#define LV_MEM_SIZE (64U * 1024U)
#define LV_TICK_CUSTOM 1
3. 移植显示驱动
实现 disp_flush()
回调:
void disp_flush(lv_disp_drv_t * disp, const lv_area_t * area, lv_color_t * color_p) {
lcd_draw_area(area->x1, area->y1, area->x2, area->y2, color_p);
lv_disp_flush_ready(disp);
}
4. 移植触摸驱动
实现 touchpad_read()
:
bool touchpad_read(lv_indev_drv_t * indev, lv_indev_data_t * data) {
if(touch_is_pressed()) {
data->point.x = get_touch_x();
data->point.y = get_touch_y();
data->state = LV_INDEV_STATE_PRESSED;
} else {
data->state = LV_INDEV_STATE_RELEASED;
}
return false;
}
5. 初始化 LVGL
lv_init();
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.flush_cb = disp_flush;
lv_disp_drv_register(&disp_drv);
lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.read_cb = touchpad_read;
lv_indev_drv_register(&indev_drv);
6. 创建 GUI 任务
void gui_task(void *pvParameter) {
while(1) {
lv_timer_handler();
vTaskDelay(pdMS_TO_TICKS(5));
}
}
六、创建第一个 GUI 界面
lv_obj_t * btn = lv_btn_create(lv_scr_act());
lv_obj_center(btn);
lv_obj_t * label = lv_label_create(btn);
lv_label_set_text(label, "点我试试!");
lv_obj_center(label);
运行效果:
七、性能优化技巧
技巧 | 描述 |
---|---|
启用 DMA2D/GPU | 利用硬件加速,降低 CPU 占用 |
双缓冲 | 使用两个显存缓冲区,减少闪烁 |
降低刷新率 | 合理设置 LV_DISP_DEF_REFR_PERIOD |
精简组件 | 关闭不用的控件,减少内存占用 |
八、LVGL 生态工具
工具 | 功能 |
---|---|
SquareLine Studio | 所见即所得的 GUI 设计器 |
LVGL Simulator | 在 PC 上调试 UI 界面 |
官方 Demo | 各类控件示例,快速上手 |
九、常见问题与踩坑记录
问题 | 解决方案 |
---|---|
屏幕不显示 | 检查 disp_flush() 实现 |
触摸无反应 | 确认 touchpad_read() 返回正确坐标 |
FPS 太低 | 开启 DMA2D,优化缓冲区大小 |
内存溢出 | 增加 LV_MEM_SIZE 或关闭不必要功能 |
十、总结
-
LVGL 是嵌入式 GUI 的首选:轻量、高效、功能丰富
-
移植成本低,支持 MCU、RTOS、Linux
-
配合 SquareLine Studio,可以快速开发炫酷界面
-
后续可以继续探索:
-
LVGL + FreeRTOS 动画优化
-
LVGL + SquareLine Studio 的高效 GUI 工作流
-
LVGL 在 ESP32、树莓派上的跨平台应用
-
一句话总结:
LVGL = 嵌入式 GUI 界面开发的开源神器
学会它,你的项目 UI 将从“黑白简陋”跃升为“丝滑炫酷”!