LVGL移植——stm32f4

news2024/11/23 5:03:37

LVGL移植说明

移植LVGL版本:8.3.6

主控:STM32F407ZGT6

github链接:https://github.com/lvgl/lvgl.git

文章目录

  • LVGL移植说明
    • STM32移植LVGL
      • ①需要的依赖文件
      • ②移植显示驱动文件
      • ③将文件加入工程当中
      • ④配置心跳
      • ④修改栈堆的空间
      • ⑤编译链接

STM32移植LVGL

步骤说明:

  • 下载lvgl的数据包
  • 将lvgl的依赖文件加入工程当中
  • 修改LVGL的配置文件,主要就是lv_port_disp_template文件和lv_conf文件的配置。
  • 配置心跳
  • 修改栈堆空间配置

注意事项:

在官方的文档说明当中有这样的一个说明:

基本上,每个能够驱动显示器的现代控制器都适合运行 LVGL。最低要求是:

  • 16、32 或 64 位微控制器或处理器

  • > 推荐 16 MHz 时钟速度

  • 闪存/ROM:> 64 kB 用于非常重要的组件(建议 > 180 kB)

  • 内存:

    静态 RAM 使用:~2 kB,具体取决于使用的功能和对象类型堆栈:> 2kB(建议> 8 kB)动态数据(堆):> 2 KB(如果使用多个对象,建议> 48 kB)。LV_MEM_SIZE在lv_conf.h中设置。显示缓冲区:> *“水平分辨率”*像素(建议>10 *“水平分辨率” )*MCU 或外部显示控制器中的一个帧缓冲器

  • C99 或更新的编译器

①需要的依赖文件

还有examples里面的porting文件,里面有三个.c文件和.h文件

其中lv_port_indev文件是对接触摸事件的

lv_port_disp对接显示事件

lv_port_fs对接文件管理事件

另外,里面的三个文件的.c和.h都有一个开关,需要用到哪个文件需得把相对应的开关打开。

除此之外,还有一个lv_conf_template.h文件,默认是把文件关闭的,需要打开。除此之外 LVGL 的核心实现中,都是使用 #include “lv_conf.h”,所以 lv_conf_template.h 文件改名为 lv_conf.h 是必须要做的;

②移植显示驱动文件

在这一个部分当中主要的就是lv_port_disp文件。要对屏幕的显示驱动进行对接。在这个文件当中,主要配置两个函数。即:disp_flush、lv_port_disp_init。主要对这两个文件进行配置。

首先要定义一下屏幕的分辨率大小

#define MY_DISP_HOR_RES    240
#define MY_DISP_VER_RES    320

lv_port_disp_init函数:

void lv_port_disp_init(void)
{
    /*-------------------------
     * Initialize your display
     * -----------------------*/
    disp_init();

    /*-----------------------------
     * Create a buffer for drawing
     *----------------------------*/

    /**
     * LVGL requires a buffer where it internally draws the widgets.
     * Later this buffer will passed to your display driver's `flush_cb` to copy its content to your display.
     * The buffer has to be greater than 1 display row
     *
     * There are 3 buffering configurations:
     * 1. Create ONE buffer:
     *      LVGL will draw the display's content here and writes it to your display
     *
     * 2. Create TWO buffer:
     *      LVGL will draw the display's content to a buffer and writes it your display.
     *      You should use DMA to write the buffer's content to the display.
     *      It will enable LVGL to draw the next part of the screen to the other buffer while
     *      the data is being sent form the first buffer. It makes rendering and flushing parallel.
     *
     * 3. Double buffering
     *      Set 2 screens sized buffers and set disp_drv.full_refresh = 1.
     *      This way LVGL will always provide the whole rendered screen in `flush_cb`
     *      and you only need to change the frame buffer's address.
     */

    /* Example for 1) */
    static lv_disp_draw_buf_t draw_buf_dsc_1;
    static lv_color_t buf_1[MY_DISP_HOR_RES * MY_DISP_VER_RES/4];                          /*A buffer for 10 rows*/
    lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, MY_DISP_HOR_RES * MY_DISP_VER_RES/4);   /*Initialize the display buffer*/

    /* Example for 2) */
