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版本:8.3.6 主控:STM32F407ZGT6 github链接:https://github.com/lvgl/lvgl.git 文章目录 LVGL移植说明STM32移植LVGL①需要的依赖文件②移植显示驱动文件③将文件加入工程当中④配置心跳④修改栈堆的空间⑤编译链接 STM…...
ASEMI代理ADP5054ACPZ-R7原装ADI车规级ADP5054ACPZ-R7
编辑:ll ASEMI代理ADP5054ACPZ-R7原装ADI车规级ADP5054ACPZ-R7 型号:ADP5054ACPZ-R7 品牌:ADI/亚德诺 封装:LFCSP-48 批号:2023 引脚数量:48 工作温度:-40C~125C 安装类型:表…...
TCP/IP相关面试题
1. 什么是TCP/IP协议?它的作用是什么? TCP/IP(Transmission Control Protocol/Internet Protocol)互联网中最常用的协议,是计算机网络通信的基础。由TCP协议和IP协议两部分组成。IP协议负责数据的传输和路由选择&#…...
MySQL数据库——MySQL存储过程是什么?
我们前面所学习的 MySQL 语句都是针对一个表或几个表的单条 SQL 语句,但是在数据库的实际操作中,经常会有需要多条 SQL 语句处理多个表才能完成的操作。 例如,为了确认学生能否毕业,需要同时查询学生档案表、成绩表和综合表&…...
消息队列中的事务消息
大家好,我是易安!今天我们谈一谈消息队列中的事务消息这个话题。 一说起事务,你可能自然会联想到数据库。我们日常使用事务的场景,绝大部分都是在操作数据库的时候。像MySQL、Oracle这些主流的关系型数据库,也都提供了…...
03. 路由参数.重定向.视图
学习要点: 1.路由参数 2.路由重定向 3.路由视图 本节课我们来开始进入学习路由的参数设置、重定向和路由的视图。 一.路由参数 1. 上一节课,我们已经学习了部分路由参数的功能,比如动态传递{id}; 2. 那么,有…...
Flowable入门
Flowable初体验 Flowable是什么 Flowable 是一个使用 Java 编写的轻量级业务流程引擎,常用于需要人工审批相关的业务,比如请假、报销、采购等业务。 为什么要使用工作流呢? 对于复杂的业务流程,通过数据库的状态字段难以控制和…...
Scala Option类型,异常处理,IO,高阶函数
Option类型 实际开发中, 在返回一些数据时, 难免会遇到空指针异常(NullPointerException), 遇到一次就处理一次相对来讲还是比较繁琐的. 在Scala中, 我们返回某些数据时,可以返回一个Option类型的对象来封装具体的数据,从而实现有效的避免空指针异常。S…...
unity进阶学习笔记:单例模式
游戏框架: 游戏框架一般包括消息框架,状态机,管理器,工具类。 消息框架指游戏物体之的通信框架,虽然unity引擎自带一套消息框架,但该框架只能用于父子物体之间通信,无法实现大部分非父子关系的…...
软件测试——性能指标
登录功能示例: 并发用户数500; 响应时间2S; TPS到500; CPU不得超过75%; 性能指标有哪些? 响应时间 并发用户数 TPS CPU 内存 磁盘吞吐量 网络吞吐量 移动端FPS 移动端耗电量 APP启动时间 性能…...
leetcode 405. 数字转换为十六进制数
题目描述解题思路执行结果 leetcode 405. 数字转换为十六进制数. 题目描述 数字转换为十六进制数 给定一个整数,编写一个算法将这个数转换为十六进制数。对于负整数,我们通常使用 补码运算 方法。 注意: 十六进制中所有字母(a-f)都必须是小写。 十六进制…...
部门来了个软件测试,听说是00后,上来一顿操作给我看呆了...
前段时间公司新来了个同事,听说大学是学的广告专业,因为喜欢IT行业就找了个培训班,后来在一家小公司干了三年,现在跳槽来我们公司。来了之后把现有项目的性能优化了一遍,服务器缩减一半,性能反而提升4倍!给…...
使用篇丨链路追踪(Tracing)很简单:链路拓扑
作者:涯海 最近一年,小玉所在的业务部门发起了轰轰烈烈的微服务化运动,大量业务中台应用被拆分成更细粒度的微服务应用。为了迎接即将到来的双十一大促重保活动,小玉的主管让她在一周内梳理出订单中心的全局关键上下游依赖&#…...
2023年厦门等保二级备案办理流程
根据规定,已运营/运行或新建的第二级以上信息系统的企业,事业单位/行政机关/民办非企业单位/社团组织/其他组织必须办理等保备案。 2023年厦门等保二级备案办理流程 办理机构:公安局 办结时限:受理后10个工作日 办理方式:网上…...
提高开发效率,从这些小技巧开始——5个让你爱上IDEA的增加体验小技巧
前言 如果你是一名Java开发人员,那么你一定会使用IntelliJ IDEA这个IDE。IntelliJ IDEA作为目前最受欢迎的Java IDE之一,已经成为了众多Java开发人员必备的工具之一。但是,你是否知道如何利用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代理后无法访问
背景: 本地搭建好elk后,一切正常,后面改成用nginx代理kibana的5601端口,发现代理后无法正常访问(未代理的地址可正常访问),花了很多时间去查问题,报错基本都是http://ip:port/spaces…...
什么是分布式事务
目录 分布式事务基础 事务 本地事务 分布式事务 分布式事务的场景 分布式事务解决方案 全局事务 优点 缺点 可靠消息服务 第一步 :消息由系统A投递到中间件 超时访问机制 最大努力通知 第一步:消息由系统A投递到中间件 第二步:消息…...
在 Python 中将整数转换为罗马数字
罗马数字使用以下七个符号书写。 Symbol Value I 1 V 5 X 10 L 50 C 100 D 500 M 1000这些符号用于表示数以千计的数字。 罗马写20,可以用两个X拼成XX。 但是 XXXX 不…...
HashTable,Properties,TreeSet源码分析
目录 HashTable基本介绍 Hashtable和HashMap对比 Properties Properties基本介绍 应该如何选择集合 TreeSet源码分析 HashTable基本介绍 1)存放的元素是键值对:即K-V 2)hashtable的键和值都不能为null,否则会抛出NullPointerException 3)hashTab…...
OBS多路推流插件:打破平台壁垒,实现直播内容最大化触达
OBS多路推流插件:打破平台壁垒,实现直播内容最大化触达 【免费下载链接】obs-multi-rtmp OBS複数サイト同時配信プラグイン 项目地址: https://gitcode.com/gh_mirrors/ob/obs-multi-rtmp 想象一下,你正在直播一场重要的产品发布会&am…...
C语言实战:辗转相除法实现分数约分
1. 从生活场景理解分数约分 记得小时候第一次学分数时,老师总让我们把分数化成最简形式。比如6/8要写成3/4,当时觉得这就像给分数"减肥"一样有趣。其实在编程世界里,我们也经常需要处理类似的"分数减肥"问题,…...
X-Mouse Controls:5个专业技巧解锁Windows鼠标终极效率
X-Mouse Controls:5个专业技巧解锁Windows鼠标终极效率 【免费下载链接】xmouse-controls Microsoft Windows utility to manage the active window tracking/raising settings. This is known as x-mouse behavior or focus follows mouse on Unix and Linux syste…...
从玩具车到智能家居:用ESP32和NRF24L01搭建低成本多节点传感网实战
从玩具车到智能家居:用ESP32和NRF24L01搭建低成本多节点传感网实战 在智能家居和物联网领域,数据传输的可靠性和成本控制一直是开发者面临的两大挑战。传统Wi-Fi方案虽然普及,但在多节点场景下存在功耗高、网络拥堵等问题;而蓝牙M…...
【卷卷观察】菲尔兹奖得主亲测GPT-5.5 Pro:一小时产出博士级数学研究,我开始慌了
Tim Gowers,菲尔兹奖得主、剑桥数学教授,用了不到一小时让ChatGPT 5.5 Pro产出了一项博士级数学成果。全程没提供任何数学输入,纯旁观。他对这件事的结论是:培养数学博士的方式可能要变了。这话从一个菲尔兹奖得主嘴里说出来&…...
抖音内容采集架构革命:douyin-downloader深度重构与智能进化
抖音内容采集架构革命:douyin-downloader深度重构与智能进化 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback…...
Xplorer文件属性查看器:为什么你需要一个真正懂文件的文件管理器?
Xplorer文件属性查看器:为什么你需要一个真正懂文件的文件管理器? 【免费下载链接】xplorer Xplorer, a customizable, modern file manager 项目地址: https://gitcode.com/gh_mirrors/xp/xplorer 你是否曾经在文件管理时感到困惑?当…...
OpenClaw插件实战:一键审批按钮提升AI自动化交互效率
1. 项目概述与核心价值 如果你正在用 OpenClaw 管理 AI 驱动的自动化任务,并且把 Telegram 作为主要的通知和交互渠道,那你肯定遇到过这个场景:AI 在执行某个需要你授权的命令(比如 exec 指令)前,会弹出…...
AI Agent配置生成器:基于agentforge的自动化项目脚手架实践
1. 项目概述:AI Agent配置生成器最近在折腾AI Agent自动化流程的朋友,估计都绕不开一个核心痛点:配置。无论是想用Claude、GPT-4还是开源的Llama,要让一个Agent真正“动”起来,你得定义它的角色、设定它的目标、给它配…...
Windows Cleaner:开源免费的Windows系统清理工具,5分钟解决C盘爆红问题
Windows Cleaner:开源免费的Windows系统清理工具,5分钟解决C盘爆红问题 【免费下载链接】WindowsCleaner Windows Cleaner——专治C盘爆红及各种不服! 项目地址: https://gitcode.com/gh_mirrors/wi/WindowsCleaner 你是否经常被C盘爆…...
