0.介绍

这篇文章主要介绍在GUI Guide制作完成一个LVGL项目后,如何将项目代码移植到指定的开发板中运行(这里使用的开发板使用的是瑞芯微的 RK3568B2 四核 64 位处理器)

包括以下内容:

1.GUI Guider基础创建

2.LVGL下载及配置(通过gitee)

3.CMakeList.txt编写

4.LVGL的main.c编写

5.交叉编译

使用到的工具:

  1. GUI Guider
  2. LVGL(v9.2)
  3. Cmake
  4. make
  5. 交叉编译器gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf
  6. 虚拟机ubuntu

1.创建项目

建立工程

在这里插入图片描述在这里插入图片描述

效果展示

创建后的效果展示,创建过程略,可自行随意制作一个简易项目
在这里插入图片描述

2.移植

复制关键文件夹

在编译运行后,gui guider 会在创建目录下生成文件,我们去当前项目存储的位置(创建项目中的文件存储路径)找到下面两个文件夹
在这里插入图片描述
找到后直接复制,然后去电脑合适地方创建一个工程文件夹,将复制的两个文件夹粘贴进去,目前我们的工程文件夹就有了两个子文件夹了。

下载相同版本的LVGL

现在我们去gitee上下载与我们创建gui 项目相同的版本的LVGL(相同版本的就不会有调用函数不兼容的问题,大幅度减小了错误发生率),在我们创建的时候我们选择的是LVGL V9.2.1版本(可见前述动图),因此我们去下载该版本,随便找一个浏览器搜索gitee进入,然后在右上方搜索LVGL,按下面的步骤找到release/v9.2,再点击右上角克隆/下载,下载压缩包
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
下载完成后是这样一个压缩包,解压缩后打开是一个叫做lvgl-release-v9.2的文件夹,将这个文件夹的名称改为lvgl(注意是最里面的那个叫lvgl-release-v9.2的文件夹),然后粘贴到我们先前创建的的工程文件夹中

在这里插入图片描述

现在我们的目录结构如下

在这里插入图片描述

配置LVGL

现在我们使用vscode打开这个文件夹,打开lvgl这个文件夹,找到它的配置头文件lv_conf_template.h(就在lvgl目录下),将其名字重命名成lv_conf.h,这个文件是用于对 LVGL 库的各种功能和参数进行定制化设置的。具体详细内容可自行了解(LVGL的配置文件lv_conf.h)

因为在LVGL 的内部,各种代码都是通过头文件包含引用这个配置文件(lv_conf.h),在这些代码中添加的头文件可能为#include "lv_conf.h" 或者#include "../../lv_conf.h" ,所以要改名为lv_conf.h,然后就是路径也是相对的,所以要放在lvgl目录的外头(与lvgl同级目录)才能准确被找到。
在这里插入图片描述

然后将配置文件lv_conf.h中的代码启动,将#if 后面的0改为1,启动后面的内容,之后还会在这个文件中修改一些内容,但是此处先搁置一下,后面逐步配置。

在这里插入图片描述

创建CMakeList.txt文件

然后我们再来创建一个CMakeList.txt文件, 这个是CMake 构建系统的核心配置文件,主要用途是描述项目的构建规则和编译流程,帮助开发者跨平台、自动化地生成可执行文件、库文件或其他构建产物。简单的来说这个文件就像一本食谱,将项目的构建流程一步步规范清楚(先做什么后做什么由谁来做),在对应步骤调动编译器与链接器等工具去做对应的事情,规范项目构建流程,指导工具依次运行。

在这里插入图片描述

接下来我们来编写CMakeLists.txt中的内容可直接复制使用,如果项目代码完全使用GUI Guider编写,基本无需改变,如果还需要在项目中自编写代码(不通过GUI Guider平台),自定义项目则需要在头文件包含中添加你所编写项目代码的头文件所在的路径,还有将源c文件添加在add_executable中,(类似于keil开发中添加新文件时需要去添加头文件目录以及将c文件添加到工程中来的操作如下图)
在这里插入图片描述

