附录07 LVGL
约 1855 字大约 6 分钟
2026-05-25
1 概述
LVGL(Light and Versatile Graphics Library)是一款免费开源的嵌入式图形库,专为资源受限的 MCU(微控制器)设计,可在 32KB Flash + 8KB RAM 以上的硬件上运行流畅的 GUI 界面。它采用 C 语言编写,提供完整的 UI 组件集(按钮、标签、图表、列表等),支持 GPU 加速、多显示器和多种输入设备。
在 Nordic nRF 系列芯片的蓝牙键盘项目中,LVGL 常被用于驱动 OLED / TFT 屏幕,显示电池电量、连接状态、按键映射等信息。
2 官方地址
- 官网:https://lvgl.io/
- GitHub 仓库:https://github.com/lvgl/lvgl
- 官方文档:https://docs.lvgl.io/
- LVGL 在线演示:https://lvgl.io/demos
3 核心技术特点
轻量高效
- 极低资源占用:最小配置仅需 32KB Flash + 8KB RAM,适合 Cortex-M 系列 MCU。
- 自定义显存大小:可根据屏幕分辨率和颜色深度灵活配置,例如 128×64 单色屏仅需 1KB 显存。
丰富的 UI 组件
- 内置 30+ 标准控件:按钮(
lv_button)、标签(lv_label)、图表(lv_chart)、列表(lv_list)、滑块(lv_slider)、开关(lv_switch)、键盘(lv_keyboard)、图片(lv_image)等。 - 灵活的布局系统:Flex 布局和 Grid 布局,轻松实现复杂界面排版。
- 主题与样式系统:支持 CSS-like 的样式定义,可全局切换主题(Material、Mono 等)。
跨平台与高可移植性
- 纯 C 实现(C99),无外部依赖,只需提供
lv_tick_inc(心跳)和lv_display_flush(刷新回调)即可运行。 - 支持多种颜色深度:1/8/16/24 bit 色深,适配单色屏到真彩屏。
- 支持多种输入设备:触摸屏、编码器、按键、鼠标、手势等。
GPU 加速与高级特性
- 支持 GPU 加速(NXP PXP、DMA2D、STM32 Chrom-ART 等),渲染性能大幅提升。
- 图层与透明度:支持多层叠加、Alpha 混合、抗锯齿字体。
- 动画系统:内置动画引擎,支持控件位置、大小、透明度等属性的平滑过渡。
- 文件系统集成:支持从外部 Flash / SD 卡加载图片(PNG、JPG、GIF、BMP)和字库。
活跃的社区与生态
- 在 GitHub 拥有 18k+ Star,是嵌入式 GUI 领域最热门的开源项目之一。
- 官方提供 SquareLine Studio 和 LVGL Editor 等 GUI 设计工具,支持拖拽式界面设计并导出 C 代码。
4 LVGL 基本使用规则
4.1 核心初始化流程
使用 LVGL 的典型初始化步骤如下:
// ① 初始化 LVGL 内核
lv_init();
// ② 初始化显示驱动并注册
lv_display_t *disp = lv_display_create(128, 64); // 创建 128x64 显示对象
lv_display_set_flush_cb(disp, my_flush_cb); // 设置刷新回调
lv_display_set_color_format(disp, LV_COLOR_FORMAT_RGB565);
// ③ 设置显存
static uint8_t buf[128 * 64 * 2]; // 显存缓冲区
lv_display_set_buffers(disp, buf, NULL, sizeof(buf), LV_DISPLAY_RENDER_MODE_PARTIAL);
// ④ 初始化输入设备(可选)
lv_indev_t *indev = lv_indev_create();
lv_indev_set_type(indev, LV_INDEV_TYPE_ENCODER); // 编码器输入
lv_indev_set_read_cb(indev, my_encoder_read_cb);
// ⑤ 提供心跳
lv_tick_set_cb(my_tick_get_cb); // 注册时钟源
// ⑥ 创建 UI
lv_obj_t *label = lv_label_create(lv_screen_active());
lv_label_set_text(label, "Hello LVGL");
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
// ⑦ 主循环
while (1) {
lv_timer_handler(); // LVGL 定时器处理(每 5ms 调用一次)
k_msleep(5); // 或使用 RTOS 延时
}4.2 对象层级(Object Tree)
LVGL 中所有 UI 元素都是 lv_obj_t 对象,采用父子层级结构:
- Screen(屏幕):最顶层容器,通过
lv_screen_active()获取当前活动屏幕。 - Parent(父对象):子对象随父对象移动、隐藏或删除。
- Child(子对象):通过
lv_xxx_create(parent)创建并挂载到父对象。
lv_obj_t *screen = lv_screen_active();
lv_obj_t *btn = lv_button_create(screen); // 创建按钮,父对象为 screen
lv_obj_set_size(btn, 100, 40); // 设置大小
lv_obj_set_pos(btn, 10, 10); // 设置位置
lv_obj_t *label = lv_label_create(btn); // 创建标签,父对象为 button
lv_label_set_text(label, "Click");
lv_obj_center(label); // 在父对象中居中4.3 事件系统
LVGL 提供通用的事件回调机制,所有控件都支持:
// 点击事件
lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL);
static void btn_event_cb(lv_event_t *e) {
lv_event_code_t code = lv_event_get_code(e);
if (code == LV_EVENT_CLICKED) {
lv_label_set_text(label, "Pressed");
}
}常用事件类型:LV_EVENT_CLICKED、LV_EVENT_PRESSED、LV_EVENT_VALUE_CHANGED、LV_EVENT_SCROLL 等。
4.4 布局系统
LVGL 提供 Flex 和 Grid 两种布局方式,声明式地自动排列子控件:
// Flex 布局示例:水平等间距排列
lv_obj_set_flex_flow(container, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(container, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);4.5 定时器
LVGL 内置定时器机制,用于周期性任务(更新图表、轮询状态等):
lv_timer_t *timer = lv_timer_create(my_timer_cb, 1000, NULL); // 每 1000ms 执行一次
static void my_timer_cb(lv_timer_t *timer) {
// 更新电池电量显示
lv_label_set_text_fmt(battery_label, "%d%%", get_battery_level());
}4.6 内存管理
- LVGL 默认使用标准
malloc/free,可通过lv_conf.h中LV_MEM_SIZE配置内存池大小(如 32KB)。 - 建议在嵌入式项目中启用自定义内存池,避免堆碎片化:
#define LV_USE_MEM_CUSTOM 1
#define LV_MEM_CUSTOM_ALLOC my_malloc
#define LV_MEM_CUSTOM_FREE my_free5 NCS / Zephyr 官方驱动与组件集成
Nordic 的 nRF Connect SDK(NCS) 基于 Zephyr RTOS,内置了 LVGL 模块,提供了完整的显示驱动和输入设备支持。
5.1 在 NCS 中启用 LVGL
在项目配置(prj.conf 或 Kconfig)中启用 LVGL:
# 启用 LVGL 图形库
CONFIG_LVGL=y
# 配置内存(单位:字节)
CONFIG_LVGL_MEM_SIZE=32768
# 配置显存大小
CONFIG_LVGL_BUF_ALLOC_DYNAMIC=y
CONFIG_LVGL_BUF_SIZE=5120
# 可选:启用日志
CONFIG_LVGL_LOG_LEVEL_INF=y或者在 sysbuild 配置中添加:
# 启用 LVGL 模块
SB_CONFIG_LVGL=y5.2 显示驱动集成
Zephyr 提供标准的 display 驱动框架,LVGL 可通过 lvgl 模块直接对接。以 SSD1306 OLED 为例:
① 设备树配置(app.overlay 或 板级 .dts 文件)
&i2c0 {
status = "okay";
ssd1306: ssd1306@3c {
compatible = "solomon,ssd1306fb";
reg = <0x3c>;
width = <128>;
height = <64>;
segment-offset = <0>;
page-offset = <0>;
display-offset = <0>;
};
};② NCS LVGL 与 display 设备绑定
#include <zephyr/kernel.h>
#include <zephyr/display.h>
#include <zephyr/lvgl.h>
void main(void) {
// 获取 display 设备
const struct device *display = DEVICE_DT_GET(DT_NODELABEL(ssd1306));
if (!device_is_ready(display)) {
printk("Display device not ready\n");
return;
}
// NCS LVGL 模块自动调用 display 驱动的 flush 回调
// 无需手动设置 lv_display_set_flush_cb
// 创建 UI...
lv_obj_t *label = lv_label_create(lv_screen_active());
lv_label_set_text(label, "Hello from NCS!");
// 主循环
while (1) {
lv_timer_handler();
k_msleep(5);
}
}③ 关键 Kconfig 配置
Zephyr 的 display 驱动与 LVGL 集成时,需确保启用:
CONFIG_DISPLAY=y
CONFIG_LVGL_USE_DISPLAY_DEV=y # 使用 Zephyr display 设备5.3 输入设备集成
NCS 支持将 Zephyr 的输入子系统(input)绑定到 LVGL 的输入设备:
CONFIG_INPUT=y
CONFIG_LVGL_INPUT_DEVICE=y # LVGL 使用 Zephyr 输入设备常见的输入设备配置:
编码器(旋转编码器)
/ {
encoder: encoder {
compatible = "gpio-keys";
up: up {
gpios = <&gpio0 11 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
};
down: down {
gpios = <&gpio0 12 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
};
};
};按键
/ {
buttons {
compatible = "gpio-keys";
btn0: btn_0 {
gpios = <&gpio0 13 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
zephyr,code = <INPUT_KEY_ENTER>;
};
};
};5.4 Nordic 官方 Display 驱动支持列表
NCS 中已集成以下常用显示驱动,可与 LVGL 开箱即用:
| 驱动芯片 | 兼容字串 | 接口 | 典型分辨率 |
|---|---|---|---|
| SSD1306 | solomon,ssd1306fb | I2C / SPI | 128×32, 128×64 |
| SSD1327 | solomon,ssd1327fb | SPI | 128×128 |
| ST7789V | sitronix,st7789v | SPI | 240×240, 320×240 |
| ST7735S | sitronix,st7735s | SPI | 128×160 |
| GC9A01 | galaxycore,gc9a01 | SPI | 240×240(圆形) |
| ILI9341 | ilitek,ili9341 | SPI | 320×240 |
5.5 LVGL 配置定制(lv_conf.h 覆盖)
NCS 提供了默认的 lv_conf.h,可通过 Kconfig 覆盖关键配置项:
# 颜色深度
CONFIG_LVGL_COLOR_DEPTH_16=y
# 主题
CONFIG_LVGL_USE_THEME_DEFAULT=y
# 字体
CONFIG_LVGL_FONT_MONTSERRAT_14=y
# 性能优化
CONFIG_LVGL_SHADOW_CACHE_SIZE=0 # 禁用阴影缓存以节省 RAM
CONFIG_LVGL_IMG_CACHE_DEF_SIZE=0 # 禁用图片缓存6 总结
LVGL 是嵌入式 GUI 开发的首选方案之一,在 NCS / Zephyr 生态中享有一流的集成支持。对于蓝牙键盘项目,利用 LVGL + NCS display 驱动,可以在极低的硬件成本下实现清晰直观的屏幕显示界面,无需从零开发显示驱动。
核心要点:
- 使用 Zephyr 设备树(DTS)描述硬件,LVGL 通过 display 框架自动对接
- 通过 Kconfig 配置裁剪 LVGL 功能,控制资源占用
- 利用 LVGL 的 Flex / Grid 布局和事件系统,快速构建交互式界面
