一、LVGL的相关资料说明

  • 说明:Light and versatile Graphic Library(轻巧且功能多样化的图形库)

(1)、官方网站链接:

1、英文资料(推荐)
https://lvgl.io/                       (官网主界面)
https://docs.lvgl.io/8.3/index.html    (相关开发文档界面)

2、中文资料
http://lvgl.100ask.net/8.2/index.html  (相关开发文档界面)

(2)、如何学习LVGL?

1、使用网页在线例程 来体验LVGL

2、阅读文档 Introduction(介绍) 章节来初步了解LVGL

3、再来阅读一下文档 Quick overview(快速概览) 章节来了解LVGL的基本知识

4、学习如何使用 Simulator on PC(PC端模拟器) 来在电脑上仿真LVGL

5、试着动手实践一些 Examples(示例)

6、查看特定于平台的教程。(在下面的本节中)。

7、参考移植指南尝试将LVGL Porting(移植) 到一块开发板上,LVGL也已经提供了一些移植好的 工程

8、仔细阅读文档Overview(概述) 章节来更加深入的了解和熟悉LVGL(2-3小时)

9、浏览文档 Widgets(控件) 章节来了解如何使用它们

10、如果你有问题可以到LVGL 论坛 提问

11、阅读文档Contributing(贡献) 章节来看看你能帮LVGL社区做些什么,以促进LVGL软件质量的不断提

二、X86环境搭建(在桌面端运行起LVGL)

(1)、如何下载(直接在官网下载即可)

下载链接:https://github.com/lvgl/lv_port_pc_eclipse/tree/release/v8.3
注意选择v8.3版本:
1、下载LVGL的模板

2、下载LVGL的硬件驱动drivers文件

3、下载LVGL的核心代码文件

  • 注意:如果不想在官网下载,点赞+关注+收藏三连可评论区留言获取(或者私信博主)

(2)、解压并放置各文件夹

  • 需要注意的是:有时候解压缩之后的文件夹,有多重嵌套子文件夹,须确保不能嵌套多重文件夹,即在 lv_drivers 下和 lvgl 下必须有 CMakeLists.txt。
1、在windows系统桌面上,创建一个合适文件夹,用来放置LVGL的各个文件(名字最好短一点)

2、将LVGL模板的文件都拖拽进你自己创建的文件夹

3、将LVGL的硬件驱动drivers文件都拖拽进上一步自己文件夹下的lv_drivers的文件夹下

4、将核心代码文件都拖拽进上一步自己文件夹下的lvgl的文件夹下

(3)、下载配置MinGW

  • 说明:MinGW(Minimalist GNU for Windows)是一个可以在Windows平台上提供轻量级、最小化的GNU工具集,使开发者能够在Windows环境下使用类Unix的工具和编程环境。MinGW的主要组成部分包括:
    • GCC(GNU Compiler Collection): 一个强大的编译器套件,包括C、C++、Fortran等语言的编译器。
    • Binutils: 一组用于处理二进制文件的工具,包括汇编器、链接器等。
    • MSYS(Minimal SYStem): 一个提供类Unix shell环境的工具,使得在Windows环境下使用GNU工具更为方便。
  • 目标:MinGW的主要目标是让开发者能够在Windows上使用开源和跨平台的软件开发工具,而无需依赖于Microsoft Visual Studio等闭源工具。使用MinGW,开发者可以编写和编译与Windows API无关的本地应用程序,这对于跨平台开发和移植代码至Windows平台是非常有用的。
1、解压Mingw64.zip到你自己电脑合适的位置(注意1:不要有中文路径, 注意2:如果之前有装cygwin64环境的同学,建议将其环境变量删除)

  • 删除cygwin64的环境变量:

2、解压 MinGW,并将 bin/ 文件夹设置到 环境变量 PATH 中 (注意不能有中文路径):

3、在命令行中测试是否安装成功:

->win键+R键打开搜索库

-> 输入cmd命令

-> 输入where gcc,查询gcc在何处,有的话,证明安装成功了

