STM32F1,LVGL简易DEMO移植

news/2024/10/19 16:38:03

简介

尝试过在ESP32上移植LVGL之后,再在STM32上面LVGL,确认下是不是可以用
虽然STM32F103ZE的ROM及RAM都没有ESP32丰富,便对应于LVGL的最低配置要求,应该也可以正常运行的。不过也只能移植简单的
按键显示,像复杂一些DEMO,在STM32F1不用了,资源不够,导致编译不通过。

LVGL

LVGL是一款比较流行的致力于MCU与MPU创建漂亮UI的嵌入式图形库,免费且开源。

最低要求

ROM > 64KB
RAM > 2K
STACK > 2K
HEAP > 2K

移植步骤

LVGL移植总的步骤主要是如下几步
1.调用lv_init();
2.初始化驱动
3.注册显示与输入驱动,显存的配置,显示响应回调函数的响应
4.lv_tick_inc(x) 在中断中定时更新,x设定取决于lv_tick_inc的调用频率
5.lv_timer_handler,定时调用,完成LVGL的响应(更新LVGL的响应)

具体示例

使用的是正点原子STM32F103ZE开发板

拷贝一个LCD可以正常驱动的工程

拷贝LVGL源码至工程

这里使用的是V8.3.0
拷贝完之后需要将源码添加至工程,并添加相应的include路径,STM32的添加LVGL的文件相对ESP32来说,就麻烦很多
需要每个文件都添加进工程
主要包括lvgl/src, lvgl/exmaples/porting(这个路径也可以不添加,在自己定义的移植文件路径添加即可)

如果一次没成功,也没事,可以根据提示的编译错误慢慢添加
重命令lv_conf.h,并使能#if 0 改为#if 1
LVGL需要编译器支持C99模式,不然无法编译通过
因为将lv_conf.h独立于LVGL的源码,需要添加预定义LV_CONF_INCLUDE_SIMPLE,没加的话,编译会提示这个错误,加上就可以正常编译
在INCLUDE的路径下添加LVGL源码路径
lvgl/example/porting目录下的移植文件拷贝到工程目录下,lv_port_disp_template与lv_port_indev_template并重命名为lv_port_disp.h, lv_port_disp.c, lv_port_indev.h, lv_port_indev.c
因为改变了路径,文件不放在LVGL源码的路径下, 直接include "lvgl.h"即可,并使能两个文件#if 0 改为 #if 1

屏幕驱动

分配好显存,移植LCD区域点阵更新操作

void lv_port_disp_init(void)
{/*-------------------------* Initialize your display* -----------------------*/disp_init();/* Example for 1) */lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, MY_DISP_HOR_RES * 10);   /*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;///*Finally register the driver*/lv_disp_drv_register(&disp_drv);
}static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{LCD_Color_Fill(area->x1, area->y1, area->x2, area->y2, (uint16_t*)color_p);/*IMPORTANT!!!*Inform the graphics library that you are ready with the flushing*/lv_disp_flush_ready(disp_drv);
}

输入驱动

这里以电阻触摸屏为例,给到LVGL的触点信息必须是和屏幕位置相对应的
校准具体模拟值与感应像素点的位置的操作,应该在BSP层里面做好,最后传给LVGL是像素逻辑位置

void lv_port_indev_init(void)
{static lv_indev_drv_t indev_drv;touchpad_init();/*Register a touchpad input device*/lv_indev_drv_init(&indev_drv);indev_drv.type = LV_INDEV_TYPE_POINTER;indev_drv.read_cb = touchpad_read;indev_touchpad = lv_indev_drv_register(&indev_drv);
}/*Initialize your touchpad*/
static void touchpad_init(void)
{/*Your code comes here*/
}/*Will be called by the library to read the touchpad*/
static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{static lv_coord_t last_x = 0;static lv_coord_t last_y = 0;/*Save the pressed coordinates and the state*/if(touchpad_is_pressed()) {touchpad_get_xy(&last_x, &last_y);data->state = LV_INDEV_STATE_PR;}else {data->state = LV_INDEV_STATE_REL;}/*Set the last pressed coordinates*/data->point.x = last_x;data->point.y = last_y;
}/*Return true is the touchpad is pressed*/
static bool touchpad_is_pressed(void)
{/*Your code comes here*/tp_dev.scan(0);if(tp_dev.sta&TP_PRES_DOWN)return true;elsereturn false;
}/*Get the x and y coordinates if the touchpad is pressed*/
static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y)
{/*Your code comes here*/(*x) = tp_dev.x[0];(*y) = tp_dev.y[0];
}