//    static lv_disp_draw_buf_t draw_buf_dsc_2;
//    static lv_color_t buf_2_1[MY_DISP_HOR_RES * 10];                        /*A buffer for 10 rows*/
//    static lv_color_t buf_2_2[MY_DISP_HOR_RES * 10];                        /*An other buffer for 10 rows*/
//    lv_disp_draw_buf_init(&draw_buf_dsc_2, buf_2_1, buf_2_2, MY_DISP_HOR_RES * 10);   /*Initialize the display buffer*/

//    /* Example for 3) also set disp_drv.full_refresh = 1 below*/
//    static lv_disp_draw_buf_t draw_buf_dsc_3;
//    static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES];            /*A screen sized buffer*/
//    static lv_color_t buf_3_2[MY_DISP_HOR_RES * MY_DISP_VER_RES];            /*Another screen sized buffer*/
//    lv_disp_draw_buf_init(&draw_buf_dsc_3, buf_3_1, buf_3_2,
//                          MY_DISP_VER_RES * LV_VER_RES_MAX);   /*Initialize the display buffer*/

    /*-----------------------------------
     * Register the display in LVGL
     *----------------------------------*/

    static lv_disp_drv_t disp_drv;                         /*Descriptor of a display driver*/
    lv_disp_drv_init(&disp_drv);                    /*Basic initialization*/

    /*Set up the functions to access to your display*/

    /*Set the resolution of the display*/
    disp_drv.hor_res = MY_DISP_HOR_RES;
    disp_drv.ver_res = MY_DISP_VER_RES;

    /*Used to copy the buffer's content to the display*/
    disp_drv.flush_cb = disp_flush;

    /*Set a display buffer*/
    disp_drv.draw_buf = &draw_buf_dsc_1;

    /*Required for Example 3)*/
    //disp_drv.full_refresh = 1;

    /* Fill a memory array with a color if you have GPU.
     * Note that, in lv_conf.h you can enable GPUs that has built-in support in LVGL.
     * But if you have a different GPU you can use with this callback.*/
    //disp_drv.gpu_fill_cb = gpu_fill;

    /*Finally register the driver*/
    lv_disp_drv_register(&disp_drv);
}

在官方文档中有这么一个说明,要有一个显示缓冲区,帧缓冲区和至少 1/10 屏幕大小的缓冲区用于渲染。在这个函数里面官方给出了三种缓冲区模式,分别是单缓冲区,非全尺寸双缓冲区,全尺寸双缓冲区。

初始化了屏幕的宽和高。即分辨率:

	disp_drv.hor_res = MY_DISP_HOR_RES;
    disp_drv.ver_res = MY_DISP_VER_RES;	

还调用了一个回调函数,对接底层和芯片平台相关的刷图接口。

disp_drv.flush_cb = disp_flush;

这个接口主要就是要对一个区域进行绘制,并把颜色传入到里面。

static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
//    if(disp_flush_enabled) {
//        /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/

//        int32_t x;
//        int32_t y;
//        for(y = area->y1; y <= area->y2; y++) {
//            for(x = area->x1; x <= area->x2; x++) {
//                /*Put a pixel to the display. For example:*/
//                /*put_px(x, y, *color_p)*/
//                color_p++;
//            }
//        }
//    }
		LCD_Color_Fill(area->x1,area->y1,area->x2,area->y2,(u16*)color_p);
    /*IMPORTANT!!!
     *Inform the graphics library that you are ready with the flushing*/
    lv_disp_flush_ready(disp_drv);
}

这样就把基本的显示接口对接完成。

另外,在配置lv_conf.h文件。

/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/
#define LV_COLOR_DEPTH 16

/*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/
  #define LV_MEM_SIZE (48U * 1024U)          /*[bytes]*/