(4)、配置SDL2

  • 说明:SDL2 的全称是 Simple DirectMedia Layer 2(简易直媒体层2)。它是一个开源、跨平台的多媒体开发库,主要用于提供对音频、键盘、鼠标、游戏手柄和图形硬件的低级访问。简单来说,SDL2 是一个工具包,它让程序员可以用一套统一的代码,轻松地为 Windows、macOS、Linux、Android、iOS 等多种操作系统开发游戏和多媒体应用。所以如果你的LVGL要在windows系统下,全部功能想要运行起来,需要用到它
  • Windows的LVGL模拟器基于 SDL2 运行,SDL2 位于 :

1、将此目录下的 SDL2.dll 拷贝到 lv_port_pc_v8.3\bin 目录下,如果没有这个bin目录,可以手工创建一个。

2、调整SDL模拟器的窗口分辨率(可令其等于开发板的LCD分辨率):

(5)、下载、配置cmake

  • 说明:cmake是跨平台工程管理工具,在用来管理配置整个LVGL的工程编译工作。下载下面的cmake并安装到Windows中 (注意安装路径不要有中文):
  • 注意:博主已经为你们准备好了,点赞三连,评论区或者私信领取

  • 安装时注意

(6)、配置VSCode软件

1、安装cmake、cmaketools插件:

2、配置 cmaketools :

  • 注意: 当需要在Windows和ARM交叉编译环境切换时,上述 Generator也需同步在 MinGW Makefiles 和 Unix Makfiles之间切换。
3、设置构建LVGL的工具链
  • 注意:如果没有出现以下选项,则重新来一遍或者最好重启系统

4、点击 ”生成“ 按钮,开始编译:

5、点击三角号,运行得到官方示例:

  • 注意:修改如下宏定义,可启停上述demo例程的边角监控信息:

三、ARM环境搭建(在开发板上运行起LVGL)

  • 注意:
    • 你的工程不能有中文路径,否则有可能会造成编译器无法识别的问题
    • 单独打开lvgl工程

(1)、下载ARM平台LVGL源码包

下载链接:https://github.com/lvgl/lv_port_pc_eclipse/tree/release/v8.2
注意选择v8.2版本:
1、下载LVGL的模板

2、下载LVGL的硬件驱动drivers文件

3、下载LVGL的核心代码文件

  • 注意:如果不想在官网下载,点赞+关注+收藏三连可评论区留言获取(或者私信博主)

(2)、解压并放置各文件夹

  • 注意:有时候解压缩之后的文件夹,有多重嵌套子文件夹,须确保不能嵌套多重文件夹,即在 lv_drivers 下和 lvgl 下必须有 CMakeLists.txt。
1、在windows系统桌面上,创建一个合适文件夹,用来放置LVGL的各个文件(名字最好短一点)

2、将LVGL模板的文件都拖拽进你自己创建的文件夹

3、将LVGL的硬件驱动drivers文件都拖拽进上一步自己文件夹下的lv_drivers的文件夹下

4、将核心代码文件都拖拽进上一步自己文件夹下的lvgl的文件夹下

(3)、将你的工程进行裁剪,然后复制移动到ubuntu系统的家目录里面去,然后使用ssh进行远程连接

1、将不必要的文件和文件夹删除

2、复制移动到ubuntu系统的家目录中, 最好再赋予权限
终端命令1:cp /mnt/hgfs/你的共享文件夹/lv_port_linux_v8.2/ ~/ -rf
终端命令2:chmod 777  ~/lv_port_linux_v8.2/ 
  • 现象

3、使用ssh进行远程链接

(4)、配置gec6818开发板的交叉编译环境

1、检查一下你自己安装交叉编译器的路径:
终端命令:which arm-linux-gcc
注意:博主的ubuntu系统交叉编译工具的路径:/home/mq/arm-linux_gcc-5.4.0/usr/
  • 现象

2、检查一下你的交叉编译器能不能用:
终端命令1:arm-linux-gcc -v                # 获取交叉编译器的版本
终端命令2:arm-linux-gcc main.c -o main    # 编译程序
  • 终端命令1的现象:

  • 终端命令2的现象:

(5)、需要更改一下VScode软件上CMake Tools工具(远程)

  • 修改一下你的编译器为unix平台

