• lvgl


    lvgl

    目录

    lvgl

    Lvgl移植到STM32

    -- 1、下载LVGL源码

    -- 2、将必要文件复制到工程目录

    -- 3、修改配置文件

    将lvgl与底层屏幕结合到一块

    -- lvgl也需要有定时器,专门给自己做了一个函数,告诉lvgl经过了多长时间(ms(毫秒)级别)

    编写代码

    lvgl的中文教程手册网站

    lvgl的基础知识

    -- 重点是lvgl基础控件的使用

    -- 如何用lvgl去制作软件

    更改错误

    -- 8、只要使用汉字,都按照下面这种方式修改

    屏幕显示调用

    如何实现界面刷新(界面中的数据如何变化)

    总结


    • 主要用于界面设计

    -- 我们在做的项目是空气质量检测仪,下面这些是项目在开发阶段分的模块

    • 分为项目硬件,项目软件,项目结构(产品外壳),UI(界面设计),APP,测试

    -- 对于界面开发,有很多,如qt,但是qt开发出来的程序比较大,占用内存比较多,所以选择了lvgl

    -- GUI:LVGL,emwin,qt,touchgfx,minigui,simplegui(嵌入式开发阶段的界面开发工具)


    -- LVGL(轻巧而多功能的图形库)是一个免费的开放源代码图形库,它提供创建具有易于使用的图形元素,精美的视觉效果和低内存占用的嵌入式GUI所需的一切。

    -- lvgl官方网站 

    alt text


    -- 硬件要求:
    基本上,每个现代控制器(肯定必须要能够驱动显示器)都适合运行LVGL。LVGL的最低运行要求很低: 16、32或64位微控制器或处理器
    最低 16 MHz 时钟频率
    Flash/ROM::对于非常重要的组件要求 >64 kB(建议 > 180 kB)

    -- Lvgl系统框架

    alt text

    -- 应用程序创建 GUI 并处理特定任务的应用程序。 -- LVGL 本身是一个图形库。我们的应用程序通过调用 LVGL 库来创建 GUI 。它包含一个 HAL (硬件抽象层)接口,用于注册显示和输入设备驱动程序。 驱动程序除特定的驱动程序外,它还有其他的功能,可驱动显示器到 GPU (可选)、读取触摸板或按钮的输入。

    Lvgl移植到STM32

    -- 1、下载LVGL源码

    alt text

    -- 其中lvgl/src文件夹内存放的是LVGL的核心源码,lvgl/examples/porting文件夹内存放的是lvgl与底层的接口函数,这些函数需要我们根据自己的项目进行修改。

    -- 源码在文件夹中可以找到

    alt text

    -- 2、将必要文件复制到工程目录

    -- 1、在个人的工程目录下创建一个名为Lvgl的文件夹,并将lvgl/src目录复制到Lvgl目录下,将lvgl/examples/porting文件夹复制到Lvgl目录下,同时将lvgl/lvgl.h文件以及lvgl/lv_conf_template.h文件复制到Lvgl目录下。如下图所示:

    alt text

    -- 2、将lv_conf_template.h文件更名为lv_conf.h,如下图所示:

    alt text

    -- 3、修改port目录下所需要的文件名字,我们只使用了屏幕的显示功能,因此我们只修改显示接口的文件名字,将lv_port_disp_template.c/.h更名为lv_port_disp.c/.h如下图所示:

    alt text

    alt text

    -- 4、在Lvgl目录下再创建一个app目录,用于存放我们后期自己写的应用层界面代码,具体操作如下图所示:

    alt text

    alt text

    -- 5、打开工程,在工程目录下新建三个分组,分别为Lvgl/app、Lvgl/porting、Lvgl/src三个目录,具体操作如下图所示:

    alt text

    -- 6、添加文件到工程目录中,porting目录下只添加lv_port_disp.c,以及Lvgl目录下的lv_conf.h文件,这两个文件后面需要修改。 

    alt text

     在src目录下,添加Lvgl/src目录下除去gpu文件夹外的所有文件夹内的c文件。

    alt text

    -- 7、配置头文件路径,把Lvgl文件夹下所有包含h文件的路径,在工程属性中进行配置,具体操作如下图: 

    alt text

    -- 3、修改配置文件

    -- 1、打开lv_port_disp.c/.h文件,修改如下内容

    alt text

    alt text

    -- 2、修改lv_conf.h文件如下图所示,修改后编译代码,这个时候代码就没有错误了。

    alt text

    -- 3、接下来适配屏幕接口到lvgl上,先修改lv_conf.h内的宏定义,通过它可以设置库的基本行为,裁剪不需要模块和功能,在编译时调整内存缓冲区的大小等等,我们先修改一些必须修改的定义,后期的功能我们在具体项目中再做裁剪。

    alt text

    -- 注:

    -- 竖屏和横屏可以自己选择

    alt text

    -- 更改单片机分给lvgl的空间大小 

    alt text

    -- 是否要适配v6版本,我们这里选择v7版本,就不适配v6了,将宏定义改为0 

    alt text

    将lvgl与底层屏幕结合到一块

    -- 更改初始化函数,进入初始化函数中

    alt text

    -- 将lcd初始化加进来,以后就不用lcd初始化了,直接调用lvgl的初始化函数即可

    alt text

    -- 绘制缓冲区,屏蔽其他两种方法

    alt text

    -- 更改参数

    alt text

    -- 找到lcd中的指定区域内填充指定颜色快的函数

    alt text

    -- 并在.h中声明

    alt text

    -- 将lv_port_disp.c中的函数进行修改

    alt text

    -- lvgl也需要有定时器,专门给自己做了一个函数,告诉lvgl经过了多长时间(ms(毫秒)级别)
    • 先将操作系统中的宏定义改变 

      alt text

    • 我们要写一个时钟节拍钩子函数 

      alt text

    • 参考我们之前写的任务栈溢出函数

    alt text

    编写代码

    -- 创建任务句柄

    TaskHandle_t xLvglTaskHandle = NULL;
    

    -- 创建任务主题函数

    1. void vLvglTaskFunction( void * pvParameters )
    2. {
    3. TickType_t xLastWakeTime;
    4. const TickType_t xPeriod = pdMS_TO_TICKS( 5 );//5ms的延时
    5. xLastWakeTime = xTaskGetTickCount();
    6. for(;;)
    7. {
    8. lv_task_handler();//在裸机里放在while循环中即可
    9. vTaskDelayUntil( &xLastWakeTime, xPeriod );//绝对延时
    10. }
    11. }

    -- 创建任务(放在main函数中)

    1. xTaskCreate(vLvglTaskFunction, "lvgl_task", 512, NULL, 2, &xLvglTaskHandle);

    -- 启动任务

    1. if(xReturn == pdPASS)
    2. vTaskStartScheduler();//任务调度器 //当程序执行完这句话之后,正常情况下下面的代码不会再运行,只会运行任务主题函数

    -- 上述内容我们就已经成功配置了lvgl的环境,下面我们写入一个测试代码,看看是否能够正常显示。写在初始化函数后面即可。

    alt text

    -- 完整代码

    1. #include "lvgl.h"
    2. #include "lv_port_disp.h"
    3. TaskHandle_t xLvglTaskHandle = NULL;
    4. void vLvglTaskFunction( void * pvParameters )
    5. {
    6. TickType_t xLastWakeTime;
    7. const TickType_t xPeriod = pdMS_TO_TICKS( 5 );//5ms的延时
    8. xLastWakeTime = xTaskGetTickCount();
    9. for(;;)
    10. {
    11. lv_task_handler();//在裸机里放在while循环中即可
    12. vTaskDelayUntil( &xLastWakeTime, xPeriod );//绝对延时
    13. }
    14. }
    15. int main(void)
    16. {
    17. lv_init();
    18. lv_port_disp_init();
    19. //测试代码--显示一个label
    20. lv_obj_t * label1 = lv_label_create(lv_scr_act(), NULL);
    21. lv_label_set_long_mode(label1, LV_LABEL_LONG_BREAK);
    22. lv_label_set_recolor(label1, true);
    23. lv_label_set_align(label1, LV_LABEL_ALIGN_CENTER);
    24. lv_label_set_text(label1, "#0000ff Re-color# #ff00ff words# #ff0000 of a# label "
    25. "and wrap long text automatically.");
    26. lv_obj_set_width(label1, 150);
    27. lv_obj_align(label1, NULL, LV_ALIGN_CENTER, 0, -30);
    28. BaseType_t xReturn = pdPASS;
    29. xTaskCreate(vLvglTaskFunction, "lvgl_task", 512, NULL, 2, &xLvglTaskHandle);
    30. //xTaskCreate(arc_loader, "lvgl_task", 512, NULL, 2, &xLvglTaskHandle);
    31. if(xReturn == pdPASS)
    32. vTaskStartScheduler();//任务调度器 //当程序执行完这句话之后,正常情况下下面的代码不会再运行,只会运行任务主题函数
    33. }

    -- 注意:这里用了lvgl的初始化函数,不用再用lcd的初始化了,前面已经把lcd初始化函数写在了lvgl的初始化函数里面了。

    -- 测试效果图

    alt text

    lvgl的中文教程手册网站

    -- 该网站包含各种事例代码和图形库

    -- 英文 Layers — LVGL documentation

    -- 中文 基础对象(lv_obj) — 百问网LVGL中文教程手册文档 1.0 文档

    alt text

    lvgl的基础知识

    -- lvgl是一个图形库

    -- 那么什么叫做图形库呢?

    alt text

    -- 这些就是一个一个的图形

    -- 每个图形又可以称为对象

    alt text

    -- 对象的属性:假如要绘制一个仪表盘,那么他的大小设置多大,位置放在哪里。能不能拖动呢?是否被拖动?

    alt text

    -- 对象的层级:父子,小介面基于大介面的基础上创建出来的,例如在大介面上点击一个按钮导致小介面生成。

    alt text

    -- 事件:点击,拖动,长按,松开,滚动等等

    alt text

    -- 这个事件怎么处理呢?

    • 当事件发生时,lvgl会跟根据提前定义好的回调函数进行处理,回调函数可以自己定义,也可以使用lvgl提供的回调函数。

    • 不同的对象所对应的事件也不同

    alt text

    -- 还有特殊的事件,键盘或者事件编码

    alt text

    -- 输入设备:触摸屏,键盘,鼠标,编码器等等

    alt text

    -- 显示:

    -- 字体:LVGL 支持 UTF-8 编码的 Unicode 字符。需要配置的编辑器,以将的代码/文本保存为 UTF-8 (通常是默认值)

    -- 在lvgl里面,只要显示汉字,一定要在UTF-8格式下写汉字

    alt text

    -- lvgl是有自己的一个操作系统的,只是目前我们还没有使用

    -- 重点是lvgl基础控件的使用

    -- 例子:圆弧展示进度条

    alt text

    alt text

    -- 首先将代码复制到咱们的程序里面

    1. static void arc_loader(lv_task_t * t)
    2. {
    3. static int16_t a = 270;
    4. a+=5;
    5. lv_arc_set_end_angle(t->user_data, a);
    6. if(a >= 270 + 360) {
    7. lv_task_del(t);
    8. return;
    9. }
    10. }
    11. int main()
    12. {
    13. lv_init();
    14. lv_port_disp_init();
    15. //显示一个圆弧(进度条)
    16. /*Create an Arc*/
    17. lv_obj_t * arc = lv_arc_create(lv_scr_act(), NULL);
    18. lv_arc_set_bg_angles(arc, 0, 360);
    19. lv_arc_set_angles(arc, 270, 270);
    20. // lv_obj_align(arc, NULL, LV_ALIGN_CENTER, 0, 0);//改变了对象的位置
    21. lv_obj_set_pos(arc,20,60);//设置起点位置
    22. lv_obj_set_size(arc,200,200);//设置对象大小
    23. /* Create an `lv_task` to update the arc.
    24. * Store the `arc` in the user data*/
    25. lv_task_create(arc_loader, 20, LV_TASK_PRIO_LOWEST, arc);
    26. }

    -- 结果图太小了,需要找个能改变自身大小的

    alt text

    • 相关api

    • 设置位置

    lv_obj_set_pos(arc,20,60);//设置起点位置
    
    • 设置对象大小
    lv_obj_set_size(arc,200,200);//设置对象大小
    

    -- 至此就可以添加一个圆弧图形了,但是这个圆弧是静态的,需要添加一个定时器,让圆弧动起来。所以前面写的时钟钩子函数就可以派上用场了。

    -- 如何用lvgl去制作软件

    -- 安装软件

    -- 1、先安装Java环境(注意一定要先安装java环境)

    alt text

    -- 2、安装软件

    alt text

    -- 3、打开软件,点击创建,选择v7

    -- 4、工程的名字和路径都不能出现中文,屏幕的类型如果选项中没有的话,可以自己定义

    alt text

    -- 5、创建成功后,会跳转新的界面,将右上角英文切换成中文,界面的颜色也可以选择,可以改为深蓝色或者其他颜色

    -- 6、可以先选择一个图片当作背景,将图片拖拽过来,可以通过更改参数让它显示在全屏

    alt text

    alt text

    -- 7、新增界面 

    alt text

    -- 8、可以更改背景的颜色

    alt text

    -- 9、也可以更改图片的透明度,255是不透明,0是完全透明

    alt text

    -- 10、设置文本

    alt text

    alt text

    -- 11、将表格拖进界面

    alt text

    alt text

    -- 12、有些是不能用的 

    alt text

    -- 13、将图形界面设计完之后,点击编译,编译成功后就会将配置好的界面显示出来

    alt text

    -- 14、注意:这个编译默认编译的是第一个界面,如果向编译其他界面。

    alt text

    -- 都编译成功后,开始将代码放到工程中

    -- 15、先找到工程所在地方

    alt text

    -- 16、

    alt text

    alt text

    -- 17、了解这些文件的作用

    alt text

    alt text

    -- 18、在工程中新建文件夹

    alt text

    -- 19、添加头文件路径

    alt text

    -- 20、之后编译,出现错误 

    alt text

    更改错误

    -- 1、修改界面文件

    alt text

    alt text

    -- 2、更改图模文件

    alt text

    -- 3、更改字模文件

    alt text

    -- 4、修改系统自带文件

    alt text

    alt text

    alt text

    alt text

    -- 5、之后编译,然后有的电脑还会出现错误,有的没有

    alt text

    -- 6、添加一个定义

    alt text

    -- 7、修改错误,一般就是中文汉字编码的错误

    alt text

    • 只要有汉字,就会报两个错
    -- 8、只要使用汉字,都按照下面这种方式修改

    -- 解决方案一:显示的字符串,最后不能以汉字结束。在字符串结束,加一个空格

    • 点击错误跳转到出错的地方,将字符串最后加一个空格
    • 其中这个摄氏度就是中文的。

    alt text

    -- 解决方案二:将keil的编码格式修改为utf-8,然后在这种编码格式下重新输入汉字

    alt text

    -- 然后在这个格式下重新输入汉字,为了保险起见,后面也加上空格

    屏幕显示调用

    -- 将代码复制到main函数中

    alt text

    -- 加上头文件

    alt text

    -- 这两个代码分别是创建和显示

    alt text

    -- 只有创建函数的话,只会创建,创建完之后不会显示

    alt text

    -- 要想在屏幕中显示,必须要调用显示函数

    alt text

    -- 此时显示的界面是screen1,如果想要显示其他界面,如screen,只需要将screen1改为screen即可

    alt text

    -- 但是如果两个显示函数都调用的话,只会显示后面调用的那个

    -- 那么如何实现切换界面

    • 1、将创建函数写在main函数中

    alt text

    • 2、然后在按键任务中调用显示函数

    alt text

    • 3、加一个标志位,防止多次点击同一按键,导致界面反复切换同一个界面无意义

    alt text

    • 3、代码
    1. uint8_t GUI_flag = 0;
    2. //2
    3. void KETTaskCreat(void *pvParameters)
    4. {
    5. uint8_t keyflag = 0;
    6. uint8_t buff[10]={0};
    7. while(1)
    8. {
    9. keyflag = get_key();
    10. switch(keyflag)
    11. {
    12. case 1:
    13. if(GUI_flag!=2)
    14. {
    15. lv_scr_load(guider_ui.screen); //显示
    16. GUI_flag=2;
    17. }
    18. break;
    19. case 2:
    20. if(GUI_flag!=1)
    21. {
    22. GUI_flag =1;
    23. lv_scr_load(guider_ui.screen_1); //显示
    24. }
    25. break;
    26. }
    27. vTaskDelay(50); //在任务周期时可以释放cpu
    28. }
    29. }
    如何实现界面刷新(界面中的数据如何变化)

    -- 1、实现文本数据刷新

    -- 要想实现数据更新,必须要找到对应的对象,然后调用对应的赋值函数

    -- 例如界面一的温度数值,先找到界面一对应的赋值函数,复制

    alt text

    -- 将函数复制到lcd显示任务函数中,直接将数值更改为变量,就可以实现动态更新数值了。

    alt text

    1. void LCDTaskCreat(void *pvParameters)//函数名称不固定,参数格式是固定的(任务一定是一个while循环,每个任务一定要有自己的任务周期)//设置任务周期的目的就是可以让任务可以主动释放cpu(指的是任务能够自动释放cpu)
    2. {
    3. //BaseType_t xReturn = pdPASS;//有没有获取成功,再显示LCD
    4. EventBits_t r_event;
    5. while(1)
    6. {
    7. r_event = xEventGroupWaitBits(Event_Handle, /* 事件对象句柄 */
    8. 0x07,/* 接收任务感兴趣的事件 */
    9. pdTRUE,/* 退出时清除事件位 */
    10. pdFALSE,/* 满足感兴趣的所有事件 *///逻辑或
    11. 500);/* 指定超时事件,一直等 */
    12. //dht
    13. if(r_event &(0x1<<0))//判断这个数中的位0是否为真
    14. {
    15. sprintf(D_wen, "tem: %.2d鈩?",(int)dht.tem);
    16. //实现数据更新
    17. //找到对应对象的赋值函数
    18. lv_label_set_text(guider_ui.screen_1_label_1, D_wen);
    19. }
    20. }
    21. }

    -- 2、实现表格数据刷新(折线图)

    -- 找到对应的赋值函数

    alt text

    -- 在lcd函数中调用

    alt text

    将值改为变量

    -- 效果图

    alt text

    总结

    -- 1、进行界面设计,注意先考虑好布局(做几个界面,每个界面显示什么内容,如何规划)

    -- 2、保证每个界面在屏幕上都能显示出来

    -- 3、保证界面相互切换不会卡死

    -- 4、界面刷新

  • 相关阅读:
    Unknown collation: ‘utf8mb4_0900_ai_ci‘的解决方法
    控制实体小车cartographer建图
    腾讯配合监管机构:未经批准不得发布新应用或更新版本
    浅谈OV SSL 证书的优势
    【神经网络与深度学习】LSTM(Long Short-Term Memory)神经网络模型
    亚马逊UL认证检测报告详细流程
    [附源码]java毕业设计乒乓球俱乐部管理系统
    网站服务器出现404情况
    从源码全面解析 dubbo 消费端服务调用的来龙去脉
    《网络协议》01. 基本概念
  • 原文地址:https://blog.csdn.net/m0_71813740/article/details/143237595