// 用于渲染和 LVGL 内部处理机制的 buffer 个数,如果配置不够的话,LVGL 会打印 ERROR 信息
 // 这个其实是一个 lv_mem_buf_arr_t[LV_MEM_BUF_MAX_NUM] 结构的数组个数;
#define LV_MEM_BUF_MAX_NUM 16

// 这个参数决定了多久处理一起屏幕刷新,默认情况是 30ms
#define LV_DISP_DEF_REFR_PERIOD 30      /*[ms]*/
 
/*Input device read period in milliseconds*/
// 这个参数决定了多久处理一起input,默认情况是 30ms
#define LV_INDEV_DEF_READ_PERIOD 30     /*[ms]*/

/*1: Show CPU usage and FPS count*/
#define LV_USE_PERF_MONITOR 1

/*1: Show the used memory and the memory fragmentation
 * Requires LV_MEM_CUSTOM = 0*/
#define LV_USE_MEM_MONITOR 0

/*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings.
 *(Not so important, you can adjust it to modify default sizes and spaces)*/
#define LV_DPI_DEF 130     /*[px/inch]*/
  • LV_COLOR_DEPTH参数是设置颜色的深度。有三种模式可以供我们选择,RGB332,RGB565,ARGB8888。三种,根据自己屏幕进行选择即可。
  • LV_MEM_SIZE是用于 LVGL 的动态申请/释放内存,这里我们配置的 48KB 的全局数组给 LVGL 使用
  • LV_MEM_BUF_MAX_NUM用于渲染和 LVGL 内部处理机制的 buffer 个数
  • LV_DISP_DEF_REFR_PERIOD和LV_DISP_DEF_REFR_PERIOD用于处理屏幕的刷新周期,在默认当中处于30ms刷新一次,即满帧为33FPS。
  • LV_USE_PERF_MONITOR用于打开或者关闭帧率的监控管理。
  • LV_USE_MEM_MONITOR用于打开或者关闭内存的监控管理。

③将文件加入工程当中

将examples里面的porting文件加入工程、src里面的所有文件加入工程当中。

④配置心跳

LVGL 的任务都是基于时间的,包含绘制,响应触摸等等;所以呢,我们需要给它一个时间基准;

LVGL 提供了一个 lv_tick_inc 的函数,我们需要在系统中去周期性调用他,告诉 LVGL 的时间基准;可以用硬件 Timer,也可以使用 SystemTick;

 void TIM3_IRQHandler(void)
 {
   /* USER CODE BEGIN TIM3_IRQn 0 */

   /* USER CODE END TIM3_IRQn 0 */
   /* USER CODE BEGIN TIM3_IRQn 1 */

   /* USER CODE END TIM3_IRQn 1 */
  if(LL_TIM_IsActiveFlag_UPDATE(TIM3) == SET)
   {
     LL_TIM_ClearFlag_UPDATE(TIM3);
     lv_tick_inc(1);
    // LL_GPIO_TogglePin(GPIOF, LL_GPIO_PIN_9);
   }
 }

④修改栈堆的空间

在官方文档当中的最小配置文档说明,根据其要求进行对栈堆的大小进行修改。

⑤编译链接

在文档中说明使用C99的风格进行编码,因此,需要将KEIL配置中的C99选项进行勾选。

另外,编译当中会有一些无关紧要的warning,在 Options->C/C++ 的 Misc Controls 中加入以下命令即可。

--diag_suppress=188 --diag_suppress=111 --diag_suppress=550

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/489236.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

02-权限提升-Win溢出漏洞及ATSCPS提权

权限提升-Win溢出漏洞及AT&SC&PS提权 思维导图 明确权限提升基础知识&#xff1a;权限划分 明确权限提升环境问题&#xff1a;web及本地 web提权&#xff1a;已有网站权限&#xff08;可以操作网站内容&#xff0c;但无法操作服务器&#xff09;&#xff0c;想要获得…

【软考中级】2022下半年软件设计师综合知识真题与答案