(6)、在工程里面创建CMakeLists.txt,并填写一下内容

cmake_minimum_required(VERSION 3.1)

project(main)

include_directories(.)

add_subdirectory(lvgl)
add_subdirectory(lv_drivers)

set(TOOLCHAIN_DIR "/home/mq/arm-linux_gcc-5.4.0/usr")   # 比如:这个位置是博主的交叉编译工具链的位置
set(CMAKE_C_COMPILER "${TOOLCHAIN_DIR}/bin/arm-linux-gcc")
set(CMAKE_CXX_COMPILER "${TOOLCHAIN_DIR}/bin/arm-linux-g++")

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/build)
add_executable(${PROJECT_NAME} main.c mouse_cursor_icon.c)
target_link_libraries(${PROJECT_NAME} PRIVATE lvgl lvgl::examples lvgl::demos lvgl::drivers)

(7)、在创建CMakeLists.txt文件后,才会出现以下选择项(最后一行那里),这个时候我们选择一下自己的交叉编译工具即可

  • 注意:如果出现以下问题,在ubuntu系统上安装一下cmake(sudo apt install cake)

(8)、配置输入设备(触摸屏及其分辨率)

  • 注意:环境到这就全部安装完了,如果按照步骤来还是不行,建议把文件删了重启再配一遍

四、LVGL工程代码分析

(1)、整个工程目录的说明

1、X86环境(Windows)        

  • 说明
bin目录
    main.exe:lvgl可执行文件,执行它后lvgl项目就会运行起来
    SDL2.dll:windows系统下图形库(小),为了方便lvgl(我们现在用的是本质上是linux的x86环境)显示到window系统上

lv_drivers目录
    解释:显示和输入设备的驱动程序,提供了硬件访问能力(包含了display(显示驱动)和indev(输入设备驱动)、sdl等子目录)

lvgl目录:
    解释:      包含了LVGL图形库的核心源代码(如:控件、绘图、主题等)
    demos:    展示LVGL功能的完整示例程序,用于展示库的强大功能和最佳实践(老手)******
    examples: 简单的代码示例,用于演示特定功能或控件的基本用法(比demo简单,更适合学习)(新手)******
    src:      LVGL核心库的源代码(又是与LVGL文件夹重复,但通常src是更常见的源代码目录名)---参考

CMakeLists.txt
    注意:只要改变了此处的配置,你的工程下次将会全编译一遍
    解释:用来编译我们LVGL工程

lv_conf.h
    注意:只要改变了此处的配置,你的工程下次将会全编译一遍
    解释:用于剪裁和配置LVGL库本身的功能,如启用/禁用控件,设置内存大小、屏幕分辨率等

lv_drv_conf.h 
    注意:只要改变了此处的配置,你的工程下次将会全编译一遍
    解释:用于配置lv_drivers中的驱动程序,如选择使用哪种显示设备(FBDEV)、输入设备(EVDEV)及其参数
    例子:显示屏(间接调用了window系统的sdl库从而使用显示屏驱动)

main.c文件
    解释:你调用lvgl各个库地方。工程第一个执行的文件
2、ARM环境(Linux/开发板)
  • 工程图示

  • 说明:
lv_drivers目录
    解释:显示和输入设备的驱动程序,提供了硬件访问能力(包含了display(显示驱动)和indev(输入设备驱动)、sdl等子目录)

lvgl目录
    解释:包含了LVGL图形库的核心源代码(如:控件、绘图、主题等)
    demos:    展示LVGL功能的完整示例程序,用于展示库的强大功能和最佳实践(老手)******
    examples: 简单的代码示例,用于演示特定功能或控件的基本用法(比demo简单,更适合学习)(新手)******
    src:      LVGL核心库的源代码(又是与LVGL文件夹重复,但通常src是更常见的源代码目录名)---参考

CMakeLists.txt
    注意:只要改变了此处的配置,你的工程下次将会全编译一遍
    解释:用来编译我们LVGL工程

