当前位置: 首页 > news >正文

LVGL移植——stm32f4

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

相关文章:

LVGL移植——stm32f4

LVGL移植说明 移植LVGL版本&#xff1a;8.3.6 主控&#xff1a;STM32F407ZGT6 github链接&#xff1a;https://github.com/lvgl/lvgl.git 文章目录 LVGL移植说明STM32移植LVGL①需要的依赖文件②移植显示驱动文件③将文件加入工程当中④配置心跳④修改栈堆的空间⑤编译链接 STM…...

ASEMI代理ADP5054ACPZ-R7原装ADI车规级ADP5054ACPZ-R7

编辑&#xff1a;ll ASEMI代理ADP5054ACPZ-R7原装ADI车规级ADP5054ACPZ-R7 型号&#xff1a;ADP5054ACPZ-R7 品牌&#xff1a;ADI/亚德诺 封装&#xff1a;LFCSP-48 批号&#xff1a;2023 引脚数量&#xff1a;48 工作温度&#xff1a;-40C~125C 安装类型&#xff1a;表…...

TCP/IP相关面试题

1. 什么是TCP/IP协议&#xff1f;它的作用是什么&#xff1f; TCP/IP&#xff08;Transmission Control Protocol/Internet Protocol&#xff09;互联网中最常用的协议&#xff0c;是计算机网络通信的基础。由TCP协议和IP协议两部分组成。IP协议负责数据的传输和路由选择&#…...

MySQL数据库——MySQL存储过程是什么?

我们前面所学习的 MySQL 语句都是针对一个表或几个表的单条 SQL 语句&#xff0c;但是在数据库的实际操作中&#xff0c;经常会有需要多条 SQL 语句处理多个表才能完成的操作。 例如&#xff0c;为了确认学生能否毕业&#xff0c;需要同时查询学生档案表、成绩表和综合表&…...

消息队列中的事务消息

大家好&#xff0c;我是易安&#xff01;今天我们谈一谈消息队列中的事务消息这个话题。 一说起事务&#xff0c;你可能自然会联想到数据库。我们日常使用事务的场景&#xff0c;绝大部分都是在操作数据库的时候。像MySQL、Oracle这些主流的关系型数据库&#xff0c;也都提供了…...

03. 路由参数.重定向.视图

学习要点&#xff1a; 1.路由参数 2.路由重定向 3.路由视图 本节课我们来开始进入学习路由的参数设置、重定向和路由的视图。 一&#xff0e;路由参数 1. 上一节课&#xff0c;我们已经学习了部分路由参数的功能&#xff0c;比如动态传递{id}&#xff1b; 2. 那么&#xff0c;有…...

Flowable入门

Flowable初体验 Flowable是什么 Flowable 是一个使用 Java 编写的轻量级业务流程引擎&#xff0c;常用于需要人工审批相关的业务&#xff0c;比如请假、报销、采购等业务。 为什么要使用工作流呢&#xff1f; 对于复杂的业务流程&#xff0c;通过数据库的状态字段难以控制和…...

Scala Option类型,异常处理,IO,高阶函数

Option类型 实际开发中, 在返回一些数据时, 难免会遇到空指针异常(NullPointerException), 遇到一次就处理一次相对来讲还是比较繁琐的. 在Scala中, 我们返回某些数据时&#xff0c;可以返回一个Option类型的对象来封装具体的数据&#xff0c;从而实现有效的避免空指针异常。S…...

unity进阶学习笔记:单例模式

游戏框架&#xff1a; 游戏框架一般包括消息框架&#xff0c;状态机&#xff0c;管理器&#xff0c;工具类。 消息框架指游戏物体之的通信框架&#xff0c;虽然unity引擎自带一套消息框架&#xff0c;但该框架只能用于父子物体之间通信&#xff0c;无法实现大部分非父子关系的…...

软件测试——性能指标

登录功能示例&#xff1a; 并发用户数500&#xff1b; 响应时间2S&#xff1b; TPS到500&#xff1b; CPU不得超过75%&#xff1b; 性能指标有哪些&#xff1f; 响应时间 并发用户数 TPS CPU 内存 磁盘吞吐量 网络吞吐量 移动端FPS 移动端耗电量 APP启动时间 性能…...

leetcode 405. 数字转换为十六进制数

题目描述解题思路执行结果 leetcode 405. 数字转换为十六进制数. 题目描述 数字转换为十六进制数 给定一个整数&#xff0c;编写一个算法将这个数转换为十六进制数。对于负整数&#xff0c;我们通常使用 补码运算 方法。 注意: 十六进制中所有字母(a-f)都必须是小写。 十六进制…...

部门来了个软件测试,听说是00后,上来一顿操作给我看呆了...

前段时间公司新来了个同事&#xff0c;听说大学是学的广告专业&#xff0c;因为喜欢IT行业就找了个培训班&#xff0c;后来在一家小公司干了三年&#xff0c;现在跳槽来我们公司。来了之后把现有项目的性能优化了一遍&#xff0c;服务器缩减一半&#xff0c;性能反而提升4倍!给…...

