LVGL移植和图片显示

最近闲来无事,偶尔刷到了移植LVGL的教程,今天肝完了机械原理又移植完LVGL库,真是收获满满的一天,先接一杯水去。

回来了,发个朋友圈高级一下,好困。

lvgl v8.3移植及组件使用_lvgl界面编辑器-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/weixin_45209978/article/details/127374115?spm=1001.2014.3001.5506LVGL - Light and Versatile Embedded Graphics Libraryicon-default.png?t=N7T8https://lvgl.io/tools/imageconverter以上的两个网址分别为野火霸天虎移植LVGL的教程,第二个是一个图片转C代码的一个在线网址。

具体步骤大概就是,我总结一下。

获取LVGL源码

先从github获取lvgl的源码


地址:GitHub - lvgl/lvgl: Embedded graphics library to create beautiful UIs for any MCU, MPU and display type.
这里选择v8.3下载

这是压缩包中含有的所有文件,接下来根据个人意愿进行修改。

删掉多余的东西 , 只保留以下部分。

为什么把其他的删掉,因为它们不包含我们需要的.c和.h文件。

顺便把留下的这五个东西介绍一下。

第一个demos     

跟它的名字一样,存放的是官方的demo,因此实际上我们也是可以删掉的,留下来的原因就是等我们移植完LVGL之后可以调用一下demo看看效果。

第二个examples 

存放的是一些关于示例代码,我们只需要留下里面的porting即可。

然后porting里的文件是三个(一对的.c和.h算一个)。

disp是显示相关的模板,fs是文件管理的模板,indev是输入相关的模板。

因为我的屏幕没有输入,也不需要文件管理,因此对于我来说只需要disp即可,但是其他没用到的最好也别删了,保不齐什么时候就用上了(没事的时候打算整个触摸屏再移植一下LVGL玩玩)。

然后就是src,这个就是核心的文件了,一个都不能少。

lv_conf_tempplate.h 这个文件是配置文件。

lvgl.h这个头文件里面包含了我们常用的其他头文件,因此我们只需要包含这个就等同于包含了其他很多头文件了,比较方便。

然后配置文件的名字我们需要把后面的_template给删掉,变成lv_conf.h。

修改名称的原因就在于LVGL里面源文件中包含的配置文件的名称就是lv_conf.h,


把所有的c文件加入到项目中

对的,就是所有。并且需要在

这个页面把所有的文件文件夹位置添加进去,(md,累死我了)。

在添加完所有文件之后就相当于移植进去了LVGL库。

根据实际情况修改   #include "lvgl\lvgl.h"    或者    #include "lvgl.h".

(  看编译器是否能找到文件位置  )

之后编译,一般有错就是xxx函数未定义,那肯定就是添加c文件的时候落东西了。

直到没有错误,一堆警告为止。(doghead)


工程文件修改

这里搬运一下大佬的。

1.启动文件

注意在启动文件中修改堆、栈大小,建议各设置 8kB 空间:(大一些也没关系)


2.lvgl

在做这个之前最好先了解一下你的屏幕是怎么驱动的,然后再做下面的工作。

1.先打开 lv_conf.h

  • 第27行,根据屏幕颜色数据类型修改
  • 第52行,指定lvgl的动态内存可用大小
  • 第96行,每英寸的像素,根据自己屏幕尺寸和像素算一下就好
  • 第258行,开启style初始化断言

其他的浏览一下即可,用到的时候再去深究。

打开 lv_port_disp_template.h,将开头的 #if 0 条件编译取消 ,把0改成1
打开 lv_port_disp_template.c,将开头的 #if 0 条件编译取消,把0改成1,设置一下屏幕宽和高的像素。

#define MY_DISP_HOR_RES    480
#define MY_DISP_VER_RES    800

2.看下面的 void lv_port_disp_init(void)

