Featured image of post LVGL Pro环境配置及初体验

LVGL Pro环境配置及初体验

啥是LVGL Pro

最近入手了一块STM32F103ZET6的开发板,用一周时间学习了外设基本知识并移植完FreeRTOS、电阻触摸屏和其他一些IO后决定开发LVGL。在经历完操蛋的LVGL 9.4移植后,我想起了LVGL官方大力推荐的Next-gen方案:LVGL Pro。这是一个让你可以使用XML编辑布局和样式并编译到C代码的工具链,我们可以看一下官方示例感受一下写法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<component>
    <previews>
        <preview width="320" height="240" style_pad_all="24" style_bg_color="0xaaa" />
    </previews>

    <styles>
        <style name="style_main" height="100%" flex_cross_place="center" pad_row="#unit_sm" />
        <style name="style_main_dark" text_color="#surface_primary_dark" />
        <style name="style_bar" width="#unit_md" flex_grow="1" />
    </styles>
    <api>
        <prop name="move" type="int" default="5000" />
        <prop name="day" type="string" default="Mon" />
    </api>
    <view extends="column">
        <style name="style_main" />
        <bind_style name="style_main_dark" subject="dark_theme" ref_value="1" />

        <bar min_value="0" max_value="10000" value="$move">
            <style name="style_bar" />
        </bar>

        <lv_label text="$day" style_text_font="geist_semibold_12" />
    </view>
</component>

看起来就像在写HTML呢。不管怎么样,至少肯定比对着C代码硬搓简单多了。上面的代码会生成以下C代码(已简化):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
lv_obj_t * stat_col_create(lv_obj_t * parent, int32_t move, const char * day)
{
    LV_TRACE_OBJ_CREATE("begin");

    static lv_style_t style_main;
    static lv_style_t style_main_dark;
    static lv_style_t style_bar;

    static bool style_inited = false;

    if (!style_inited) {
        lv_style_init(&style_main);
        lv_style_set_height(&style_main, lv_pct(100));
        lv_style_set_flex_cross_place(&style_main, LV_FLEX_ALIGN_CENTER);
        lv_style_set_pad_row(&style_main, UNIT_SM);

        lv_style_init(&style_main_dark);
        lv_style_set_text_color(&style_main_dark, SURFACE_PRIMARY_DARK);

        lv_style_init(&style_bar);
        lv_style_set_width(&style_bar, UNIT_MD);
        lv_style_set_flex_grow(&style_bar, 1);

        style_inited = true;
    }

    lv_obj_t * column_0 = column_create(parent);
    lv_obj_set_name_static(column_0, "stat_col_#");

    lv_obj_add_style(column_0, &style_main, 0);
    lv_obj_bind_style(column_0, &style_main_dark, 0, &dark_theme, 1);
    lv_obj_t * bar_0 = bar_create(column_0);
    lv_bar_set_min_value(bar_0, 0);
    lv_bar_set_max_value(bar_0, 10000);
    lv_bar_set_value(bar_0, move, false);
    lv_obj_add_style(bar_0, &style_bar, 0);
    
    lv_obj_t * lv_label_0 = lv_label_create(column_0);
    lv_label_set_text(lv_label_0, day);
    lv_obj_set_style_text_font(lv_label_0, geist_semibold_12, 0);

    LV_TRACE_OBJ_CREATE("finished");

    return column_0;
}

而且LVGL Pro还支持可视化。简直香爆了!值得一提的是,要在本地使用LVGL Pro的话是需要订阅的,想免费用只能在网页端编辑开源项目。下面是订阅价格表(2026/1/21):

准备工作

安装WSL2

打开控制面板 - 程序 - 程序和功能或Win+R输入appwiz.cpl,点击启用或关闭Windows功能,勾选以下三项:

如果其中没有Hyper-V,可先尝试进行后续步骤再尝试以下方案:打开终端管理员,粘贴以下代码

1
2
3
4
5
$pkgs = Get-ChildItem "$env:SystemRoot\servicing\Packages\*Hyper-V*.mum" | Select-Object -ExpandProperty Name
foreach ($pkg in $pkgs) {
   dism /online /norestart /add-package:"$env:SystemRoot\servicing\Packages\$pkg"
}
dism /online /enable-feature /featurename:Microsoft-Hyper-V-All /LimitAccess /All

安装LVGL Pro

前往Releases页面下载并安装编辑器,随后新建一个项目。编辑器将自动完成Podman镜像拉取和后续工作。如果在这里遇到WSL2不能启动的问题,请打开cmd输入wsl查看报错并自行搜索解决方法。

配置Podman镜像源

在开始菜单中找到podman-machine-default或打开终端输入wsl -d podman-machine-default。在WSL中输入sudo vi /etc/containers/registries.conf.d/999-podman-machine.conf,按i进入编辑模式并将配置修改为

1
2
3
4
5
unqualified-search-registries = ["docker.io"]

[[registry]]
prefix = "docker.io"
location = "docker.1ms.run"

按esc退出编辑模式,输入:wq保存并退出编辑器。

集成至现有项目

如果你顺利完成了以上操作,不出意外的话可以开始编辑UI、查看预览了。如果你遇到了其他问题,可以跳转至踩坑小节或在评论区询问~

当你完成了UI的设计,点击右上角的 按钮即可生成.c/.h文件。接下来,我们只需要在嵌入式工程的CMakeLists.txt中加入相关配置引入子目录即可。以下是我的目录结构:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
/
├─Core
│  └─Usr
│      └─Lvgl
│         └─Project
│             ├─CMakeLists.txt
│             ├─Project.c
│             └─Project.h
├─Middlewares
│   └─lvgl
└─CMakeLists.txt

/CMakeLists.txt:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# ...

# 添加UI项目为子项目
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/Core/Usr/Lvgl/Project)

# lib-ui为子项目的CMakeLists.txt中设置的默认项目名
# 为子项目提供lvgl环境
target_include_directories(lib-ui PRIVATE
    Middlewares/
)

# 让当前项目依赖子项目
target_link_libraries(${CMAKE_PROJECT_NAME}
    lib-ui  
)

# ...

然后在你的嵌入式项目中进行以下调用:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include "Lvgl/Project/Project.h"

void StartLvglTask(void *argument) {  
    lv_init();
    lv_tick_set_cb(osKernelGetTickCount);
    lv_port_disp_init();
    lv_port_indev_init();
    // 以上为驱动初始化
    
    Project_init(NULL);  // 初始化UI项目
    lv_obj_t *main_screen = main_create();  // 创建屏幕
    lv_screen_load(main_screen);  // 加载屏幕
    
    // 如果不使用screens,也可以直接添加components到默认屏幕
    // appbar_create(lv_scr_act(), "Text");
    
    for (;;) {  
        lv_timer_handler();  
        osDelay(5);  
    }  
}

踩坑

WSL2提示无法配置网络(networkingMode Nat)

参考WSL2 无法连接互联网 - Microsoft Q&A

升级版本

从1.0.1升级到1.0.2后出现编译错误的情况,需要进入%appdata%\lvgl-editor删除resources文件夹。

Licensed under CC BY-NC-SA 4.0