1、LVGL概述与环境搭建

LVGL是什么?

LVGL,全称Light and Versatile Graphics Library,是一个开源的嵌入式图形库。说白了,它就是一套专门给MCU用的UI框架。你想想看,在单片机上跑个带触摸的彩色界面,这事儿以前挺麻烦的。LVGL就是来解决这个问题的。

我最早接触LVGL是在2019年,当时一个智能家居项目需要做个小屏幕控制面板。那时候可选方案不多,要么用emWin(要钱),要么自己从头画像素点。LVGL的出现,确实让嵌入式UI开发轻松了不少。

为什么选择LVGL?

这个问题我经常被问到。其实原因很直接:

  • 开源免费:MIT协议,商用无压力。我见过不少团队因为授权问题被迫换方案,LVGL没这个烦恼。
  • 资源占用低:最低配置只要16KB RAM、64KB Flash就能跑。嗯,你没看错,一个Cortex-M0内核的芯片就能玩起来。
  • 控件丰富:按钮、滑块、图表、键盘...30多种现成控件。我做过一个医疗设备界面,从零到原型只用了两天。
  • 跨平台:同一套代码,MCU上能跑,PC模拟器也能跑。调试效率提升不是一点半点。

核心优势:LVGL把复杂UI开发的门槛降到了极低。你不需要懂图形学,不需要会OpenGL,只要会C语言,就能做出专业级的嵌入式界面。

LVGL在嵌入式领域的地位

现在嵌入式UI领域,LVGL基本是事实上的标准了。我参加过几次行业展会,10个带屏幕的嵌入式产品里,至少有6个用的是LVGL。为什么?

因为嵌入式UI的需求变了。以前大家觉得屏幕能显示几个数字就够了,现在用户要的是滑动、动画、触摸反馈。LVGL正好满足了这种需求。

举个例子,我去年帮一家家电厂商做智能烤箱的界面。他们之前用段码屏,后来换成彩屏,UI复杂度直接翻了好几倍。用LVGL,两个月就搞定了量产版本。要是自己从头写,半年都不一定够。

开发环境搭建

环境搭建这块,我建议你走两条路:先用模拟器熟悉API,再移植到真实硬件。这样效率最高。

方案一:PC模拟器(推荐新手)

模拟器用的是SDL2或X11,在Windows、Linux、macOS上都能跑。我个人习惯用VS Code + CMake,配置起来很清爽。

具体步骤:

  1. 从GitHub拉取LVGL源码(建议用v8.3.x稳定版)
  2. 下载模拟器示例工程(官方有现成的)
  3. 安装SDL2开发库
  4. 编译运行

我曾经帮一个学员远程调试,他卡在SDL2安装上。其实Windows下用vcpkg一条命令就搞定了:

vcpkg install sdl2

方案二:真实MCU开发板

如果你手头有STM32、ESP32或者任何带屏幕的开发板,直接移植也很简单。核心就三步:

  • 配置显示驱动:告诉LVGL你的屏幕分辨率、颜色格式、刷新回调函数
  • 配置触摸驱动:把触摸坐标传给LVGL
  • 配置系统时钟:给LVGL一个心跳(通常用1ms定时器)

小技巧:第一次移植时,先用LVGL自带的demo程序验证。如果屏幕上能显示出官方demo的界面,说明移植成功了。我每次换新平台都这么干,省心。

第一个LVGL程序

好了,理论说完了,咱们直接上手。下面是一个最简单的LVGL程序,在屏幕上显示一个按钮:

#include "lvgl.h"

int main(void)
{
    /* 1. 初始化LVGL */
    lv_init();

    /* 2. 初始化显示驱动和触摸驱动(这里用模拟器) */
    lv_port_disp_init();
    lv_port_indev_init();

    /* 3. 创建一个按钮 */
    lv_obj_t *btn = lv_btn_create(lv_scr_act());
    lv_obj_set_pos(btn, 100, 100);
    lv_obj_set_size(btn, 120, 50);

    /* 4. 在按钮上添加标签 */
    lv_obj_t *label = lv_label_create(btn);
    lv_label_set_text(label, "Hello LVGL");
    lv_obj_center(label);

    /* 5. 主循环 */
    while(1) {
        lv_timer_handler();
        lv_delay_ms(5);
    }

    return 0;
}

这段代码看着简单,但包含了LVGL的核心流程:

  • lv_init():启动LVGL内核
  • lv_btn_create():创建控件,所有控件都是这么创建的
  • lv_timer_handler():定时处理LVGL内部任务,必须放在主循环里

注意:lv_timer_handler()的调用间隔不能太长,否则界面会卡顿。我一般设5ms调用一次。如果你发现触摸反应慢,先检查这个函数的调用频率。

运行起来后,你会看到一个带"Hello LVGL"文字的按钮出现在屏幕中央。点击它?嗯,目前还没绑定事件。别急,后面章节会讲事件处理。

说实话,第一次看到自己的代码在屏幕上显示出UI时,那种感觉还是挺爽的。我记得自己第一次跑通LVGL demo时,盯着那个旋转的齿轮动画看了好几分钟——就为了确认这不是幻觉。

小结

这一章我们搞定了三件事:

  • 明白了LVGL是什么,为什么选它
  • 搭建了开发环境(模拟器或MCU)
  • 跑通了第一个LVGL程序

下一章,我们会深入LVGL的对象系统。说白了,就是搞清楚LVGL里那些控件到底是怎么组织、怎么管理的。理解了对象系统,后面学控件、学布局就会轻松很多。

嗯,准备好了吗?我们继续。