使用篇丨链路追踪(Tracing)很简单:链路拓扑

作者&#xff1a;涯海 最近一年&#xff0c;小玉所在的业务部门发起了轰轰烈烈的微服务化运动&#xff0c;大量业务中台应用被拆分成更细粒度的微服务应用。为了迎接即将到来的双十一大促重保活动&#xff0c;小玉的主管让她在一周内梳理出订单中心的全局关键上下游依赖&#…...

2023年厦门等保二级备案办理流程

根据规定&#xff0c;已运营/运行或新建的第二级以上信息系统的企业,事业单位/行政机关/民办非企业单位/社团组织/其他组织必须办理等保备案。 2023年厦门等保二级备案办理流程 办理机构&#xff1a;公安局 办结时限&#xff1a;受理后10个工作日 办理方式&#xff1a;网上…...

提高开发效率,从这些小技巧开始——5个让你爱上IDEA的增加体验小技巧

前言 如果你是一名Java开发人员&#xff0c;那么你一定会使用IntelliJ IDEA这个IDE。IntelliJ IDEA作为目前最受欢迎的Java IDE之一&#xff0c;已经成为了众多Java开发人员必备的工具之一。但是&#xff0c;你是否知道如何利用IDEA中的一些小技巧来提高你的开发效率和体验呢&a…...

Python基础合集 练习22 (错误与异常处理语句2)

‘’’ try: 语句块 except: 语句块2 else ‘’’ class Mobe1(): def init(self) -> None: pass def mob1(self):while True:try:num int(input(请输入一个数: ))result 50 / numprint(result)print(50/{0}{1}.format(num, result))except (ZeroDivisionError, ValueEr…...

ELK -- kibana 用nginx代理后无法访问

背景&#xff1a; 本地搭建好elk后&#xff0c;一切正常&#xff0c;后面改成用nginx代理kibana的5601端口&#xff0c;发现代理后无法正常访问&#xff08;未代理的地址可正常访问&#xff09;&#xff0c;花了很多时间去查问题&#xff0c;报错基本都是http://ip:port/spaces…...

什么是分布式事务

目录 分布式事务基础 事务 本地事务 分布式事务 分布式事务的场景 分布式事务解决方案 全局事务 优点 缺点 可靠消息服务 第一步 &#xff1a;消息由系统A投递到中间件 超时访问机制 最大努力通知 第一步&#xff1a;消息由系统A投递到中间件 第二步&#xff1a;消息…...

在 Python 中将整数转换为罗马数字

罗马数字使用以下七个符号书写。 Symbol Value I 1 V 5 X 10 L 50 C 100 D 500 M 1000这些符号用于表示数以千计的数字。 罗马写20&#xff0c;可以用两个X拼成XX。 但是 XXXX 不…...

HashTable,Properties,TreeSet源码分析

目录 HashTable基本介绍 Hashtable和HashMap对比 Properties Properties基本介绍 应该如何选择集合 TreeSet源码分析 HashTable基本介绍 1)存放的元素是键值对&#xff1a;即K-V 2)hashtable的键和值都不能为null&#xff0c;否则会抛出NullPointerException 3)hashTab…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...

篇章二 论坛系统——系统设计

目录 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 1. 数据库设计 1.1 数据库名: forum db 1.2 表的设计 1.3 编写SQL 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 通过需求分析获得概念类并结合业务实现过程中的技术需要&#x…...

[USACO23FEB] Bakery S

题目描述 Bessie 开了一家面包店! 在她的面包店里&#xff0c;Bessie 有一个烤箱&#xff0c;可以在 t C t_C tC​ 的时间内生产一块饼干或在 t M t_M tM​ 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC​,tM​≤109)。由于空间…...

AD学习(3)

1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分&#xff1a; &#xff08;1&#xff09;PCB焊盘&#xff1a;表层的铜 &#xff0c;top层的铜 &#xff08;2&#xff09;管脚序号&#xff1a;用来关联原理图中的管脚的序号&#xff0c;原理图的序号需要和PCB封装一一…...

Qt Quick Controls模块功能及架构

Qt Quick Controls是Qt Quick的一个附加模块&#xff0c;提供了一套用于构建完整用户界面的UI控件。在Qt 6.0中&#xff0c;这个模块经历了重大重构和改进。 一、主要功能和特点 1. 架构重构 完全重写了底层架构&#xff0c;与Qt Quick更紧密集成 移除了对Qt Widgets的依赖&…...

【Java】Ajax 技术详解

文章目录 1. Filter 过滤器1.1 Filter 概述1.2 Filter 快速入门开发步骤:1.3 Filter 执行流程1.4 Filter 拦截路径配置1.5 过滤器链2. Listener 监听器2.1 Listener 概述2.2 ServletContextListener3. Ajax 技术3.1 Ajax 概述3.2 Ajax 快速入门服务端实现:客户端实现:4. Axi…...