初始化及调用

在SYSTICK中断函数里,将LVGL计时增加

void SysTick_Handler(void)
{HAL_IncTick();lv_tick_inc(1);
}

初始化并调用

    lv_init();lv_port_disp_init();lv_port_indev_init();lv_example_btn_1();while(1) {		lv_timer_handler();delay_ms(3);} 

存在问题

编译通过后,烧录到硬件,发现只显示部分就卡死了
单步调试时,发生HardFault错误
原因是默认的STACK深度不够,导致跑LVGL的栈溢出了,整个程序就出错了
需要修改默认的栈深度,针对按钮测试DEMO,暂改为0x800的大小

Stack_Size      EQU     0x00000800AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size

显示图片

其他

使用片上SRAM可以使用LVGL,使用外部的SRAM也可以正常使用LVGL

总结

这里只是验证了,LVGL在STM32F1上面是可以跑起来的,具体的使用及细节还是需要在实际用到的项目去了解及深入

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

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

相关文章

于国庆回高中母校省锡中有感(搬运自qq空间)

于2024.10.6下午在回京高铁上浅记一下昨日回省锡中的一些事(虽然到宿舍才发) 有些东西还是一如既往,比如乐群湖边乱窜的白鹅,某人的摩托车;但有些已悄然发生了变化,诚信超市5元大瓶装饮料被取缔,为防止糖尿病小卖部含糖饮品被禁售(太了吧),教室外走廊上多出的公共饮水…

数据采集与融合技术实践作业一

作业1:大学排名数据爬取 作业代码和图片主要代码import urllib.request from bs4 import BeautifulSoup import re # 导入正则表达式模块# 指定要爬取的URL url = http://www.shanghairanking.cn/rankings/bcur/2020# 发送请求获取网页内容 response = urllib.request.urlope…

解决driverClassName: com.mysql.cj.jdbc.Driver报红问题

为将项目从postgre库转为本地mysql数据库,需要将数据库驱动改为mysql 1.在父工程的pom中引入数据库<!-- Mysql驱动包 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.28</…

SpringBoot 整合 RabbitMQ

简介 一般在开发过程中: 生产者工程:application.yml 文件配置 RabbitMQ 相关信息;在生产者工程中编写配置类,用于创建交换机和队列,并进行绑定;注入 RabbitTemplate 对象,通过 RabbitTemplate 对象发送消息到交换机。消费者工程:application.yml 文件配置 RabbitMQ 相…

P3571 [POI2014] SUP-Supercomputer 题解

P3571「POI2014」SUP-Supercomputer 题解 一道 “较” 水的黑题 (可一开始苦思冥想还是不会)。 本蒟蒻的第一篇黑题题解,求赞。 题意简化 给定一棵 $n$ 个节点、根节点为 $1$ 的有根树。$q$ 次询问中每次给定一个 $k$,输出需要最少用几次操作次数 删除 完整棵树。每次操作可…

Spring IoC

一、Spring IoC的理解IoC(Inversion of Control:控制反转) 是一种设计思想,而不是一个具体的技术实现。IoC 的思想就是将原本在程序中手动创建对象的控制权,交由 Spring 框架来管理。不过, IoC 并非 Spring 特有,在其他语言中也有应用。 控制反转?控制:指的是对象创建(…

修改VS的代码高亮颜色

点击工具->选项选择“字体和颜色”找到“用户成员-xx”、“用户类型-xx”,点击即可修改前景色、背景色

ArkUI-Image详解

ArkUI-Image详解 文章摘要: 给Image组件设置属性可以使图片显示更灵活,达到一些自定义的效果。以下是几个常用属性的使用示例。这时可以使用interpolation属性对图片进行插值,使图片显示得更清晰。Image组件引入本地图片路径,即可显示图片(根目录为ets文件夹)。通过rende…