# lvgl-simulator-repo **Repository Path**: thewon/lvgl-simulator-repo ## Basic Information - **Project Name**: lvgl-simulator-repo - **Description**: LVGL 模拟器框架仓库 - **Primary Language**: C - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 4 - **Forks**: 0 - **Created**: 2022-01-05 - **Last Updated**: 2023-07-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # LVGL Simulator ### 介绍 虽然 LVGL 官方提供了多种模拟器环境,但是,一个是没有我熟悉的环境,一个是它们都没有考虑代码复用。 本文讲解了三种模拟器环境,相同的是都使用了 Mingw32 编译器,第一种使用 SDL 但是没有 IDE;第二种使用了 Qt Creator 做 IDE 但是还是依赖 SDL;第三种是全新的用 Qt5 做的模拟器。 ### 框架约定 本模拟器框架实现基于以下几点: 1. 最大限度的代码复用,多个应用共用相同的源码。 2. 灵活切换 lvgl demo drivers sdl 等等版本。在代码复用的基础上,允许不同应用使用不同版本的 lvgl drivers sdl 等。 ### 测试环境 编译器,Mingw32 7.3.0 终端 PowerShell IDE Qt Creator 4.8.2 SDL 2.0.18 Qt 5.12.2 ### 准备工作 - 从 https://github.com/lvgl/lvgl 下载 LVGL 核心源码。并解压到工作目录。 - 从 https://github.com/lvgl/lv_drivers 下载 LVGL 驱动。并解压到同上目录。 - 从 https://github.com/lvgl/lv_demos 下载 LVGL demo。并解压到同上目录。 - 从 https://www.libsdl.org/download-2.0.php 下载 mingw 版本 sdl2。并解压到同上目录。 - 下载安装 mingw 版本 qt,或者单独安装 mingw 编译器。设置 mingw32-make.exe 文件所在路径到环境变量。 ### Mingw32 SDL2 console 环境 mingw 对一些 makefile 语法不识别,所以需要修改 lvgl 源码中的 mk 文件。 #### 进入 LVGL 核心源码目录,修改 lvgl.mk 文件,注释掉 examples 引用。 #### 修改 src/extra/extra.mk 文件 ``` # CSRCS += $(shell find -L $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/extra -name \*.c) CSRCS += lv_extra.c DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/extra VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/extra CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/extra" include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/extra/layouts/layouts.mk include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/extra/libs/libs.mk include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/extra/others/others.mk include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/extra/themes/themes.mk include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/extra/widgets/widgets.mk ``` 因为 find 命令在这里用法不对,但我也不知道改成哪个命令,只能换成复杂的写法。靠 include 和 CSRCS 把所有 c 文件一个个添加到编译。 类似的修改还有 extra 目录下的所有子目录,demos drivers,在此不再赘述,详见仓库吧。 #### 创建模拟器目录 从 LVGL 源码目录下拷贝 `lv_conf_template.h` 并重命名 `lv_conf.h`。 从 lv_drivers 拷贝 `lv_drv_conf_template.h` 并重命名 `lv_drv_conf.h` 从 lv_demos 拷贝 `lv_demo_conf_template.h` 并重命名 `lv_demo_conf.h` #### 添加 Makefile 文件 实现顶层 Makefile 定义编译选项以及引用其他各个模块的 mk 文件。例如必须定义一些路径,包含其他模块的 mk 等等。 ``` LVGL_DIR = F:/lvgl SDL2_DIR = $(LVGL_DIR)/SDL2-2.0.18/i686-w64-mingw32 SIMU_DIR = $(LVGL_DIR)/simulator-8x_mingw LVGL_DIR_NAME = lvgl-8.1.0 LV_DRIVERS_DIR_NAME = lv_drivers LV_DEMOS_DIR_NAME = lv_demos ... include $(SIMU_DIR)/main/main.mk # include $(LVGL_DIR)/lvgl.mk include $(LVGL_DIR)/$(LV_DRIVERS_DIR_NAME)/lv_drivers.mk include $(LVGL_DIR)/$(LV_DEMOS_DIR_NAME)/lv_demo.mk ``` 其中,每一个部分可以共存多个版本,单独修改 XXX_DIR_NAME 可能轻易改变版本。 > 注:笔者已经动态编译了 LVGL ,所以 `include $(LVGL_DIR)/lvgl.mk` 行被注释了。 #### 添加 main.c 文件 初始化 lvgl 和 sdl ,调用 demo 的入口函数。 ``` /*Initialize LittlevGL*/ lv_init(); /*Initialize the HAL for LittlevGL*/ hal_init(); #if LV_USE_DEMO_WIDGETS lv_demo_widgets(); #endif ``` #### 修改配置文件,编译 demo。 ### Mingw32 SDL2 QtCreator 环境 有了上面的工作,在 QtCreator 下的就好弄了。但笔者已经动态编译了 LVGL 。pro 文件也可以简化很多。 ``` INCLUDEPATH += ./ F:/lvgl F:/lvgl/lvgl-8.1.0 F:/lvgl/SDL2-2.0.18/i686-w64-mingw32/include LIBS += -L"F:/lvgl/simulator-8x_qtcreator" LIBS += -llvgl8 -lSDL2 -lm DEFINES += LV_CONF_INCLUDE_SIMPLE LV_LVGL_H_INCLUDE_SIMPLE LV_DEMO_CONF_INCLUDE_SIMPLE SOURCES += \ main/main.c \ main/mouse_cursor_icon.c \ ../lv_drivers/sdl/sdl.c \ ../lv_demos/src/lv_demo_widgets/lv_demo_widgets.c \ ../lv_demos/src/lv_demo_widgets/assets/img_clothes.c \ ../lv_demos/src/lv_demo_widgets/assets/img_demo_widgets_avatar.c \ ../lv_demos/src/lv_demo_widgets/assets/img_lvgl_logo.c HEADERS += \ lv_conf.h \ lv_demo_conf.h \ lv_drv_conf.h \ ../lv_drivers/sdl/sdl.h \ ../lv_demos/src/lv_demo_widgets/lv_demo_widgets.h ``` > 注:每个 demo 添加一个 pri 文件会极好。 ### Qt5 模拟器 实现的关键是写一份驱动,主要改动 lv_drv_conf.h 和 mian.c 两个文件 lv_drv_conf.h 添加 QT 模拟器驱动配置项 ``` /* QT based drivers for display, mouse, mousewheel and keyboard*/ #ifndef USE_QT5 # define USE_QT5 1 #endif #if USE_QT5 # define QT_HOR_RES 800 # define QT_VER_RES 480 /* Scale window by this factor (useful when simulating small screens) */ # define QT_ZOOM 1 #endif ``` > 注:未实现 DOUBLE_BUFFERED 和 DUAL_DISPLAY main.c 文件改动比较大,main 函数开头和结尾添加 ``` #if USE_QT5 QApplication app(argc, argv); QApplication::setOrganizationName("TFT Simulator"); QApplication::setApplicationName("TFT Simulator"); #endif // USE_QT5 ... #if USE_QT5 return app.exec(); #else return 0; #endif // USE_QT5 ``` 之前的 while 循环要删掉。 hal_init 函数里显示、键盘、鼠标回调函数改成 qt 驱动提供的回调函数。 驱动部分实现了一个主窗口类,笔者使用 `QMainWindow` 实现的,用 `QWidget` 实现应该也是可以的。 其它的实现细节请移步仓库源码。上一个效果图 ![](https://thewon.gitee.io/images/lvgl.gif) ### 编译 LVGL 动态库 因为上面 Qt 模拟器使用了 LVGL 动态库,思来想去,还是几句话写写笔者怎么编译的 LVGL 动态库吧。 - 首先,对 LVGL 源码部分做些修改,参照 “Mingw32 SDL2 console 环境” 部分的修改。 - 然后对 Makefile 进行改动,去掉 demos、drivers、main.c ,总之,只留下 lvgl 核心源码。 - 链接目标文件阶段增加 “-shared” 选项。 相对来讲,和编译 demo 的过程是一样的。最关键的区别是去 `main` 添 `shared` 完整 makefile 详见仓库根目录下的 Makefile.lvgl 文件