注意:如果你是新手,需要观看上一篇文章《LVGL应用编程入门》。本文使用的开发板sdk是小智学长(b站知名up)的T113智慧屏板卡配套sdk,当然考虑到小伙伴新手居多,本文及后续文章也主要以Linux仿真为主,效果与开发板一致,让小伙伴可以只用一台windows电脑也能学习并实操嵌入式LVGL应用开发。
在开始之前,请确保你已经完成:
如果你还没有完成,需要先观看上一篇博客《LVGL应用编程入门》:LVGL应用编程入门:从零开始打造炫酷嵌入式界面,不然这篇文章实操会有问题。
然后提前看下本文最终显示效果:

打个比方:
通过创建自己的工程,你可以:
打开Ubuntu终端,按照以下步骤操作:
# 1. 进入SDK目录cd ~/work/app_sdk# 2. 创建自己的工程文件夹(我命名为app1,你可以取任何名字)mkdir app1# 3. 进入新创建的文件夹cd app1现在你的目录结构应该是这样的:
app_sdk/├── app/ # SDK自带的示例工程├── app1/ # 你创建的新工程├── lvgl/ # LVGL核心库├── component/ # 各种组件└── ... # 其他文件夹在app1文件夹中创建两个关键文件:
# 创建main.c - 程序的入口文件touch main.c# 创建CMakeLists.txt - 告诉编译器如何编译我们的程序touch CMakeLists.txt通俗解释:这个文件就像餐厅的菜单和制作流程,告诉厨师(编译器):
打开app_sdk/app1/CMakeLists.txt,输入以下内容:
# 指定CMake的最低版本要求cmake_minimum_required(VERSION 3.15)# 设置工程名称为demo1(这个名字将决定生成的可执行文件名)project(demo1)# 自动收集当前目录下所有的.c文件,存入SOURCES变量aux_source_directory(. SOURCES)# 告诉CMake要生成一个可执行文件:# demo1 - 可执行文件的名字# ${SOURCES} - 使用的源文件列表add_executable(demo1 ${SOURCES})# 设置头文件搜索路径(告诉编译器去哪里找.h文件)target_include_directories(demo1 PRIVATE ./ # 当前目录 ${CMAKE_SOURCE_DIR}/lvgl # LVGL库目录)# 链接需要的库(就像告诉链接器:"做这道菜需要LVGL这个调味料")target_link_libraries(demo1 PRIVATE lvgl)# 为什么用PRIVATE而不是PUBLIC?# PRIVATE - "自己用的调味料不放锅里"# 效果:当前工程(demo1)可以使用lvgl库# 但是:其他工程如果依赖demo1,不会自动获得lvgl库# PUBLIC - "调味料放锅里大家一起用"# 效果:当前工程可以使用lvgl库# 而且:其他工程如果依赖demo1,也会自动获得lvgl库# 对于我们的小工程,用PRIVATE就足够了!一个最基本的LVGL程序包含以下部分:
1. 头文件引入 (#include ...)2. LVGL初始化 (lv_init())3. 显示设备初始化 (lv_port_disp_init())4. 输入设备初始化 (lv_port_indev_init())5. 创建界面 (创建控件、设置属性)6. 主循环 (不断处理用户交互和界面更新)打开app_sdk/app1/main.c,输入以下内容:
#include <unistd.h> // 提供usleep函数#include <stdlib.h> // 标准库#include <stdio.h> // 标准输入输出#include "lvgl.h" // LVGL核心库// 声明外部函数(这些函数已经在SDK的其他地方实现了)extern void lv_port_disp_init(bool is_disp_orientation);extern void lv_port_indev_init(void);// 创建Hello World界面的函数void lv_example_hello_world(void) { lv_obj_t *scr = lv_scr_act(); // 1.获取当前活动屏幕(就像拿到一张白纸) lv_obj_t *label = lv_label_create(scr); // 2.在屏幕上创建一个标签控件(就像在白纸上贴一个便签) lv_label_set_text(label, "Hello, World!"); // 3.设置标签的文本内容 lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); // 4.将标签居中对齐(x偏移0,y偏移0) // 解释:LV_ALIGN_CENTER表示居中对齐 // 0,0表示水平和垂直方向都不偏移}// 主函数 - 程序从这里开始执行int main() { printf("Starting LVGL Hello World application...\n"); lv_init(); // 第一步:LVGL框架初始化 lv_port_disp_init(true); // 第二步:初始化显示设备(true表示使用默认的显示方向) lv_port_indev_init(); // 第三步:初始化输入设备 lv_example_hello_world(); // 第四步:创建我们的Hello World界面 // 第五步:主循环 - 保持程序运行,处理事件 while (1) { lv_task_handler(); // 处理LVGL任务(检查有没有触摸事件,要不要更新显示等) usleep(1000); // 短暂延时,避免CPU使用率过高,usleep(1000)表示暂停1000微秒(1毫秒) } // 理论上程序不会执行到这里(因为while(1)是无限循环) return 0;}我们需要告诉SDK:"嘿,我新建了一个工程,请把它也编译进去!"
编辑app_sdk/CMakeLists.txt文件:
# 找到这一行(大约在文件末尾):# add_subdirectory(app)# 在这行下面添加:add_subdirectory(app1)# 修改后应该是这样的:add_subdirectory(app) # 这个原本的可以注释掉add_subdirectory(app1) # 新增的行
如果你打开app_sdk/CMakeLists.txt发现没有add_subdirectory(app)这一行,可能是SDK版本不同。没关系,你只需要在合适的位置(文件末尾附近)添加:
# 编译app1工程add_subdirectory(app1)回到终端,确保你在app_sdk目录下:
# 1. 清理之前的编译文件(如果是第一次编译或切换平台)./build.sh -clean# 2. 编译Linux版本./build.sh -linux编译成功的标志:
[100%] Built target demo1Scanning dependencies of target demo1[ 90%] Linking C executable demo1[100%] Built target demo1编译成功后,会在build目录下生成你的程序:
# 查看生成的可执行文件ls build/app1/# 应该能看到:demo1# 运行程序./build/app1/demo1期待的画面:你会看到一个窗口,中间显示着"Hello, World!"文字!

恭喜你完成了第一个LVGL工程! 🎉 现在你可以自豪地说:"我会用LVGL创建图形界面了!" 继续前进,下一个挑战是创建一个有按钮和交互的完整应用!
现在你的工程结构应该是这样的:
app_sdk/├── app1/ # 你的第一个工程│ ├── main.c # 主程序文件│ └── CMakeLists.txt # 工程配置文件├── build/ # 编译输出目录│ └── app1/│ └── demo1 # 可执行文件└── ... # 其他SDK文件通过这个简单的Hello World工程,你已经学会了:
# 1. 创建工程目录和文件mkdir app1cd app1touch main.c CMakeLists.txt# 2. 编写代码# 3. 修改SDK的CMakeLists.txt,添加add_subdirectory(app1)# 4. 编译cd ~/work/app_sdk./build.sh -clean./build.sh -linux# 5. 运行./build/app1/demo1