LVGL缓冲区的图像写入有三种方式

  • 第一种:一个缓冲区,默认存10行图像
  • 第二种:两个缓冲区,默认每个缓冲区存10行图像
  • 第三种:两个缓冲区,每个缓冲区存一整个屏幕的图像


这里我们用第二种,把第一种和第三种注释掉即可。

第二种是为存在DMA之类的数据传送机制的硬件设计的,可以把传送缓冲区的内容交给DMA处理,而cpu去执行其他工作(比如渲染),这里我暂时没用DMA,这样的话效果和第一种是一样的。(注:缓冲区大小为屏幕的1/10效果会比较好,这里为了节约一点RAM没有改大小)

也要记得把下面的  &draw_buf_dsc_1  改成  &draw_buf_dsc_2 。

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 * 10];                          /*A buffer for 10 rows*/
//    lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, MY_DISP_HOR_RES * 10);   /*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_2;/*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);
}

3.屏幕初始化

/*Initialize your display and the required peripherals.*/
static void disp_init(void)
{/*You code here*/NT35510_Init ();
}

4.刷新缓冲区

/*Flush the content of the internal buffer the specific area on the display*You can use DMA or any hardware acceleration to do this operation in the background but*'lv_disp_flush_ready()' has to be called when finished.*/
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{if(disp_flush_enabled) {uint32_t width = area->x2 - area->x1 + 1;uint32_t height = area->y2 - area->y1 + 1;NT35510_OpenWindow(area->x1,area->y1,width,height);NT35510_Write_Cmd ( CMD_SetPixel );	for(uint32_t i = 0;i < width * height;i++){NT35510_Write_Data ( color_p->full );color_p++;}//        /*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++;
//            }
//        }}/*IMPORTANT!!!*Inform the graphics library that you are ready with the flushing*/lv_disp_flush_ready(disp_drv);
}

5.接下来修改main函数

int main ( void )
{LED_GPIO_Config();NT35510_Init ();  TIM7_Configuration();DEBUG_USART_Config();lv_init();lv_port_disp_init();lv_obj_t* btn = lv_btn_create(lv_scr_act()); lv_obj_set_pos(btn, 100, 100);lv_obj_set_size(btn, 120, 50);lv_obj_t* label = lv_label_create(btn);lv_label_set_text(label, "Button");lv_obj_center(label);//	GTP_Init_Panel();while ( 1 ){lv_timer_handler();}
}

6.在周期位1s定时器中断里添加函数给lvgl做时钟

void  BASIC_TIM7_IRQHandler (void)
{if ( TIM_GetITStatus( BASIC_TIM7, TIM_IT_Update) != RESET ){lv_tick_inc(1);TIM_ClearITPendingBit(BASIC_TIM7, TIM_IT_Update);}
}

上述的有些操作调用了其他文件的函数,记得要包含相应函数的头文件,

比如SysTick_Handler()调用了lv_tick_inc(),那么在stm32f4xx_it.c开头要 加上#include “lvgl/lvgl.h”


效果如图所示

图片显示

1.首先准备一张英文名字的图片(不能是数字或者字母)

之后在在线转换网站中


2.按图所示进行设置之后输入图片,生成C代码


3.把C文件加入到工程中

图片文件不能太大,要不然单片机的flash放不下(也许可以放在sd卡中)。


4.将以下代码放到main函数中。

	lv_obj_t * bg_top;LV_IMG_DECLARE(nahida);bg_top = lv_img_create(lv_scr_act());lv_img_set_src(bg_top, &nahida );

就可以对图片进行显示。效果如下:

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RAG:如何从0到1搭建一个RAG应用

通过本文你可以了解到&#xff1a; 什么是RAG&#xff1f;如何搭建一个RAG应用&#xff1f;目前开源的RAG应用有哪些&#xff1f; 大模型学习参考&#xff1a; 1.大模型学习资料整理&#xff1a;大模型学习资料整理&#xff1a;如何从0到1学习大模型&#xff0c;搭建个人或企业…

手机连接ESP8266的WIFI,进入内置网页,输入要显示的内容,在OLED显示屏上显示文本

在这篇技术博客中&#xff0c;我们将探讨如何使用ESP8266 Wi-Fi 模块和SSD1306 OLED显示屏&#xff0c;构建一个简易的信息显示和交互系统。此系统能够让用户通过一个简单的Web界面输入信息&#xff0c;并将其显示在OLED屏幕上。这种设备的应用非常广泛&#xff0c;可以用于智能…

vue实现pdf下载——html2canvas

html2canvas 官方文档https://html2canvas.hertzen.com/getting-started html2canvas 的原理是通过遍历DOM树,将每一个HTML元素转化为Canvas对象,并叠加到一起形成一张完整的图片或者PDF文件。 1. 安装插件 npm install html2canvas jspdf --save 2.使用&#xff08;页面已经…

Leetcode刷题笔记9

1. 两数之和 1. 两数之和 - 力扣&#xff08;LeetCode&#xff09; 解法一&#xff1a;暴力枚举 没什么好说的&#xff0c;直接使用两个for循环&#xff0c;i从第一个元素开始&#xff0c;j从第二个元素开始遍历并寻找 时间复杂度&#xff1a;O(N^2) 空间复杂度&#xff1a…

4_机械臂位姿求逆理论及代码计算

1、aubo arcs sdk poseInverse 使用例子 auto cur_pose rpc_cli->getRobotInterface(robot_name)->getRobotState()->getTcpPose();// 2.288083 0.035207 1.550335auto pose_inv rpc_cli->getMath()->poseInverse(cur_pose);//结果&#xff1a;0.118611 -0.57…

blender

通用设置&#xff1a; 仅显示/取消隐藏&#xff1a;数字键盘/ 移动视角&#xff1a;shift鼠标中键 Blender如何给场景添加参考图片-百度经验 (baidu.com) 进入编辑模式&#xff1a;Tab 编辑模式&#xff1a;点-线-面 两个视图 法向显示&#xff1a;就能变成恶心的蓝红色 显…

自动驾驶---Perception之视觉点云雷达点云

1 前言 在自动驾驶领域&#xff0c;点云技术的发展历程可以追溯到自动驾驶技术的早期阶段&#xff0c;特别是在环境感知和地图构建方面。 在自动驾驶技术的早期技术研究中&#xff0c;视觉点云和和雷达点云都有出现。20世纪60年代&#xff0c;美国MIT的Roberts从2D图像中提取3D…

解锁ChatGPT:从GPT-2实践入手解密ChatGPT

⭐️我叫忆_恒心&#xff0c;一名喜欢书写博客的研究生&#x1f468;‍&#x1f393;。 如果觉得本文能帮到您&#xff0c;麻烦点个赞&#x1f44d;呗&#xff01; 近期会不断在专栏里进行更新讲解博客~~~ 有什么问题的小伙伴 欢迎留言提问欧&#xff0c;喜欢的小伙伴给个三连支…

LabVIEW开发实验室超导体电流特性测试系统

本系统旨在为学校实验室提供一个基于LabVIEW的超导体电流特性测试平台&#xff0c;通过精确测量超导体在不同温度和电流条件下的电学特性&#xff0c;帮助学生和研究人员深入理解超导体的物理性质。本文将从背景、目标、工作原理、使用方法、操作流程和注意事项等方面详细介绍该…

现代x86汇编-环境安装

今天端午节&#xff0c;独自在家&#xff0c;翻阅了张银奎老师编写的《现代x86汇编语言程序设计》一书&#xff0c;前言部分说明书中示例代码都是用微软visual C工具编写并使用微软宏汇编&#xff08;著名的MASM&#xff09;编译的&#xff0c;好久没有用微软vc了&#xff0c;假…

【UML用户指南】-13-对高级结构建模-包

目录 1、名称 2、元素 3、可见性 4、引入与引出 用包把建模元素安排成可作为一个组来处理的较大组块。可以控制这些元素的可见性&#xff0c;使一些元素在包外是可见的&#xff0c;而另一些元素要隐藏在包内。也可以用包表示系统体系结构的不同视图。 狗窝并不复杂&#x…

排序题+贪心

排序力扣题 一&#xff1a;合并区间 56. 合并区间 方法一&#xff1a;先排序再合并 如图&#xff0c;把区间按照起点从小到达排序&#xff0c;如果起点相同那么按照终点小的优先排序 然后每次记录一个区间&#xff0c;访问下一个区间&#xff1a; 如果下一个区间的起点<前…

Hexo+Github搭建个人博客教程

hexo官网&#xff1a;https://hexo.io/zh-cn/ butterfly 主题设置&#xff1a;https://butterfly.js.org/ GitHub地址&#xff1a;https://github.com/jerryc127/hexo-theme-butterfly 基础命令 初始化博客命令&#xff1a;hexo init “文件名” 开启本地服务&#xff08;本…

支付交易——在线支付系统基本概念

摘要 本文聚集于实战&#xff0c;只讲解最实用的知识点&#xff0c;至于支付起源、在线支付发展历程等科普知识&#xff0c;感兴趣的读者可参考其它优秀的支付类书籍或网络上其它优秀的文章。本章内容对大部分专业概念进行了极致简化&#xff0c;以便更好地帮助读者入门。实际…

XSS(跨站脚本攻击)

1.什么是xss XSS全称&#xff08;Cross Site Scripting&#xff09;跨站脚本攻击&#xff0c;为了避免和CSS层叠样式表名称冲突&#xff0c;所以改为了 XSS&#xff0c;是最常见的Web应用程序安全漏洞之一,XSS是指攻击者在网页中嵌入客户端脚本&#xff0c;通常是JavaScript编写…

Word中插入Mathtype右编号,调整公式与编号的位置

当你已经将mathtype内置于word后&#xff0c;可以使用右编号快速插入公式 但是往往会出现公式和编号出现的位置或之间的距离不合适 比如我在双栏下插入公式&#xff0c;会发现插入的公式与编号是适用于单栏的 解决办法&#xff1a; 开始->样式->MTDisplayLquation -&g…

【Python Cookbook】S02E04 文本模式的匹配和查找 match()、search()、findall() 以及 捕获组和 + 的含义

目录 问题解决方案讨论 问题 本文讨论一些按照特定的文本模式进行的查找和匹配。 解决方案 如果想要匹配的只是简单文字&#xff0c;通常我们使用一些内置的基本字符串方法即可&#xff0c;如&#xff1a;str.find()&#xff0c;str.startwith()&#xff0c;str.endswith() …

电脑存储设备,固态硬盘介绍,usb接口

简介 存储设备分为两大类主存和辅存&#xff0c;另外还有专门提供存储服务的网络存储 主存储器 随机存取存储器&#xff08;RAM, Random Access Memory&#xff09; 特点&#xff1a;高速、易失性存储器&#xff0c;断电后数据丢失。用途&#xff1a;临时存储正在使用的数据…

【Oracle生产运维】数据库服务器负载过高异常排查处理

说明 在Oracle数据库运维工作中&#xff0c;经常会遇到Oracle数据库服务器平均负载&#xff08;load average&#xff09;突然异常升高&#xff0c;如果放任不管&#xff0c;严重的情况下会出现数据库宕机、服务器重启等重大故障。因此&#xff0c;当发现数据库服务器平均负载…

log4j日志打印导致OOM问题

一、背景 某天压测&#xff0c;QPS压到一定值后机器就开始重启&#xff0c;出现OOM&#xff0c;好在线上机器配置了启动参数-XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath/**/**heapdump.hprof。将dump文件下载到本地&#xff0c;打开Java sdk bin目录下的jvisualvm工具&a…