4、第一个LVGL程序:初始化LVGL、创建基础屏幕、添加标签、编译与下载运行
好,到了真正动手的时候了。
前面几章我们聊了LVGL是什么,也搭好了开发环境。但说实话,光看不练是学不会GUI的。我记得自己第一次接触LVGL时,对着文档看了半天,总觉得心里没底。直到亲手敲了几行代码,看到屏幕上出现第一个"Hello World",那种感觉才踏实下来。
这一章,我们就来写第一个LVGL程序。目标很简单:初始化LVGL,创建一个屏幕,在上面显示一行文字。然后编译、下载,看它跑起来。
本章核心目标:用最少的代码,让LVGL在你的硬件上亮起来。
4.1 程序骨架:先搞清楚要做什么
一个LVGL程序,说白了就三步:
- 初始化——让LVGL内核准备好干活
- 创建UI——画屏幕、放控件
- 进入循环——让LVGL不断刷新显示
你想想看,这跟咱们平时写单片机程序很像。只不过LVGL帮我们管好了显示和触摸,我们只需要告诉它"画什么"就行。
下面这张图,就是整个程序的运行逻辑:
嗯,流程不复杂。但有个细节我得多说一句:lv_tick_inc() 这个函数,必须在定时器中断里周期性调用。我见过不少新手,程序跑起来屏幕没反应,查了半天发现是忘了喂这个"心跳"。
4.2 代码实现:一行一行拆开讲
下面就是完整的代码。别急着复制,先跟着我过一遍。
#include "lvgl.h"
#include "lv_port_disp.h"
#include "lv_port_indev.h"
int main(void)
{
/* 1. 硬件初始化 */
hal_init(); // 时钟、GPIO、定时器等
/* 2. 初始化LVGL核心库 */
lv_init();
/* 3. 初始化显示驱动 */
lv_port_disp_init();
/* 4. 初始化触摸驱动(如果有) */
lv_port_indev_init();
/* 5. 创建基础屏幕 */
lv_obj_t *scr = lv_obj_create(NULL);
lv_scr_load(scr);
/* 6. 在屏幕上添加一个标签 */
lv_obj_t *label = lv_label_create(scr);
lv_label_set_text(label, "Hello LVGL!");
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
/* 7. 主循环 */
while(1)
{
lv_timer_handler();
lv_tick_inc(1);
delay_ms(5);
}
}
代码不长,但每个函数都有它的意义。我挑几个重点说说:
| 函数 | 作用 | 个人经验 |
|---|---|---|
lv_init() |
初始化LVGL内部数据结构、内存池、动画系统等 | 必须在所有LVGL函数之前调用,否则会崩溃 |
lv_port_disp_init() |
注册显示驱动,告诉LVGL怎么往屏幕刷像素 | 我习惯用双缓冲,能有效避免撕裂 |
lv_obj_create(NULL) |
创建一个对象,参数NULL表示它是根屏幕 | 注意:第一个参数是父对象,NULL就是顶级 |
lv_scr_load() |
把创建好的屏幕设置为当前活动屏幕 | 不调用这行,屏幕是黑的 |
lv_label_create() |
在指定父对象上创建标签控件 | 标签是最简单的控件,适合入门 |
lv_timer_handler() |
LVGL的心跳函数,处理所有待办任务 | 必须在主循环中周期性调用 |
小技巧:lv_obj_align(label, LV_ALIGN_CENTER, 0, 0) 这行,意思是把标签相对于父对象居中。后面两个0是X和Y的偏移量。如果你想往右偏10像素,就写成 10, 0。
4.3 避坑指南:我踩过的几个坑
说实话,第一次跑LVGL程序,很少有人能一次成功。我当初也折腾了好一阵子。下面这几个坑,你大概率也会遇到:
- 屏幕没反应——检查
lv_tick_inc()有没有在定时器里调用。我曾经忘了开定时器,屏幕一直黑着,查了半小时。 - 花屏或闪烁——多半是显示驱动配置不对。检查像素格式(RGB565还是RGB888)和缓冲区大小是否匹配。
- 编译报错,提示找不到头文件——确认LVGL源码路径有没有加到编译器的包含目录里。我习惯把
lvgl/文件夹直接放在工程根目录下。 - 触摸没反应——先别急着调触摸,用屏幕自带的按钮测试。或者干脆先不接触摸,只用显示。
重要提醒:lv_timer_handler() 和 lv_tick_inc() 是两个不同的东西。前者在主循环里调用,后者在定时器中断里调用。千万别搞混了!
4.4 编译与下载:让代码跑起来
代码写好了,接下来就是编译和下载。不同平台操作略有不同,但思路一样:
- 编译:在IDE里点"Build",或者命令行敲
make。如果没有报错,会生成一个 .bin 或 .hex 文件。 - 下载:用调试器(J-Link、ST-Link等)或者串口烧录工具,把固件写到芯片里。
- 运行:按下复位键,或者重新上电。
如果一切顺利,屏幕上应该会出现居中显示的"Hello LVGL!"字样。嗯,看到这个画面,恭喜你——LVGL已经成功跑起来了。
第一个里程碑:从这一刻起,你不再是LVGL的旁观者,而是真正的使用者了。
4.5 扩展一下:让标签更生动
光显示一行文字太单调了。我们加点花样:
/* 修改标签文字颜色 */
lv_obj_set_style_text_color(label, lv_color_hex(0xFF0000), 0);
/* 修改字体大小(需要先启用对应的字体宏) */
lv_obj_set_style_text_font(label, &lv_font_montserrat_20, 0);
/* 添加阴影效果 */
lv_obj_set_style_text_opa(label, LV_OPA_80, 0);
你看,LVGL的样式修改就是这么直观。每个属性都可以单独设置,而且支持多种状态(默认、按下、禁用等)。
我个人习惯在调试阶段,先把文字设成红色,这样一眼就能看出标签有没有显示出来。等布局调好了,再改回正式颜色。
4.6 本章小结
这一章我们完成了第一个LVGL程序。从初始化到创建屏幕,再到添加标签,最后编译下载运行。整个过程虽然简单,但它是后面所有复杂UI的基础。
你想想看,屏幕和标签都有了,接下来加个按钮、加个滑块,不就是同样的套路吗?
嗯,先别急着往下翻。我建议你亲手敲一遍代码,哪怕只是改个文字内容,也比光看强十倍。遇到问题别慌,对照着避坑指南排查一遍,多半能解决。