建议把需要添加的c与h文件放在一个新创建的文件夹内,然后将这个文件夹中头文件的路径添加到include_directories中,c文件(文件多时可通过file命令或者set命令将其c文件赋与变量,再将变量以正确的方式添加到add_executable中,两个命令的用法可自行了解)添加到add_executable中

CMakeLists.txt:代码其实不多,有很多便于理解的注释

#该cmakeLists.txt功能
#适用于使用LVGL 9.2版本的CMake文件
#用于交叉编译LVGL项目移植到开发板RK3568B2上显示

cmake_minimum_required(VERSION 3.10)# 声明此CMake配置文件的最低版本要求为3.10,低于此版本的CMake可能无法正确解析配置

set(CMAKE_SYSTEM_NAME Linux)# 设置目标系统名称为Linux,表明编译产物将运行在Linux系统上
set(CMAKE_SYSTEM_PROCESSOR arm)# 设置目标系统处理器架构为ARM,说明编译产物适用于ARM架构的设备(此处指RK3568B2开发板)

# 指定C交叉编译器路径,使用arm-linux-gnueabihf-gcc为RK3568B2开发板编译C代码,这需要针对不同开发板选择合适的交叉编译器
#开发板的官方文档通常会明确指出推荐或适配的交叉编译工具链,下载合适的编译器后指定其路径
set(CMAKE_C_COMPILER /usr/local/arm/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc)
# 指定C++交叉编译器路径,使用arm-linux-gnueabihf-g++为RK3568B2开发板编译C++代码,如果没有使用C++,此行以及下面的CXX规则可以去掉
set(CMAKE_CXX_COMPILER /usr/local/arm/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin//arm-linux-gnueabihf-g++)

# 此处用于定义项目的基本信息,我仅定义项目名称为GUI_LVGL_RK3568B2,标识当前是针对RK3568B2的LVGL GUI项目
project(GUI_LVGL_RK3568B2)

set(CMAKE_C_STANDARD 99)# 设置C语言标准为C99,LVGL官方支持C99及以上标准
set(CMAKE_CXX_STANDARD 17)# 设置C++语言标准为C17
set(CMAKE_CXX_STANDARD_REQUIRED ON)# 强制要求使用指定的C++标准,若编译器不支持则会报错

# 指定可执行文件的输出目录为项目根目录下的bin文件夹,这样,我们的编译好对于开发板的可执行文件则会存在当前目录下的bin目录下,
#${PROJECT_SOURCE_DIR}代表的是CMakeLists.txt所在的路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

###################递归处理 lvgl 内部的构建逻辑(编译 lvgl 源码、处理它的依赖等 )###################################
# 添加lvgl子目录,CMake会自动查找该目录下的CMakeLists.txt并执行,完成LVGL库的编译和配置
add_subdirectory(lvgl) 

#########################################头文件处理#################################################
# custom 和 generated 中的代码需要引用彼此的头文件以及 LVGL 的头文件(如 lv_conf.h、lvgl/lvgl.h 等)。通过include_directories 暴露这些头文件的路径,全局可用(对所有源文件类型,即在调用头文件的名称即可,无需查找相对位置,如#include "../../lvgl.h",添加后可以直接#include "lvgl.h",编译器会在你所添加的搜索路径下去找该头文件,就不会因为粗心导致编译错误找不到头文件了)
#添加头文件搜索路径,确保编译器能找到以下目录中的头文件
include_directories(
    ${PROJECT_SOURCE_DIR}          # 项目根目录,如上所说(包含lv_conf.h等全局配置头文件)
    ${PROJECT_SOURCE_DIR}/custom   # custom目录(GUI guider生成的用户自定义代码的头文件)
    ${PROJECT_SOURCE_DIR}/generated# generated目录(GUI Guider自动生成的UI头文件)
    ${PROJECT_SOURCE_DIR}/generated/guider_customer_fonts # 自定义字体相关头文件
    ${PROJECT_SOURCE_DIR}/generated/guider_fonts # 自动生成的字体相关头文件
    ${PROJECT_SOURCE_DIR}/lvgl     # LVGL库的头文件目录
)

#########################################源文件处理##################################################
# GUI Guider 生成的代码分散在 custom(用户逻辑)和 generated(自动 UI 代码)中,需递归收集所有 .c 文件
# 递归查找custom目录下所有.c文件,并存入CUSTOM_SOURCES变量
file(GLOB_RECURSE CUSTOM_SOURCES "${PROJECT_SOURCE_DIR}/custom/*.c")
# 递归查找generated目录下所有.c文件,并存入GENERATED_SOURCES变量
file(GLOB_RECURSE GENERATED_SOURCES "${PROJECT_SOURCE_DIR}/generated/*.c")

# 定义驱动源文件列表,包含LVGL的帧缓冲显示驱动和输入设备驱动
set(DIRVER_SOURCES
    lvgl/src/drivers/display/fb/lv_linux_fbdev.c  # Linux帧缓冲显示驱动(用于屏幕输出)
    lvgl/src/drivers/evdev/lv_evdev.c             # 输入设备驱动(用于处理触摸、按键等输入)
    )

# 创建名为my_gui_app的可执行文件,并指定其依赖的源文件
add_executable(my_gui_app 
    main.c           # 程序入口主文件
    ${CUSTOM_SOURCES}# 包含custom目录下的所有用户自定义逻辑代码
    ${GENERATED_SOURCES}# 包含generated目录下的所有自动生成UI代码
    ${DIRVER_SOURCES}# 包含LVGL的显示和输入驱动代码
)

# 为my_gui_app可执行文件链接所需的库
target_link_libraries(my_gui_app
                        PRIVATE 
                        lvgl               # 链接LVGL库
                        lvgl::thorvg       # 链接LVGL依赖的thorvg矢量图形库
                        m                  # 链接数学库(部分LVGL功能依赖)
                        dl                 # 链接动态加载库(用于运行时加载动态库)
                        pthread            # 链接线程库(LVGL的多线程功能依赖)
                     ) 

LVGL的main.c编写(此内容重点就是调用guider的关键三个函数以及配置输出设备)

创建完CMakeList.txt后,我们再来编写一个main.c函数,创建一个main.c文件,顺便将bin文件夹(存储最终开发板执行文件)与build文件夹(cmake执行目录)创建好
在这里插入图片描述
main.c内容如下,在GUI Guider完全开发的情况下,同CMakeLists_txt可以直接复制使用,无需修改:

#include "lvgl/lvgl.h"                  // 包含LittlevGL图形库的主头文件,提供核心功能
#include <unistd.h>                     // 包含Unix标准函数定义,如sleep等
#include <time.h>                       // 包含时间相关函数定义,用于时间操作
#include <stdio.h>                      // 包含标准输入输出函数定义,如printf等
#include <stdlib.h>                     // 包含标准库函数定义,如内存分配等
//上面头文件有些没用到的可不加

#include "gui_guider.h"                 // 包含GUI Guider生成的UI相关函数声明
#include "events_init.h"                // 包含事件初始化相关函数声明
#include "custom.h"                     // 包含自定义功能相关函数声明

#include "./lvgl/src/drivers/display/fb/lv_linux_fbdev.h"  // 包含Linux帧缓冲设备显示驱动头文件
#include "./lvgl/src/drivers/evdev/lv_evdev.h"              // 包含Linux输入设备驱动头文件

lv_ui guider_ui;                        // 声明GUI Guider生成的UI结构体实例

int main(int argc, char **argv)         // 程序主函数,argc为命令行参数数量,argv为参数数组
{
    lv_init();                          // 初始化LittlevGL库
    lv_display_t *disp = lv_linux_fbdev_create();  // 创建Linux帧缓冲显示设备实例
    lv_linux_fbdev_set_file(disp, "/dev/fb0");     // 设置显示设备文件路径为/dev/fb0(第一个帧缓冲设备)
    lv_indev_t *indev = lv_evdev_create(LV_INDEV_TYPE_POINTER, "/dev/input/event6");  // 创建输入设备实例,类型为指针设备,路径为/dev/input/event6
    
    setup_ui(&guider_ui);               // 调用GUI Guider生成的UI设置函数,初始化界面
    events_init(&guider_ui);            // 初始化事件处理函数,绑定UI元素与事件
    custom_init(&guider_ui);            // 初始化自定义功能
    
    while (1)                           // 主循环,持续运行
    {
        lv_timer_handler_run_in_period(5);  // 每5毫秒调用一次LVGL的定时器处理函数,处理UI刷新和事件
    }
    return 0;                           // 程序退出返回值(实际不会执行到这里)
}

最后的lv_conf.h

到这里基本已经完成所有的内容搭建,现在我们在去lv_conf.h中打开一些功能,先将需要用到的改一下,我们按住ctrl + 鼠标左键点击main.c函数中的几个函数,见下方

    lv_display_t *disp = lv_linux_fbdev_create();
    lv_linux_fbdev_set_file(disp, "/dev/fb0");
    lv_indev_t *indev = lv_evdev_create(LV_INDEV_TYPE_POINTER, "/dev/input/event6");

点击这三个函数(lv_linux_fbdev_create() lv_linux_fbdev_set_file() lv_evdev_create())跳转过去后,发现函数内部的代码是灰色的,(如下)代表没有代码部分未使用,我们点击#if 后面的宏变量跳转到lv_conf.h的对应位置,将其开启置1

在这里插入图片描述

在这里插入图片描述

由于 lv_display_t *disp = lv_linux_fbdev_create(); lv_linux_fbdev_set_file(disp, “/dev/fb0”);是在同一个头文件中的,因此此处打开后两个都可用了,还剩下一个lv_evdev_create,点击也无法跳转,它的头文件路径在lvgl\src\drivers\evdev\中,可以找到后打开lv_evdev.h,如下所示,然后点击#if 后面的宏定义进入lv_conf.h中如上述一样将该宏定义置1 打开功能

在这里插入图片描述此处打开后就大功告成了,还有一点需要注意,就是在我们创建GUI GUider项目的时候选择的颜色色深是16位(RGB)的,如果选择其他的,如24位(ARGB),则需要去lv_conf.h中配置,如下,将划线的地方改成与gui guider项目一致的色深。
在这里插入图片描述

在这里插入图片描述

后续随着项目的扩大,用到的功能也会越多,都是需要检查一下在lv_conf.h中是否开启对应功能或者修改对应值的,这里只简单介绍项目的移植流程。

编译

OK!到这里我们就可以去开始激动人心的编译了!打开虚拟机ubuntu,将我们创建的工程文件夹加入共享文件夹中,

在这里插入图片描述

添加完毕后,打开终端进入我们的文件夹中的build目录下进行命令 cmake … 等待cmake完成后进行make,等待make完成即可,其中的附注的问题的原因,不影响编译,所以我没有去解决掉

在这里插入图片描述

编译通过后就可以通过终端仿真软件secureCRT将可执行软件传输至开发板运行了

结果展示

ild目录下进行命令 cmake … 等待cmake完成后进行make,等待make完成即可,其中的附注的问题的原因,不影响编译,所以我没有解决掉
在这里插入图片描述

编译通过后就可以通过终端仿真软件secureCRT将可执行软件传输至开发板运行了

结果展示

在这里插入图片描述
之后再修改项目应该怎么移植呢?
只需要在GUI Guider上设计好项目,然后编译运行,没有错误了就再去保存目录复制custom与generated这两个文件夹,然后替换掉我们的工程目录下的这两个文件夹,然后再去到build中重新cmake …(因为修改后文件夹内部变了,就需要重新cmake一次否则直接make会出错的),然后再make,检查是否出错,如果有错误就逐一排查

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