lv_conf.h
    注意:只要改变了此处的配置,你的工程下次将会全编译一遍
    解释:用于剪裁和配置LVGL库本身的功能,如启用/禁用控件,设置内存大小、屏幕分辨率等、

lv_drv_conf.h  
    注意:只要改变了此处的配置,你的工程下次将会全编译一遍
    解释:用于配置lv_drivers中的驱动程序,如选择使用哪种显示设备(FBDEV)、输入设备(EVDEV)及其参数
    例子:触摸屏

main.c文件
    解释:你调用lvgl各个库地方,工程第一个执行的文件

(2)、CMakeLists.txt说明

1、X86环境
# 1.CMake基础设置
cmake_minimum_required(VERSION 3.10)            # 要求cmake最低版本3.10
project(lvgl)                                   # 项目名称为:lvgl
set(CMAKE_C_STANDARD 11)#C11                    # C语言标准设置为C11
set(CMAKE_CXX_STANDARD 17)#C17                  # C++语言标准设置为C17
set(CMAKE_CXX_STANDARD_REQUIRED ON)             # 强制要求使用指定的C++标准

# 2.包含(头文件)目录设置
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR})      # 将项目了添加到包含路径下      

# 3.文件收集
# a.收集所有头文件路径
file(GLOB_RECURSE INCLUDES 
    "lv_drivers/*.h"                            # lv_drivers目录及其子目录的所有.h文件
    "lvgl/demos/*.h"                            # lvgl/demos目录及其子目录的所有.h文件
    "lvgl/*.h"                                  # lvgl目录及其子目录的所有.h文件
    "lvgl/examples/*.h"                         # lvgl/examples目录及其子目录的所有.h文件
    "./*.h"                                     # 当前目录及其子目录的所有.h文件  
    "my_inc/*.h"                                # my_inc目录及其子目录的所有.h文件
)
# b. 收集所有源文件路径
file(GLOB_RECURSE SOURCES  
    "lv_drivers/*.c"                            # lv_drivers目录及其子目录的所有.c文件
    "lvgl/demos/*.c"                            # lvgl/demos目录及其子目录的所有.c文件
    "lvgl/src/*.c"                              # lvgl/src目录及其子目录的所有.c文件
    "lvgl/examples/*.c"                         # lvgl/examples目录及其子目录的所有.c文件  
    "my_src/*.c"                                # my_src目录及其子目录的所有.c文件
)

# 4. 输出和编译设置
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/build)  # 可执行文件输出到工程中的bin目录下
SET(CMAKE_CXX_FLAGS "-O3")                               # 设置C++编译优化级别为O3(最高优化)

# 5. SDL2依赖配置
find_package(SDL2 REQUIRED SDL2)                        # 查找并要求SDL2库
include_directories(${SDL2_INCLUDE_DIRS})               # 添加SDL2的头文件目录 

# 6. 构建目标(创建可执行文件main, 包含所有源文件)
    add_executable(main 
    main.c 
    ${SOURCES} 
    ${INCLUDES}
)

# 7. 定义预处理宏
add_compile_definitions(LV_CONF_INCLUDE_SIMPLE)        

# 8. 链接SDL2库到可执行文件
target_link_libraries(main PRIVATE SDL2 )

# 9.自定义目标(创建一个名为run的自定义目标,用于运行生成的可执行文件)
add_custom_target (run COMMAND ${EXECUTABLE_OUTPUT_PATH}/main)
2、ARM环境
# 1.CMake基础设置
cmake_minimum_required(VERSION 3.1)         # 要求cmake最低版本3.1
project(main)                               # 项目名称为:main
include_directories(.)                      # 将当前目录添加到包含路径

# 2. 添加子目录(LVGL组件)
add_subdirectory(lvgl)                      # 添加lvgl子目录(包含LVGL核心库)
add_subdirectory(lv_drivers)                # 添加lv_drivers子目录(包含驱动程序)

# 3. 交叉编译工具链配置(关键部分)
set(TOOLCHAIN_DIR "/home/mq/arm-linux_gcc-5.4.0/usr")          # 工具链的安装路径
set(CMAKE_C_COMPILER "${TOOLCHAIN_DIR}/bin/arm-linux-gcc")     # 设置C编译器为ARM版本
set(CMAKE_CXX_COMPILER "${TOOLCHAIN_DIR}/bin/arm-linux-g++")   # 设置C++编译器为ARM版本 

