1. 课程导入

1.1 LVGL到底是什么?

LVGL,全称是Light and Versatile Graphics Library。说白了,它就是一个为嵌入式设备量身打造的图形用户界面库。

我刚开始接触嵌入式GUI时,用的还是最原始的画点画线函数。那时候做个菜单,得自己算坐标、刷缓冲区,一个不小心就花屏。后来遇到LVGL,才觉得「原来嵌入式UI也能这么写」。

LVGL的核心特点,我总结为三点:

  • 轻量:最低配置只需要16KB RAM、64KB Flash,就能跑起来
  • 丰富:内置30+控件,按钮、滑块、图表、键盘……基本覆盖常见需求
  • 开源:MIT协议,商用无压力

一句话总结:LVGL就是嵌入式界的Qt,但比Qt轻得多。

1.2 为什么选择LVGL?

市面上嵌入式GUI方案不少,比如emWin、TouchGFX、LittlevGL(LVGL的前身)。为什么我推荐LVGL?

拿我去年做的一个智能家居中控项目来说。当时需要在Cortex-M4上跑一个带动画的触摸界面,emWin授权费太贵,TouchGFX对硬件要求高。最后选了LVGL,两周就完成了原型。

我整理了一个对比表,你一看就明白:

特性 LVGL emWin TouchGFX
开源协议 MIT(免费) 商业授权(收费) 部分免费
最低RAM 16KB 32KB 64KB
控件数量 30+ 20+ 25+
动画引擎 内置 需额外配置 内置
社区活跃度 高(GitHub 15k+ Star) 低 中

你看,LVGL在资源占用和功能丰富度之间找到了很好的平衡点。而且社区活跃,遇到问题基本都能搜到答案。

我的建议:如果你的项目对成本敏感、硬件资源有限、又需要漂亮的UI,LVGL几乎是首选。

1.3 开发板选型

选开发板这事,我踩过不少坑。刚开始图便宜买了个不带LCD接口的板子,结果飞线飞得想哭。

我个人习惯把开发板分成三类:

  1. 入门级:STM32F4系列 + 3.5寸TFT屏,适合初学者
  2. 进阶级:ESP32-S3 + 带触摸的LCD,适合做物联网项目
  3. 高性能级:i.MX RT系列 + 5寸以上高清屏,适合复杂动画

具体推荐几款我实际用过的:

开发板 主控 RAM Flash 推荐理由
正点原子潘多拉 STM32L475 128KB 512KB 资料全,适合入门
ESP32-S3-DevKitC ESP32-S3 512KB 16MB WiFi/蓝牙,性价比高
野火i.MX RT1021 i.MX RT1021 1MB 8MB 性能强劲,动画流畅

注意:选板子时一定要确认LCD接口类型。我建议选带RGB接口或SPI接口的屏,驱动起来最省事。

1.4 源码获取与目录结构解析

源码获取很简单,直接去LVGL的GitHub仓库:https://github.com/lvgl/lvgl。我习惯用git clone,方便后续更新。

git clone https://github.com/lvgl/lvgl.git
cd lvgl
git checkout v8.3.0  # 建议用稳定版

下载完后,我们来看看目录结构。我第一次打开时也懵了一下,但摸清楚规律后就好办了。

下面这张图是我画的LVGL源码结构图,帮你快速建立全局认知:

LVGL 源码目录结构 lvgl/ (根目录) src/ (核心源码) examples/ (示例) docs/ (文档) tests/ (测试) core/ (核心) widgets/ (控件) draw/ (渲染) hal/ (硬件抽象) misc/ (杂项) font/ (字体) 💡 重点说明 • core/:对象管理、事件、动画核心 • widgets/:按钮、标签、滑块等控件 • hal/:显示屏、触摸屏驱动接口 移植时主要关注 src/hal/ 和 src/core/ 两个目录 examples/ 目录下的代码可以直接参考使用

嗯,这里要注意几个关键目录:

  • src/core/:LVGL的心脏,对象系统、事件处理、动画引擎都在这里
  • src/widgets/:所有控件的实现,你用的按钮、标签、列表都在这
  • src/hal/:硬件抽象层,移植时主要改这里
  • src/draw/:渲染引擎,负责把控件画到屏幕上

我的经验:刚开始不用看所有代码。先看examples/里的demo,跑起来再说。遇到不懂的再回src/里查。

1.5 环境搭建实战

环境搭建其实就三步:

  1. 准备编译器:我习惯用ARM GCC,免费又好用
  2. 配置工程:把LVGL源码加进工程,设置好包含路径
  3. 编写移植层:实现显示屏和触摸屏的驱动接口

这里给一个最简单的main.c框架:

#include "lvgl.h"
#include "lv_port_disp.h"
#include "lv_port_indev.h"

int main(void)
{
    /* 硬件初始化 */
    lv_init();
    
    /* 显示屏移植 */
    lv_port_disp_init();
    
    /* 触摸屏移植 */
    lv_port_indev_init();
    
    /* 创建一个简单的按钮 */
    lv_obj_t *btn = lv_btn_create(lv_scr_act());
    lv_obj_set_size(btn, 100, 50);
    lv_obj_center(btn);
    
    lv_obj_t *label = lv_label_create(btn);
    lv_label_set_text(label, "Hello LVGL");
    lv_obj_center(label);
    
    /* 主循环 */
    while(1) {
        lv_timer_handler();
        delay(5);
    }
}

避坑指南:我曾经在lv_timer_handler()里忘了加延时,结果CPU跑满,屏幕还闪烁。记得加个5-10ms的延时。