1、以下关于R1SC(精简指令集计算机)特点的叙述中&#xff0c;错误的是()。 A.对存储器操作进行限制&#xff0c;使控制简单化 B.指令种类多&#xff0c;指令功能强 C.设置大量通用寄存器 D.选取使用频率较高的一些指令&#xff0c;提高执行速度 参考答案&#xff1a;B 2、…

Qt6之KDE框架

25年来&#xff0c;KDE社区一直在使用Qt开发各种自由软件产品。其中包括Plasma桌面环境&#xff0c;像Krita和Kdenlive这样的创意工具&#xff0c;像GCompris这样的教育应用程序&#xff0c;像Kontact这样的群件套件以及无数其他应用程序&#xff0c;实用程序和小部件。 Qt以其…

Shell+VCS学习3---VCS命令

1 VCS介绍 VCS的功能可以大致分为两个大类&#xff1a;编译和仿真。 VCS编译的过程&#xff0c;就是经过一系列的操作&#xff0c;将verilog代码转换为可执行文件&#xff08;.svim&#xff09;&#xff0c;接下来就是用dve进行仿真过程生成.vpd波形文件。 VCS是编译型verilo…

C++---树形DP---树的最长路径(每日一道算法2023.5.4)

注意事项&#xff1a; 本题为"树与图的DFS深度优先遍历—树的重心"的近似题&#xff0c;同时涉及到 单链表模拟邻接表存储图 的操作&#xff0c;建议先理解那篇文章。 题目&#xff1a; 给定一棵树&#xff0c;树中包含 n 个结点&#xff08;编号1~n&#xff09;和 …

JavaScript:栈和对列

文章目录 栈和对列Js 有栈与队列吗20. 有效的括号 - 力扣&#xff08;LeetCode&#xff09;思路 1047. 删除字符串中的所有相邻重复项 - 力扣&#xff08;LeetCode&#xff09;思路代码分析array.join() 操作打印const s of str 操作遍历 150. 逆波兰表达式求值 - 力扣&#xf…

(1)QT基础铺垫

目录 1.Qt特性 2. 新建项目 3. 工作目录与构建目录 4. 工作目录 4.1 .pro 项目配置文件 4.2 dialog.h 4.3 dialog.cpp 4.4 main.cpp 5. 帮助文档 6. 调试信息 1.Qt特性 Qt经常被当作是一个基于c语言的gui开发框架&#xff0c;但是这并不是qt的全部&#xff0c;除了开…

助力工业物联网,工业大数据之ODS层构建:申明分区代码及测试【十】

文章目录 知识点13&#xff1a;ODS层构建&#xff1a;申明分区代码及测试知识点14&#xff1a;ODS层与DWD层区别知识点15&#xff1a;DWD层构建&#xff1a;需求分析知识点16&#xff1a;DWD层构建&#xff1a;建库实现测试知识点17&#xff1a;DWD层构建&#xff1a;建表实现测…

Packet Tracer – 研究 VLAN 实施

Packet Tracer – 研究 VLAN 实施 地址分配表 设备 接口 IP 地址 子网掩码 默认网关 S1 VLAN 99 172.17.99.31 255.255.255.0 不适用 S2 VLAN 99 172.17.99.32 255.255.255.0 不适用 S3 VLAN 99 172.17.99.33 255.255.255.0 不适用 PC1 NIC 172.17.10.2…

Linux部署Gitlab/上传项目

一、提前准备 1.1安装依赖工具 yum install -y curl policycoreutils-python openssh-serversystemctl start sshd systemctl enable sshd 1.2安装Postfix邮件服务器 #安装 postfix yum install -y postfix#启动 postfix 并设置为开机启动 systemctl enable postfix systemctl …

HashCode与String大家庭

当金钱站起来说话时&#xff0c;所有的真理都保持了沉默&#xff1b;金钱一旦作响&#xff0c;坏话随之戛然而止。 Hashcode的作用 java的集合有两类&#xff0c;一类是List&#xff0c;还有一类是Set 前者有序可重复&#xff0c;后者无序不重复。当我们在set中插入的时候怎…