# 4. 输出目录设置
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/build)        # 可执行输出到build目录下

# 5.文件收集
# a.收集所有头文件路径
file(GLOB_RECURSE INCLUDES 
    "my_inc/*.h"                                               # my_inc目录及其子目录的所有.h文件
)
# b. 收集所有源文件路径
file(GLOB_RECURSE SOURCES  
    "my_src/*.c"                                               # my_src目录及其子目录的所有.c文件
)

# 6. 构建目标(创建可执行文件main, 包含所有源文件)
add_executable(${PROJECT_NAME}                              
    main.c
    ${SOURCES} 
    ${INCLUDES}
)                         
                                                               # mouse_cursor_icon.c在开发板上不需要,所以可以注释
# 7. 链接库
target_link_libraries(${PROJECT_NAME} PRIVATE 
    lvgl                 # LVGL核心库
    lvgl::examples       # LVGL示例库
    lvgl::demos          # LVGL演示例程
    lvgl::drivers        # LVGL驱动程序
)

(3)、main.c说明

1、X86环境:这是一个使用SDL2作为后端的LVGL模拟器程序,允许在PC上开发和测试LVGL应用程序
// (1)、头文件包含
#define _DEFAULT_SOURCE                 // 启用usleep()等函数
#include <stdlib.h>
#include <unistd.h>
#define SDL_MAIN_HANDLED                // 修复SDL的WinMain问题
#include <SDL2/SDL.h>                   // SDL2图形库

#include "lv_drivers/sdl/sdl.h"         // SDL的驱动程序
#include "lvgl/lvgl.h"                  // LVGL核心库
#include "lvgl/examples/lv_examples.h"  // LVGL示例库(新手)
#include "lvgl/demos/lv_demos.h"        // LVGL演示程序(老手)

#include "my_inc/my_func.h"             // 自己写的库

// (2)、静态函数
static void hal_init(void);


// (3)、主函数
int main(int argc, char **argv)
{
    // 1、初始化LVGL库
    lv_init();

    // 2、初始化SDL的硬件抽象层(比如:显示、输入设备,滴答定时器)
    hal_init();

    // 3、创建演示界面
    // a、使用的是lv_examples的LVGL示例库(新手)
    //  lv_example_switch_1();
    //  lv_example_calendar_1();
    //  lv_example_btnmatrix_2();
    //  lv_example_checkbox_1();
    //  lv_example_colorwheel_1();
    //  lv_example_chart_6();
    //  lv_example_table_2();
    //  lv_example_scroll_2();
    //  lv_example_textarea_1();
    //  lv_example_msgbox_1();
    //  lv_example_dropdown_2();
    //  lv_example_btn_1();
    //  lv_example_scroll_1();
    //  lv_example_tabview_1();
    //  lv_example_tabview_1();
    //  lv_example_flex_3();
    //  lv_example_label_1();

    // b、使用的是lv_demos的LVGLLVGL演示程序(老手)
    lv_demo_widgets();

    // c、自己写的库
    MY_FUNC_Printf();

    // 4、主循环 --- 处理LVGL任务
    while(1) 
    {
        lv_timer_handler();     // 处理LVGL定时器和任务
        usleep(5 * 1000);       // 休眠5ms(约200FPS)
    }

    return 0;
}

