目录
~~ 约定 ~~
在文中的各个操作阶段,会适当提示你:编译。
请在各阶段提示位,谨遵执行。这样操作,能清晰地定位移植过程中的问题所在。
只要操作没错漏,都能成功开跑lvgl。
一、lvgl 简述
二、复制一个stm32工程
准备好一个stm32的工程,这个工程要求如下:
1、硬件的要求
- 芯片资源:flash>128k, ram>64k; (lvgl至少占用: flash>64k, ram>16k);
- 与芯片型号无关,f1、f4、h7等系列的芯片,满足上述资源的都行;
- 不建议使用常用的stm32f103c8,资源太小,裁剪难度大,强行移植了也会很卡。
- 显示屏:建议使用16位色深的彩屏, 1.44寸、2.8寸、4.3寸等等;
- 不建议使用常用的0.96寸oled屏,指甲大小的单色屏,耗100k资源去撑它,没搞头。
2、软件的环境
- 库支持方式:标准库、寄存器、手撸hal库、cubemx生成的hal库、ll库,都可以;
- 开发环境:keil、cubeide,都可以;
3、stm32工程的要求
- 堆栈大小:heap、stack,设置为:0x1000;
- 准备:画点函数,用于后面注册lvgl的显示功能;
- 准备:触摸检测函数 (返回:0-未按下、1-按下)、坐标获取函数,用于注册lvgl的触屏功能;
上述,是lvgl最基础的资源需要。
如果有一项你没看懂,就先把它盘透,回头再盘lvgl。
本篇,复制了开发板的一个示例作移植的基础工程:"显示屏_2.8寸_触摸检测_xpt2046"。
4、复制源工程后,测试是否可用
- 编译:以确保 0 error;
- 烧录:以确保能正常运行,触摸和显示都正常(忽视下图中的文字显示,非必要)。
- 对于这个工程,最低限度,你必须已懂得调用函数,实现如下图画线效果。
三、下载 lvgl
尽管lvgl已发布了v9.0、v9.1等,但v8.3版,是目前最广泛使用的版本。
v8.3版本,网上教程资源众多、移植简单;
更重要的:多款主流可视化设计工具,都支持lvgl的v8.3版本!
因此,强烈推荐使用v8.3版本。
官方下载链接:https://github.com/lvgl/lvgl
1、选择版本
2、下载
3、下载后,解压缩得到文件夹:lvgl-release-v8.3
四、源文件 裁剪
上一步得到的源文件夹: lvgl-release-v8.3。
里头文件众多:源代码、帮助文档、官方示例等等。
不用发晕,需要用到的,仅仅是:3个文件夹 + 2个h文件。
1、新建一个文件夹
因为lvgl源代码中的头文件,使用了相对路径,如在 "lvgl.h" 中:
为了令移植后的文件能直接使用这些相对路径,我们复制文件时,按下方目录结构来操作:
- 在你喜欢的硬盘位置,新建文件夹:lvgl
- 在源文件夹中,把下图选中的 3个文件夹、2个h文件, 复制到新建的 lvgl文件夹中;
完成后,"lvgl" 文件夹,是这个样子的:
提醒:
- 网上好些教程,在keil工程目录下新建 middlewares 文件夹,在里面再新建lvgl文件夹。
- 如果你使用的是标准库的工程,或者是自己手撸建立的hal库工程,都可以那样操作。
- 但是,如果使用cubemx、cubeide生成的工程,就不要使用 “middlewares” 作文件夹名称。
- 因为 "middlewares",刚好是cubemx可能生成的文件夹,用来存放中间件,如:freertos、fatfs等支持文件。如果你没有使能这些中间件,那么 ,cubemx重新生成工程时,"middlewares"文件夹就会被认为不需要了,被删除掉。
2、修改 lv_conf.h 文件名
在 "lvgl" 文件夹中,有 h文件:"lv_conf_template.h",是lvgl配置参数的重要文件。
- 原文件名:“lv_conf_template.h”,修改为: "lv_conf.h";
完成后, "lvgl" 文件夹,是这个样子的:
3、删除不需要的文件夹
打开文件夹:"lvgl / examples":
- 只保留 porting 文件夹,其它的文件夹和文件,都删除掉。
完成后,文件夹"lvgl / examples",是这个样子的:
4、修改 porting 里面的文件名称
打开刚才的 "porting" 文件夹:
- 6个文件的名称,都删除 "_template" 字样
完成后,"porting" 文件夹,是这个样子的:
好了,现在 "lvgl" 文件夹,已经是我们需要的效果。
这个 "lvgl" 文件夹,以后可以复制给各类的工程使用,不限于stm32的工程,通用。
五、stm32工程添加 lvgl 文件
现在,我们开始给stm32工程添加lvgl源文件。
1、复制 lvgl 文件夹,粘贴到stm32工程目录下。
每个人的工程文件夹,几乎都不一样,没关系的。
- 把上一步做好的 lvgl 文件夹,复制到工程目录下
完成后,是这个样子的:
2、打开keil,在工程里,添加4个文件夹(groups);
文件夹名称 (groups) | 用于存放什么文件 |
lvgl_mygui | 用户自己的界面代码文件、官方demo等 |
lvgl_conf | lvgl 的两个h文件 |
lvgl_porting | lvgl 的接口文件, 如显示、触摸屏、键盘等 |
lvgl_src | lvgl 的所有底层c文件 |
操作过程、完成后,是这个样子的:
提示:
- 操作完成后,先点击ok,保存操作。
- 网上好些教程会新建近10个group, 分开存放各个子功能文件。4个文件夹够了,简单直观。
- 这里用下划线作名称分界线。尝试过使用“ / ”, 感觉没下划线直观。你可以用自己喜欢风格。
添加完后,再编译一次,确认:0 error, 不要觉得事多。
3、为每一个文件夹组(groups),添加需要的文件
特别地:这一步,是整个移植里,最容易出错的步骤!务必在开始操作前,反复看两次本步图解。
很多人在后面的编译中,出现error,提示缺少文件,基本是在这一步把某个文件添加漏了。
提醒:一点也不难,但务必细心地操作。
操作过程,步骤如下:
重要:每个文件夹(group),需要添加的文件,如下表:
文件夹 (group) | 添加文件 |
---|---|
lvgl_mygui | 不用添加。 |
lvgl_conf | 共2个文件:"lvgl"下的: lv_conf.h、lvgl.h(要选择文件类型才能看到h文件) |
lvgl_porting | 共4个文件:"lvgl/ examples / porting" 下的:lv_port_disp.c 、lv_port_disp.h、 lv_port_indev.c、lv_port_indev.h;(要选择文件类型才能看到 h 文件) |
lvgl_src | 近200+的c文件:"lvgl / src" 下的所有 c 文件; 重点:包括src里所有子、子子文件夹的 c 文件. 不用添加h和mk文件. |
在操作 lvgl_conf 和 lvgl_porting 添加h文件时,需要在选择窗口中,把文件类型设置 *.*:
细细解释一下 lvgl_src 的添加,:
- src文件夹下,会有多重的子文件夹,必须慢慢地、把每一个子文件夹的c文件全部添加进来;
- 只须添加 c 文件,不用添加其它类型的文件,如:h、mk等 (技巧:文件类型配置为 *.c );
- 添加完毕后,必须点击"ok"保存, 不然,你会后悔。
完成后,keil的工程文件管理器,是这个样子的:
4、添加头文件路径
打勾c99,并,添加3个头文件路径:
- 添加:lvgl 文件夹的路径
- 添加:lvgl\src 文件夹的路径
- 添加:lvgl\examples\porting 文件夹的路径
操作过程、完成后,是这个样子的:
5、编译验证
来到这一步,需要用到的文件,已经添加完毕。
我们在这里必须先编译一次,以验证文件是否都添加完整。
正常情况下,编译后: 0 error。会有一大堆 warning,不用管,不影响的。
如果,编译后有 error 报错:
- 检查是否打勾: c99
- 先检查头文件路径 ,是否添加完成;
- 排除上述两个原因后,编译还有报错,那就是添加文件那一步有遗漏:删除4个group里的文件,再次重新添加。
友情提示:
如果有error未解决,必须要解决了,再继续操作下文 。
别心急!何况,下文没有你上面error的解决方法。多点耐心就好。
六、注册 显示
1、启用 lv_conf.h
双击打开 lv_conf.h,对以下内容进行修改,以启用此文件。
- 第15行,原:#if 0,修改为:#if 1
完成后,是这个样子的:
2、启用 lv_port_disp.h
双击打开 lv_port_disp.h,修改以下内容,以启用此文件:
- 第7行,原:#if 0, 修改为:#if 1
- 第22行,原:“lvgl/lvgl.h", 修改为:”lvgl.h"
完成后,是这个样子的:
3、启用 lv_port_disp.c
双击打开 lv_port_disp.c,修改以下内容,以启用此文件:
- 第7行,原:#if 0, 修改为:#if 1
- 第12行,原"lv_port_disp_template.h", 修改为:"lv_port_disp.h"
完成后,是这个样子的:
4、添加 lcd 驱动的头文件
在 lv_port_disp.c中:
- 第14行,插入你的lcd驱动文件,如:#include "bsp_lcd_ili341.h",写上你的h文件。
- 第20行、第25行,是显示屏的宽、高度。查看你的显示屏参数,填写实际像素即可。
插入lcd的头文件,目的是为了让这个c文件,能调用lcd的: 画点函数;
注意一个:lvgl默认使用横屏的方式,这一点要注意,别写反了。
完成后,是这个样子的
5、选择创建缓存的方式,3选1
还是在 lv_port_disp.c 中,向下滚动,
(会出现很多错误提示,不用管。也可以先编译一次,让刚才启用的h文件生效,错误就会消失)
第86行到101行,lvgl 提供了创建显示缓冲区的3种方式,这里,必须3选1。
绝大多数情况下,使用第1种方法,即:只创建1个缓冲区;
- 注释掉第90~101行,即:不使用第2和第3种方法;
完成后,是这个样子的:
6、关联 画点函数
还是在 lv_port_disp.c 中,向下滚动,找到disp_flush( )函数:
- 第173行,替换你的 lcd 的画点函数; 参数:x坐标、y坐标、16位颜色值。
- 小编用的画点函数:lcd_drawpoint( x, y, color_p->full) ;
你的画点函数,可能和小篇所用的不一样,照样画瓢即可。
完成后,是这个样子的:
这里给lvgl一个画点函数后, lvgl就能完成需要的显示操作了。
至此,显示部分的修改、注册,已完成。
点击编译:0 erros。
切记:如果有error未解决,必须要解决了,再继续操作下文 。
七、注册 触摸屏
1、启用 "lv_port_indev.h"
打开"lv_port_indev.h", 修改以下内容,以启动此文件:
- 第8行,原:#if 0, 修改成:#if 1
- 第20行,原:"lvgl / lvgl.h", 修改成:"lvgl.h"
完成后,是这个样子的:
2、启动 "lv_port_indev.c"
打开"lv_port_indev.c", 修改以下内容,以启动此文件:
- 第 7行,原:#if 0, 修改为:#if 1
- 第12行,原:“lv_port_indev_template.h", 修改为:"lv_port_indev.h"
- 第13行,原:"../../lvgl.h",修改为:"lvgl.h"
完成后,是这个样子的:
3、添加 触屏 的驱动头文件
还是在 "lv_port_indev.c" 中:
- 第14行,插入:#include "触摸屏的头文件",小编这边是:#include "bsp_xpt2046.h"
目的是为了让这个c文件,能调用触屏的:触摸状态检测函数、坐标获取函数;
完成后,是这样子的:
4、注释掉不需要的输入任务注册
还是在 "lv_port_indev.c" 中,
向下滚动至大约70行,找到输入注册函数:lv_port_indev_init( ),
函数内有5种输入方式的任务注册:触屏、鼠标、键盘、编码器、物理按键;
- 保留触摸屏输入的任务注册;
- 其它4种输入任务的注册,注释掉,;
完成后,是这个样子的:
5、添加 触摸检测函数
还是在 "lv_port_indev.c" 中,
向下滚动到大约209行,找到触摸检测函数:touchpad_is_pressed(),
这个是:触屏状态检测函数,函数返回:0-未按下、1-按下;
- 第213行,原 return false, 注释掉;
- 第212行,原来是空行,插入:return xpt2046_ispressed();
这个是魔女开发板所提供的触屏检测函数,返回值已符合:0-未按下、1-按下;
你可以替换成你的方式,如原子哥的变量值方式。各施各法,只要符合函数要求,都行;
完成后,是这个样子的:
6、添加 坐标获取函数
还是在 "lv_port_indev.c" 中,
在刚才触摸检测函数的下方,大约217行,找到坐标获取函数:touchpad_get_xy();
本函数的作为:使lvgl能够获取到触摸按下时的x、y坐标;
- 第221行, 修改为:(*x) = xpt2046_getx();
- 第222行, 修改为:(*y) = xpt2046_gety();
同上,可以各施各法,用各种方法赋值。
完成后,是这个样子的:
至此,触摸屏的注册,已经完成。
点击编译:0 error。
八、添加 lvgl 的文件引用
之前的几个部分,已修改完成了lvgl显示、触摸支持。
现在,正式在工程中“应用” lvgl。
1、给工程,添加 lvgl 的头文件
打开 main.c,在顶部, #include 三个头文件(复制下面三行):
#include "lvgl.h" // 它为整个lvgl提供了更完整的头文件引用
#include "lv_port_disp.h" // lvgl的显示支持
#include "lv_port_indev.h" // lvgl的触屏支持
完成后,是这个样子的:
2、初始化lcd、触摸屏
在main函数内、 while 循环之前,调用lcd初始化函数、触摸屏初始化函数。
删除原示例中多余的显示测试代码、触摸测试代码。
下图,是小篇所用开发板的lcd驱动函数:
lcd_init(); // 初始化 lcd
lcd_setdir(1); // 设置lcd的显示方向:横屏
xpt2046_init(xlcd.width, xlcd.height, xlcd.dir); // 初始化触摸屏
记得前几步时,我们没有像其它教程那样,给disp_init() 填入lcd的初始化函数。
现在,随着其它的设备,把初始化放在一起,更符合习惯、更直观。
完成后,是这个样子的:
3、初始化lvgl、显示、触屏
在硬件的初始化代码之后,进行lvgl的初始化(复制下面3行):
lv_init(); // lvgl 初始化
lv_port_disp_init(); // 注册lvgl的显示任务
lv_port_indev_init(); // 注册lvgl的触屏检测任务
完成后,是这个样子的:
4、显示按钮控件、文本控件
在lvgl的初始化之后,添加lvgl控件 ,以测试lvgl的显示:
- 添加一个按钮
- 为按钮添加文本
- 添加一个独立的标签文本
具体代码如下:
// 按钮
lv_obj_t *mybtn = lv_btn_create(lv_scr_act()); // 创建按钮; 父对象:当前活动屏幕
lv_obj_set_pos(mybtn, 10, 10); // 设置坐标
lv_obj_set_size(mybtn, 120, 50); // 设置大小
// 按钮上的文本
lv_obj_t *label_btn = lv_label_create(mybtn); // 创建文本标签,父对象:上面的btn按钮
lv_obj_align(label_btn, lv_align_center, 0, 0); // 对齐于:父对象
lv_label_set_text(label_btn, "test"); // 设置标签的文本
// 独立的标签
lv_obj_t *mylabel = lv_label_create(lv_scr_act()); // 创建文本标签; 父对象:当前活动屏幕
lv_label_set_text(mylabel, "hello world!"); // 设置标签的文本
lv_obj_align(mylabel, lv_align_center, 0, 0); // 对齐于:父对象
lv_obj_align_to(mybtn, mylabel, lv_align_out_top_mid, 0, -20); // 对齐于:某对象
完成后,是这个样子的:
有没有一种感觉:lvgl的代码,与我们平时写的stm32的代码,风格区别相当大?
特别是刚玩嵌入式的兄弟,很不习惯:函数名称长、参数多......。
没事,不用太在意。
多读,多写写,慢慢就会喜欢上它这种“编码思维”:一致性、模块化、可配置性、可维护性!
好了,至此,已经编写好让lvgl显示控件的代码,离开跑只差两步操作!
不急,先编译一下!
0 error, 35 warning !!
只要是 0 error,就可以了!那些35个警告的,不用管它。
如果出现错误:
1:少量的错误,应该是某个操作错了,向上翻动编译信息,找到第1个 error, 按它的描述排查、对比刚才的操作。
2:数量众多的错误,如几十个!向上翻动编译信息,应该会看到一片相同的错误描述,如下图:
错误描述:error:l640e:no space in execution regions with .any....
这种情况就是内存不足了,程序需要的内存大于芯片ram。
具体解决:下面的裁剪方法,可以参考。
九、lvgl 心跳、任务刷新
按目前的移植进度,我们只差两个时间任务要处理:
-
第1个时间任务:为lvgl提供准确的心跳。必须间隔精准地,调用时基函数:lv_tick_inc(),俗称心跳,让lvgl精准地知道时间的流逝;
-
第2个时间任务:间隔5ms左右,调用周期性任务函数: lv_timer_handler() ,它的作用是检查所有注册任务的时间戳,执行那些已经到期的任务,如:屏显更新、动画更新、触控、定时器事件等;
1、给lvgl一个心跳时基
(概念上,有点类似freertos的1ms时基。)
lvgl心跳函数(时基函数):lv_tick_inc(),每隔1ms调用一次;
这个函数对于图形界面的流畅运行比较重要,它令 lvgl 知道执行任务时流逝的时间。
如果 lv_tick_inc() 调用间隔不准确,可能会导致显示卡顿、任务处理不及时。
特别地,不建议使用滴答时钟systick产生这个时基,因为它常常需要被用于rtos等。
建议使用tim产生1ms中断,设置它的中断为高优先级,通过中断函数调用lvgl心跳时基。
可以使用各个tim、各种方法,产生1ms中断,如寄存器操作、标准库、手撸hal等等。
本篇,通过cubemx配置tim6,产生1ms中断。
( tim6 1ms中断,操作 5-1:设置tim6时基 )
- 使能tim6,打勾 activated即可。
- 设置分频值(psc):f103是72-1, f407是84-1。为什么要减1,因为执行时:寄存器值+1。
- 设置周期值(arr):1000-1。
通过设置这两个参数,可以把周期设置为1ms,具体的计算方法:
周期时长 = psc/运行时钟*arr = 84/84000000*1000 = 0.001秒
( tim6 1ms中断,操作 5-2:设置tim6的中断 )
设定好了周期,还要使能中断,令每一周期结束时产生一次中断。
- 打勾tim6的中断,并设置中断抢占级为:0,(默认也是0);
tim6已设置好了。
(tim6 1ms中断,操作 5-3:cubemx 生成)
keil,先点击保存,不要嫌麻烦。如果之前最后的操作是编译,那么,它就已自动保存了。
现在点击cubemx里的生成按钮,令刚才的配置更新到工程里面。
切换为keil,如果刚才没有关闭,这时它就弹窗提示代码有更新,点击“是”, 当前工程即可更新代码。
( tim6 1ms中断,操作 5-4:开启tim6 )
回到main.c中,调用hal函数:启动tim6,并使能它的周期更新中断。
- hal_tim_base_start_it(&htim6);
注意,这一行,建议插入在lvgl的初始化之后,如下图中位置 。
完成后,是这个样子的:
( tim6 1ms中断,操作 5-5:中断回调函数 )
编写周期更新中断的回调函数中,在里面调用lv_tick_inc( ),给lvgl提供心跳;
本篇,在main.c的尾部,在/* user code begin 4 */ 的配对注释内,编写这个函数;
完成后,是这个样子的:
编写回调函数后,编译!
0 error, 35 warning。
2、每隔5ms左右,调用任务刷新函数: lv_timer_handler()
简单地理解,每5ms让lvgl刷新(干活)一次。
让lvgl定期检查所有已注册任务的时间戳,执行那些已经到期的任务,如刷屏、检测触摸等;
官方的描述:大约5ms左右、在while循环中调用;
- 在msin.c的while中,每隔5ms调用:lv_timer_handler()
特别地:切勿通过tim中断调用它,因为它的执行时间有点长,避免霸占中断资源。
完成后,是这样子的:
至此,两个时间任务的,也处理完毕!
lvgl的移植,已全部完成 !
点击编译:0 erros !
开始烧录吧!
一百多k的程序,烧录时间有点长,大约耗时十来秒。
运行效果如下:
显示正常,显示部分已移植成功!
触摸正常,按下时按钮的状态生产了变化,触摸部分也移植成功!
(已移植成功的老乡,先别走!!建议耐心读完下半部分,干货!!)
5、触摸没反应的排查
一次就移植成功的机率太低太低了。
更大可能出现的情况是:显示正常,触摸没反应!
正常情况下:如上图gif 所显示的,点击按钮时,按下、释放,按钮的状态是不一样的。
如果按钮在按下时没有反应、不会产生状态变化 ,主要排查3项:
- 触摸检测:lv_port_indev.c 第209行:touchpad_is_pressed(),返回值是否相符;
- 坐标获取:lv_port_indev.c 第217行:touchpad_get_xy();
- 坐标不符:触摸屏坐标与显示屏坐标不符,需要重新校准;
如果已按上面(七-7)的步骤,在touchpad_get_xy()函数预埋了画点函数,如下图:
配合这个预埋,现在可以这样测试:在显示屏空白的地方,用指甲,慢慢地,划几道线。
- 如果划不出黑线(断断续续的黑线),排查硬件初始化,和上面的1、2两项;
- 如果划出了黑线,但是坐标不对,那就是触摸屏需要重新校准了,即上面的3;
注意:有时候,黑点黑线,是被画在了屏的边上,堆在一起了,要注意细看。
关于第一种错误,检查:触摸检测函数返回值,是否正确。
- 用printf大法!把触摸返回值、坐标获取值,printf出来,在串口助手上观察;
- 必须确认:触摸按下时,有返回值,而且返回值正确(0-未按下、1-按下),
- 如果返回值对了,再确认坐标获取是否正常,查对printf出来的数据。
- 最后,就是从本篇开头,一步步对归照,是哪一步出现漏做了。
关于第二种,重新校准
- 不同的开发板,问一问屏的商家,如何重新校准触摸屏;
- 本篇使用的“魔女开发板”在这个工程中,使用串口助手发送:xpt2046, 即可进入重新校准。进入了校准界面后,用笔尖,点击依次出现的四个十字线,即可完成重新校准。
十、控件的事件添加、响应处理
当上述问题都解决了,按钮能正常触控后,再操作这一步部分。
lvgl的学习,可以大概地为分两部分:界面绘制、事件处理。
1、界面的绘制
我们这里不啰嗦,上面的示范代码,你能看个明白即可,无需深挖。
因为lvgl的界面绘制,更常规的操作:使用可视化工具进行设计,再把界面工程移植回stm32。
2、事件处理
可视化工具,能帮我们处理好:控件生成、布局、屏幕切换等;
但是,不能处理stm32上的事,如按下按钮,发送某can通信等;
这些,都是需要回到keil或者cubeide里,自行增加编写的。
所以,特意增加一章,示范:事件的添加、编写响应处理函数。
明白了响应和处理的操作,后面使用可视化工具时,能有更好的理解。
下面,以按钮的点击为例,示范:事件添加、响应处理。
回到main函数,在添加按钮的那三行代码下方,增加一行,为控件添加事件:
- lv_obj_add_event_cb(mybtn, mybtn_event, lv_event_clicked, null);
这行有点复杂,对参数稍作解释:
mybtn:控件的名称(不限于按钮);
mybtn_event:事件响应时,lvgl调用的处理函数 (等一会儿要手动编写这个函数);
lv_event_clicked:点击事件; 不同的控件,有不同的事件类型;
null:传递给回调函数的可选用户数据,这里暂时不用;
完成后,是这个样子的:
然后,开始编写刚才说的那个事件回调函数。
在main函数的上方,注释begin 0 与 end 0之间,编写回调函数:mybtn_event();
// 按钮的事件回调函数
static void mybtn_event(lv_event_t *event)
{
lv_obj_t *btn = lv_event_get_target(event); // 获得调用这个回调函数的对象
if (event->code == lv_event_clicked)
{
static uint8_t cnt = 0;
cnt++;
lv_obj_t *label = lv_obj_get_child(btn, null); // 获取第1个子对象(我们在设计时,已安排了它的第1个子对象是一个label对象)
lv_label_set_text_fmt(label, "button: %d", cnt); // 设置标签的文本,写法类似printf
}
}
对函数内的代码行,上面已有注释,比较简单,这里也就不啰嗦了。
完成后,是这个样子的:
编译,烧录,运行效果如下:
十 一、几个相关的小事情
上面,lvgl的移植,已经完成的。
备份好这个工程吧,它能作为后续可视化设计移植的基础工程。
本部分,探讨一些轻松一点的、可能对你有用的玩法。
1、在右下角,显示cpu使用率、fps帧数
- lv_conf.h中第282行,找到:lv_use_perf_monitor,原值:0, 修改为:1
2、在左下角,显示lvgl的内存使用率
- lv_conf.h中第289行,找到:lv_use_mem_monitor,原值:0, 修改为:1
3、黑色主题
- lv_conf.h中第579行:找到:lv_theme_default_dark, 原值:0, 修改为:1
4、获取控件的各种玩法
lvgl的控件玩法,最好的网站,没有之一:
lvgl 中文开发手册 -- https://lvgl.100ask.net/master/index.html
有啥控件,控件的实现效果如何,都可以在这里找到答案。
如,想实现一个下拉列表:
打开上面网址, 找到 examples / widgets / dropdown(下拉列表)。
点击后,右侧会展示各种下拉列表的效果(有点延时,要稍等),还可以通过鼠标点击它。
先找到我们想要的控件效果,
在效果的下方,点击 “show c code",可以展开这个效果的代码,复制到工程中,即可测试。
5、查询 lvgl 某个函数、某个变量的解释
直接问ai,没有更快了,下面是kimi的网址:
十 二、显示中文
如何显示中文呢?如果使用代码的方法,不外乎两个方法:
- lvgl源文件中,自带了一个中文字库。
- 网上有各种的字模转换方法、程序。
这两种方法,使用过程都很烦琐,都不建议使用。
小篇的建议是:通过gui guider实现。
gui guider除了能对界面进行可视化设计,还能轻松实现中文显示,根本无需理会转换的问题。
在我们移植的这个lvgl工程基础上,就能直接使用gui guider的移植。
gui guider 教程链接:lvgl_可视化设计 (gui guider)
发表评论