Vue传参${id}变成$%7Bid%7D

发生缘由 外卖项目在Linux服务器上面运行发送请求乱码 运行环境 电脑系统&#xff1a;win10jdk版本&#xff1a;jdk-8SpringBoot版本&#xff1a;v2.4.5MP版本&#xff1a;3.4.2Vue版本&#xff1a;Vue.js v2.6.12Linux版本&#xff1a;Centos7 报错信息 // 修改页面反查详…

MES系统中的BOM为何如此重要?先进的BOM体系怎么构建?

其实不管有没有数字化&#xff0c;BOM都是制造企业的灵魂纽带&#xff0c;对于产品繁多、流程冗长的工业企业来说&#xff0c;如果BOM管理不规范&#xff0c;必然对生产效率和产品质量带来巨大的隐患&#xff0c;因此在工业企业的数字化转型之路中&#xff0c;建立科学规范的BO…

Blender 建模练习-锁链

目录 1.1.1 贝塞尔圆1.2 阵列修改器1.3 阵列修改器 物体偏移1.4 添加贝塞尔曲线1.5 曲线修改器 1. 本次练习主要使用到阵列修改器、贝塞尔曲线、空物体 1.1 贝塞尔圆 把贝塞尔圆进行缩放&#xff0c;然后在物体数据属性|几何数据|倒角|设置倒角深度为0.05 1.2 阵列修改器 …

【数据结构】二叉树(详细)

二叉树 1.树1.1定义1.2基本术语1.3树形结构和线性结构1.4树的存储结构1.4.1双亲表示法1.4.2孩子兄弟表示法 2.二叉树2.1定义2.2特殊二叉树2.3性质2.4存储结构2.4.1顺序存储2.4.2链式存储结构 3.二叉树的基本操作3.1前序遍历&#xff08;先序遍历&#xff09;3.2中序遍历3.3后序…

开放原子训练营(第三季)inBuilder低代码开发实验室---报销单录入系统

作为一名低代码初学者&#xff0c;我使用inBuilder系统设计了一款报销单录入系统&#xff0c;实现了报销单录入与显示报销单列表的功能&#xff08;如图1与图2所示&#xff09;&#xff0c;并获得了很多开发心得。从inBuilder系统的优点、缺点以及开发过程三方面出发&#xff0…

go继承nacos配置中心并读取配置信息

配置中心 为什么需要配置中心 平时我们写一个demo的时候&#xff0c;或者说一个单体的应用&#xff0c;都会有一个配置文件&#xff0c;不管是 json文件或者yaml文件&#xff0c;里面包含了redis,mysql,es等信息&#xff0c;如果我们修改了配置文件&#xff0c;往往我们需要重…

和Ai一起学习CMake(一)

和Ai一起学习CMake 现在人工智能爆火&#xff0c;ChatGPT、new bing等层出不穷。我们借助Ai来学习一下CMake。下面是我与Ai的问答&#xff0c;这个学习主要是通过Ai来学习&#xff0c;但是防止Ai乱说话&#xff0c;我会结合自身的知识和实际操作给出相应的补充。 我的环境如下…

玄子Share - Tomcat 9 安装配置教程(含安装包)

玄子Share - Tomcat 9 安装配置教程&#xff08;含安装包&#xff09; 下载 下载链接 官网 https://tomcat.apache.org/ 下载教程 进入 Tomcat 官网&#xff0c;点击左侧导航栏&#xff0c;选择需要的版本下载。这里按照课程要求选择tomcat 9的版本 Mirrors&#xff1a;选…

为什么越来越多的企业开始选择云计算?

一、前言 随着数字化时代的到来&#xff0c;企业对于数据的需求越来越大&#xff0c;而传统的数据存储方式已经无法满足企业的需求。云计算作为一种新兴的技术&#xff0c;可以为企业提供更加灵活、高效、安全的数据存储和处理方式&#xff0c;因此越来越多的企业开始选择云计算…