// (4)、硬件抽象层初始化函数
/**
 * @brief 硬件抽象层初始化
 * @note  初始化输出设备驱动(SDL2代替了)、输入设备驱动(鼠标(滚动,位置)、键盘)
 * @param None
 * @retv  None
 * 
*/
static void hal_init(void)
{
    // 1、初始化SDL窗口和渲染器(输出显示)
    sdl_init();

    // a、创建显示缓冲区
    static lv_disp_draw_buf_t disp_buf1;
    static lv_color_t buf1_1[SDL_HOR_RES * 100];            // 缓冲区的大小
    lv_disp_draw_buf_init(&disp_buf1, buf1_1, NULL, SDL_HOR_RES * 100);

    // b、配置显示驱动
    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);            
    disp_drv.draw_buf = &disp_buf1;                     // 设置绘制缓冲区
    disp_drv.flush_cb = sdl_display_flush;              // SDL刷新回调
    disp_drv.hor_res = SDL_HOR_RES;                     // 使用SDL定义的水平分辨率
    disp_drv.ver_res = SDL_VER_RES;                     // 使用SDL定义的水平分辨率
    lv_disp_t * disp = lv_disp_drv_register(&disp_drv); // 注册显示驱动

    // c、主题设置                                         // 主颜色:蓝色                  次要颜色:红色                  深色主题                默认字体
    lv_theme_t * th = lv_theme_default_init(disp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), LV_THEME_DEFAULT_DARK, LV_FONT_DEFAULT);
    lv_disp_set_theme(disp, th);                            // 应用主题


    // 2、输入设备初始化
    lv_group_t *g = lv_group_create();
    lv_group_set_default(g);

    // A、鼠标输入设备
    // a、添加鼠标作为输入设备,使用读取电脑鼠标的 'mouse' 驱动程序
    static lv_indev_drv_t indev_drv_1;
    lv_indev_drv_init(&indev_drv_1); /*Basic initialization*/
    indev_drv_1.type = LV_INDEV_TYPE_POINTER;

    // b、该函数将被(库)定期调用以获取鼠标位置和状态
    indev_drv_1.read_cb = sdl_mouse_read;
    lv_indev_t *mouse_indev = lv_indev_drv_register(&indev_drv_1);


    // B、键盘输入设备
    static lv_indev_drv_t indev_drv_2;
    lv_indev_drv_init(&indev_drv_2); /*Basic initialization*/
    indev_drv_2.type = LV_INDEV_TYPE_KEYPAD;
    indev_drv_2.read_cb = sdl_keyboard_read;
    lv_indev_t *kb_indev = lv_indev_drv_register(&indev_drv_2);
    lv_indev_set_group(kb_indev, g);

    // C、编码器输入设备(模拟鼠标滚轮)
    static lv_indev_drv_t indev_drv_3;
    lv_indev_drv_init(&indev_drv_3); /*Basic initialization*/
    indev_drv_3.type = LV_INDEV_TYPE_ENCODER;
    indev_drv_3.read_cb = sdl_mousewheel_read;
    lv_indev_t * enc_indev = lv_indev_drv_register(&indev_drv_3);
    lv_indev_set_group(enc_indev, g);

    
    // // D、设置自定义的鼠标光标
    // LV_IMG_DECLARE(mouse_cursor_icon); /*Declare the image file.*/
    // lv_obj_t * cursor_obj = lv_img_create(lv_scr_act()); /*Create an image object for the cursor */
    // lv_img_set_src(cursor_obj, &mouse_cursor_icon);           /*Set the image source*/
    // lv_indev_set_cursor(mouse_indev, cursor_obj);             /*Connect the image  object to the driver*/
}
2、ARM环境
// (1)、头文件包含
#include <unistd.h>                     // Linux系统调用                
#include <pthread.h>                    // 线程支持 --- 系统编程
#include <time.h>                       // 时间函数
#include <sys/time.h>                   // 系统时间

#include "lv_drivers/display/fbdev.h"   // 显示驱动(FrameBuffer)
#include "lv_drivers/indev/evdev.h"     // 输入设备驱动(evdev)

#include "lvgl/lvgl.h"                  // LVGL核心库
#include "lvgl/examples/lv_examples.h"  // LVGL示例库(新手)
#include "lvgl/demos/lv_demos.h"        // LVGL演示程序(老手)

#include "my_inc/my_func.h"             // 自己写的库


// (2)、宏定义声明
#define DISP_BUF_SIZE (128 * 1024)

// (2)、函数声明
static void hal_init(void);
uint32_t custom_tick_get(void);

