准备工具
- Windows Eclipse C/C++ 安装包
- Windows VS2019 安装器:生成离线安装包
- LVGL 在 eclipse 下的仿真源码
- LVGL 在 VS2017 下的仿真源码
一些介绍
LVGL 是开源RTOS(实时操作系统)RT-Thread 上的一个 GUI 软件包,截至目前最新版为 v7.0.2。
官网:lvgl.io
GitHub:github.com/lvgl
相关网站:
CDT 开始
一、安装 Eclipse CDT(C/C++)
-
在官网下载页面安装启动下载工具(进去可选择安装支持C/C++的版本)
在如下界面选择“China - TUNA”源进行下载:
-
如果未安装 Java,打开安装器软件就会有如下提示
在此页面可跳转官网,接着下载和安装包含 Java 1.8.0 的 JDK;
-
配置 JDK 环境变量
需要建立 JAVA_HOME 变量,新增 Path 变量
注意 JDK 13 版本上 jre 和 jdk 已经合在同一安装目录下了,安装后这两个都有;
新建一个系统变量“JAVA_HOME”
在系统”Path“变量中新增一项,写入
%JAVA_HOME%\bin
最后 CMD 验证 Java 是否安装成功:
-
接着继续用安装器软件进行安装
选择”Eclipse IDE for C/C++ Developers“
选择安装路径:
但是安装失败了,心累。。原因是国内网络下载太慢,故直接选国内源下载 CDT:点这里
最后,我解压放在了:
D:\Program Files\eclipse\CDT
二、安装 MinGW
MinGW 提供 Windows 上的 gcc 工具;
在下载页面选择”MingW-W64-builds“进行下载:
按照如下设置安装:
选择安装路径:
安装完成后,将安装目录下的 bin 目录添加到系统 Path:
我添加如下地址:
1
D:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin
验证是否安装成功:
CMD 中输入 gcc -v
显示版本号说明安装成功;
三、安装 SDL2
SDL 2是一个在PC上模拟 TFT 屏和触摸板的库。
点这里下载开发库:
- 复制
x86_64-w64-mingw32\include
中 SDL2 文件夹到x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\include
- 复制
x86_64-w64-mingw32\lib
中所有文件到x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\lib
- [这步在后面操作] 复制
x86_64-w64-mingw32\bin\SDL2.dll
到{eclipse_worksapce}/pc_simulator/Debug/
,放在工程调试目录下,也就是默认的 Eclipse CDT 工程生成目标 exe 的目录;
四、下载 eclipse 环境的 PC 模拟运行源码
-
从 Github 下载工程
这步真的太痛苦了,特别是内部的三个子模块(submodule)总是下载不了,最后是使用 https://notebooks.azure.com/ 进行中转下载的;
1
git clone --recursive https://github.com/lvgl/lv_sim_eclipse_sdl.git
我的工程路径(注意更名):
D:\Projects\lvgl\pc_simulator
-
启动 Eclipse CDT,选择 Workspace
我选择的路径是 D:\Projects\lvgl
-
复制 SDL2.dll 文件到 Eclipse CDT 的工作目录的子目录下
编译后默认会在 Debug 目录下生成 exe 文件,所以放在这个目录下;
复制
x86_64-w64-mingw32\bin\SDL2.dll
到{eclipse_worksapce}/pc_simulator/Debug/
-
导入工程
”File“ -> ”Import“ -> ”General“ -> ”Existing Projects into Workspace“ -> ”在 root directory 选择中拾取 pc_simulator 文件夹“,进行导入;
成功导入的界面如下:
注意,此时还不能点锤子图标编译工程;
-
配置工程
”project“ -> ”properties“ -> ”C/C++ Build“ -> ”Settings“ -> ”Libraries -> Add“ 进行操作,在 SDLmain 和 SDL 之前添加一项 mingw32,注意顺序;
”project“ -> ”properties“ -> ”C/C++ Build“ -> ”Tool Chain Editor“ -> ”Current toolchain“ 修改为 MinGW GCC;
-
编译工程
如果是其他错误,说明工程有问题,请重新下载~
点击“锤子”图标编译工程,会发现找不到“SDL2.h”头文件:
解决方法:
添加一个头文件路径:
${MINGW_HOME}/include
-
运行工程
编译完成后,点击“三角”按钮运行工程,会报如下错误:
需要在工程启动配置中选择生成的 exe 文件:
成功运行如下:
VS2019/VS2022 开始
VS2019/VS2022 离线包的制作
官方的离线安装说明–>点击打开
1.下载 vs引导程序 ,选择你所需的版本下载,我选择了社区版 vs_Community.exe
2.设置命令参数(命令参数说明),启动vs2019引导程序下载
命令如下:
1
<vs引导程序exe> --layout <离线安装包下载的路径> --add <功能模块> --lang <语言>
–layout:指定用于创建脱机安装缓存的目录,也就离线安装包下载的路径,必须是绝对路径;
–add:要添加的一个或多个工作负载或组件 ID。指定多个工作负载和组件时,在每个负载前都使用 --add
命令行开关;
示例:
安装 C++ 的桌面开发(包含 MSVC 编译器):
1
.\vs_community.exe --layout D:\VS2022 --add Microsoft.VisualStudio.Workload.NativeDesktop --includeRecommended --lang zh-CN
安装 C++ 的 Linux 开发(WSL2 需要用到这个组件),建议和 C++ 桌面开发同时制作离线包:
1
.\vs_community.exe --layout D:\VS2022 --add Microsoft.VisualStudio.Workload.NativeCrossPlat --includeRecommended --lang zh-CN
还可用 Free ISO Creator 工具将目标文件夹制作为 ISO 镜像,方便使用;
PC 模拟运行源码
该章节使用 VS2019。如果你是 VS2022 请看个大概,应该也是大同小异;
- 下载仿真源码 LVGL 在 VS2017 下的仿真源码
- 使用 VS2019 打开项目(2017),提示升级,按默认升级工程
运行效果如图:
LVGL 移植方法
参见官方博客
一、下载 lvgl 库
下载地址: github.com/lvgl/lvgl
国内码云: gitee.com/mirrors/lvgl
下载好的根目录 lvgl
是我们的库目录;
二、将库复制到项目
从库中复制 lvgl/lv_conf_template.h
文件放到库根目录的同级目录并重命名为 lv_conf.h
;
三、修改配置文件
首先启用配置文件 lv_conf.h
,把该文件顶部的 if 0
改为 if 1
;
修改 lv_conf.h
文件,至少修改这三个地方:
- LV_HOR_RES_MAX 显示横向像素
- LV_VER_RES_MAX 显示纵向像素
- LV_COLOR_DEPTH 显示色彩深度(可选 1、8、16、32)
单色屏的配置可参考这篇官方博客,参考上面的宏定义更改即可;
四、创建我的应用程序
-
在我的应用程序中引用
lvgl/lvgl.h
头文件;1
#include "lvgl/lvgl.h"
-
初始化 LVGL
1 2
/*Initialize LVGL*/ lv_init();
-
创建和注册显示缓冲区
1 2 3
static lv_disp_buf_t disp_buf; static lv_color_t buf[LV_HOR_RES_MAX * 10]; lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);
-
创建和注册显示驱动
1 2 3 4 5 6 7
monitor_init(); //显示设备的初始化(配置、清屏等) lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); disp_drv.flush_cb = my_disp_flush; disp_drv.buffer = &disp_buf; lv_disp_drv_register(&disp_drv);
其中 my_disp_flush 是显示函数,需要实现中间的打点函数
my_set_pixel(x, y, *color_p)
;color_p 指针指向的是显示缓冲区,每打一个点需要右移色深的位数;可能你还需要在这片区域全部打点完成后,调用一次你的屏幕刷新函数 my_monitor_flush(或者在 lvgl 配置中用宏指定你的刷新函数,这样只用在函数尾部保留 lv_disp_flush_ready 即可);
1 2 3 4 5 6 7 8 9 10 11
void my_disp_flush(lv_disp_t * disp, const lv_area_t * area, lv_color_t * color_p){ int32_t x, y; for(y = area->y1; y <= area->y2; y++) { for(x = area->x1; x <= area->x2; x++) { my_set_pixel(x, y, *color_p); color_p++; } } //my_monitor_flush(); //在这里刷新一次,或者宏定义中指定刷新函数 lv_disp_flush_ready(disp); }
-
创建显示
如下是创建了一个 “Hello world” 文本标签,并放在中心;
1 2 3 4
/*Create a "Hello world!" label*/ lv_obj_t * label = lv_label_create(lv_scr_act(), NULL); lv_label_set_text(label, "Hello world!"); lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0, 0);
-
5ms 执行一次
1 2 3 4 5
while (1) { lv_task_handler(); usleep(5 * 1000); lv_tick_inc(5); }
五、打印测试
单色屏将驱动改为如下,把 color_p 指向的内容全部打印出来:
1
2
3
4
5
6
7
8
9
10
11
12
void my_disp_flush(struct _disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
{
int32_t x, y;
for(y = area->y1; y <= area->y2; y++) {
for(x = area->x1; x <= area->x2; x++) {
printf("%d", *color_p);
color_p++;
}
printf("\n");
}
lv_disp_flush_ready(disp_drv);
}
结果:
你也可以尝试打印下坐标,看看 my_disp_flush 执行了几次,写入了哪些地方;