// (4)、主函数
int main(void)
{
    // 1、初始化LVGL库
    lv_init();

    // 2、初始化硬件抽象层
    hal_init();


    // 3、创建演示界面
    // a、使用的是lv_examples的LVGL示例库(新手)
    //  lv_example_switch_1();
    //  lv_example_calendar_1();
    //  lv_example_btnmatrix_2();
    //  lv_example_checkbox_1();
    //  lv_example_colorwheel_1();
    //  lv_example_chart_6();
    //  lv_example_table_2();
    //  lv_example_scroll_2();
    //  lv_example_textarea_1();
    //  lv_example_msgbox_1();
    //  lv_example_dropdown_2();
    //  lv_example_btn_1();
    //  lv_example_scroll_1();
    //  lv_example_tabview_1();
    //  lv_example_tabview_1();
    //  lv_example_flex_3();
    //  lv_example_label_1();

    // b、使用的是lv_demos的LVGLLVGL演示程序(老手)
    lv_demo_widgets();

    // c、自己写的库
    MY_FUNC_Printf();

    // 4、主循环 --- 处理LVGL任务
    while(1) 
    {
        lv_timer_handler();     // 处理LVGL定时器和任务
        usleep(5 * 1000);       // 休眠5ms(约200FPS)
    }

    return 0;
}


// (4)、硬件抽象层初始化函数
/**
 * @brief 硬件抽象层初始化
 * @note  初始化输出设备驱动(SDL2代替了)、输入设备驱动(鼠标(滚动,位置)、键盘)
 * @param None
 * @retv  None
*/
static void hal_init(void)
{

    // 1、显示部分(显示屏)
    fbdev_init();

    // a、创建显示缓冲区
    static lv_color_t buf[DISP_BUF_SIZE];
    static lv_disp_draw_buf_t disp_buf;
    lv_disp_draw_buf_init(&disp_buf, buf, NULL, DISP_BUF_SIZE);

    // b、配置显示驱动
    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.draw_buf   = &disp_buf;
    disp_drv.flush_cb   = fbdev_flush;
    disp_drv.hor_res    = 800;
    disp_drv.ver_res    = 480;
    lv_disp_drv_register(&disp_drv);


    // 2、输入部分(触摸屏、鼠标)
    evdev_init();

    // a、配置触摸屏驱动
    static lv_indev_drv_t indev_drv_1;
    lv_indev_drv_init(&indev_drv_1); /*Basic initialization*/
    indev_drv_1.type = LV_INDEV_TYPE_POINTER;
    indev_drv_1.read_cb = evdev_read;
    lv_indev_t *mouse_indev = lv_indev_drv_register(&indev_drv_1);

    // b、注释掉的鼠标光标图标位置(配置鼠标驱动)
    // /*Set a cursor for the mouse*/
    // LV_IMG_DECLARE(mouse_cursor_icon)
    // lv_obj_t * cursor_obj = lv_img_create(lv_scr_act()); /*Create an image object for the cursor */
    // lv_img_set_src(cursor_obj, &mouse_cursor_icon);           /*Set the image source*/
    // lv_indev_set_cursor(mouse_indev, cursor_obj);             /*Connect the image  object to the driver*/

}


// (5)、硬件抽象层初始化函数
/**
 * @brief 自定义时间函数
 * @note  提供从程序启动开始的毫秒数、用于LVGL的动画的定时器系统、需要在lv_conf.h中配置LV_TICK_CUSTOM_SYS_TIME_EXPR
 * @param None
 * @retv  None
*/
uint32_t custom_tick_get(void)
{
    static uint64_t start_ms = 0;
    if(start_ms == 0) {
        struct timeval tv_start;
        gettimeofday(&tv_start, NULL);
        start_ms = (tv_start.tv_sec * 1000000 + tv_start.tv_usec) / 1000;
    }
    
    struct timeval tv_now;
    gettimeofday(&tv_now, NULL);
    uint64_t now_ms;
    now_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000;

    uint32_t time_ms = now_ms - start_ms;
    return time_ms;
}

五、如何将自己的工程加入到LVGL工程中,并应用?

(1)、X86环境

1、创建my_inc和my_src文件夹到LVGL工程中,并在相应的文件夹里创建.h和.c文件

  • my_func.h文件内容:
/**
  ******************************************************************************
  * @file    my_func.h
  * @author  MChine慕青
  * @version V0.0.1
  * @date    2025.09.26
  * @brief   普通的函数
  * 
  ******************************************************************************
  * @attention
  *
  *  本文档只供学习使用,不得商用,违者必究
  * 
  *  个人博客网:    https://blog.csdn.net/2402_83622972?spm=1011.2415.3001.5343
  *  有疑问或者建议:3211735057@qq.com
  * 
  ******************************************************************************
  */

#ifndef __MY_FUNC_H  // 定义以防止递归包含
#define __MY_FUNC_H

// (1)、其它头文件
#include <stdio.h>

// (2)、宏定义(函数、变量、常量)

// (3)、自定义类型(结构体、联合体、枚举、函数指针类型等...)

// (4)、函数声明

// (5)、全局变量声明
extern int MY_FUNC_Printf(void);

// (6)、静态函数定义

// (7)、静态变量定义

#endif
  • my_func.c文件内容:
#include "../my_inc/my_func.h"

/**
 * @brief: 打印数据
 * @note:  None
 * @param: None
 * @retval: 成功:返回0
 *          失败:返回非0
*/
int MY_FUNC_Printf(void)
{
    printf("hello MY_FUNC_Printf!\n");
    return 0;
}
2、在CMakeLists.txt文件中加入你.h和.c的文件路径

3、在main.c中声明并调用即可
  • 声明

  • 调用:

(2)、ARM环境

1、创建my_inc和my_src文件夹到LVGL工程中,并在相应的文件夹里创建.h和.c文件

  • my_func.h文件内容:
/**
  ******************************************************************************
  * @file    my_func.h
  * @author  MChine慕青
  * @version V0.0.1
  * @date    2025.09.26
  * @brief   普通的函数
  * 
  ******************************************************************************
  * @attention
  *
  *  本文档只供学习使用,不得商用,违者必究
  * 
  *  个人博客网:    https://blog.csdn.net/2402_83622972?spm=1011.2415.3001.5343
  *  有疑问或者建议:3211735057@qq.com
  * 
  ******************************************************************************
  */

#ifndef __MY_FUNC_H  // 定义以防止递归包含
#define __MY_FUNC_H

// (1)、其它头文件
#include <stdio.h>

// (2)、宏定义(函数、变量、常量)

// (3)、自定义类型(结构体、联合体、枚举、函数指针类型等...)

// (4)、函数声明

// (5)、全局变量声明
extern int MY_FUNC_Printf(void);

// (6)、静态函数定义

// (7)、静态变量定义

#endif
  • my_func.c文件内容:
#include "../my_inc/my_func.h"

/**
 * @brief: 打印数据
 * @note:  None
 * @param: None
 * @retval: 成功:返回0
 *          失败:返回非0
*/
int MY_FUNC_Printf(void)
{
    printf("hello MY_FUNC_Printf!\n");
    return 0;
}
2、在CMakeLists.txt文件中加入你.h和.c的文件路径

3、在main.c中声明并调用即可
  • 声明:

  • 调用:

六、调用LVGL自带的示例库和演示程序

(1)、示例库

  • 说明:如何找到示例库并获取其功能函数

  • 找到后,复制到主函数上进行调用

  • X86环境、ARM环境都是直接打开即可:

(2)、演示程序

  • 说明:通常来说,使用演示程序的时候,我们看其.h文件,找到有GLOBAL的字样的注释,下面的那个函数一般就是这个演示程序功能集合

  • 找到后,复制到主函数上进行调用

  • 注意:X86环境、ARM环境操作一致:
  • 编译出现的问题:

  • 原因:通常来说是因为LVGL默认将其屏蔽了,因为编译起来会比较大,而且慢
  • 解决方法:

  • 注意:使用music演示程序的时候,此处还需要打开一下

结语:LVGL(Light and Versatile Graphics Library)是一款开源嵌入式图形库,专为资源受限设备设计。其核心优势在于轻量级架构与丰富功能的平衡,支持多种显示驱动和输入设备接口。本期重点解析了整个工程,下期将深入动画效果和主题定制。

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