stm32f407移植LVGL8.3.1实况(所有bug调试现场,最终成功点灯)

这篇具有很好参考价值的文章主要介绍了stm32f407移植LVGL8.3.1实况(所有bug调试现场,最终成功点灯)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

移植LVGL


声明:本文主要参考 stm32移植lvgl_NULL_1969的博客-CSDN博客_lvgl stm32 及 STM32移植LVGL8.0.2超详细的保姆级教程附移植好的工程文件 ,底层驱动主要采用正点原子触摸屏实验和定时器实验


1 驱动层接口


1.1 主要硬件接口

1.1.1 触摸屏

主要需要触摸屏来实现屏幕的显示及触摸。

触摸屏需要底层的接口进行交互,GUI的主要工作就是用户交互,如果你想做带触摸功能的屏幕,就需要这些底层的函数。

LVGL主要是中间层的一些函数,负责联系底层的硬件驱动与上层的应用层,本文采用正点原子的触摸屏实验的源码,移植成功之后源码已上传至stm32f07+lvgl8.3工程(适配正点原子stm32拯救者开发板,3.5寸屏),并且后期的触摸屏移植及相关实验请参考lvgl触摸屏实验。

1.1.2 定时器

要定时进行屏幕刷新,定义刷新的时间。


1.2 底层程序移植

主要步骤是在一个触摸屏的程序中添加一个定时器。

与所有的添加驱动方法类似,1234部基本可以搞定。主要步骤如下所述:

  1. 文件夹中添加驱动程序文件源文件timer.c
  2. 在keil的组中添加进来timer.c文件,左侧菜单栏文件夹中右击ADD Exiting Files ...
  3. 添加库文件stm32xx_TIM.c,方法同上述步骤2
  4. 添加头文件路径 菜单魔术棒->C/C++->Including Paths

2 源码下载


github下载源码: GitHub地址

下载完毕后文件夹内容:
lv_ver_res_max
主要移植的部分所用的文件如上图所示。


因为源码中有头文件名称是:

#ifndef LV_CONF_H
#define LV_CONF_H

但其文件名为:lv_conf_template.h

因此先将文件名该为lv_conf.h,即文件移植配置文件,此处是必须的。

同时更改文件中宏定义(此处修改宏定0–>1的作用是使能这部分内容):
lv_ver_res_max


3 中间层LVGL移植


3.1 物理移植

所有的移植程序都是需要将所需的文件按照前文所述的1、2、3、4步骤进行移植,只不过每次要建立的分组或者移植的程序稍有差别。

  1. 文件夹中添加驱动程序文件源文件SRC文件夹examples->poprting文件夹lvgl.h,lv_conf_template.h添加进新工程的文件夹中

  2. 在keil的中新建两个组LVGLSRC,LVGLPORT。组中添加进来SRC文件夹examples->poprting文件夹所有文件,
    lv_ver_res_max

  3. 添加库文件,本节内容无,不需要库文件

  4. 添加头文件路径 LVGL等文件
    lv_ver_res_max


3.2 修改移植bug (相当酸爽)

3.2.1 一开始4000+错误

很可怕,但从前往后看注意到第一个是C语言语法方面的错误,因此修改C标准,使用C99
lv_ver_res_max

3.2.2 软件修改bug–>warning部分
warning: #188-D: enumerated type mixed with another type

这只是警告枚举类型应该用枚举里面所包含的元素,(即你在枚举里面使用了RESET = 0,但下面你使用枚举变量时定义的是0,但没有用RESET就会报这个警告)无需管

warning: #546-D: transfer of control bypasses initialization of:

这个警告有点意思,主要参考 寂寞才学习的博客

大致总结如下所述:

🅰️ 变量初始化

🅱️ 使用了goto,并且goto之后又定义了变量,修改也比较简单,将变量声明提到goto前面

🆎 使用了switch,修复方法为对swich的每个case分支都加一个花括号

本处感觉不用修改

warning: #68-D: integer conversion resulted in a change of sign

也不大需要改,这个错误的出现主要是数据类型报的错( 无符号转换成有符号数,但是数据的最高位是符号位 ),但此处为成熟代码,无需修改

3.2.3 软件修改bug–>errror部分
error: #5: cannot open source input file “lvgl/lvgl.h”: No such file or directory

我看见的错误就这一个,报错如本节标题所示错误,定位位置如下所述

lv_ver_res_max

我为了方便起见,直接只保留#include "lvgl.h"引用这个头文件就行了,就是把所有if结构除了#include "lvgl.h"全部删掉

3.2.3.2 修改像素

改完上节的错误,有两个warning提示我修改像素分辨率,比较简单

..\LVGL\examples\porting\lv_port_disp_template.c(19): warning:  #1215-D: #warning directive: Please define or replace the macro MY_DISP_HOR_RES with the actual screen width, default value 320 is used for now.
  #warning Please define or replace the macro MY_DISP_HOR_RES with the actual screen width, default value 320 is used for now.

定位错误:

#ifndef MY_DISP_HOR_RES
    #warning Please define or replace the macro MY_DISP_HOR_RES with the actual screen width, default value 320 is used for now. //报错的原因
    #define MY_DISP_HOR_RES    320 //像素的默认分辨率
#endif

还有一个error…

error: #20: identifier “LV_VER_RES_MAX” is undefined

定位了一下错误发现是在Example for 3) 中的部分,直接把example2example3直接注释就好

   /**
     * 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*/

此外还需要主要修改一个参数(屏幕位色)

#define LV_COLOR_DEPTH 16

🥇大功告成​,​至少​不报错​了🥇

lv_ver_res_max


4 stm32移植修改(准备上机,点灯!!!)


4.1 添加头文件

main.c中添加头文件

#include "lvgl.h"
#include "lv_port_disp_template.h"
#include "lv_port_indev_template.h"

4.2 报错:栈空间

按照步骤增加初始化函数和事务处理函数,代码及结构如下所示:

int main(void)
{ 

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);  //初始化延时函数
	uart_init(115200);		//初始化串口波特率为115200
	
	TIM3_Int_Init(1000-1,84-1);	//定时器时钟84M,分频系数84,所以84M/84=1Mhz的计数频率,计数1000次为1ms
	
	LED_Init();					//初始化LED 
 	LCD_Init();					//LCD初始化 
	KEY_Init(); 				//按键初始化  
	tp_dev.init();				//触摸屏初始化
	
	lv_init();			  // lvgl系统初始化
	lv_port_disp_init();  // lvgl显示接口初始化,放在lv_init()的后面
	lv_port_indev_init(); // lvgl输入接口初始化,放在lv_init()的后面

	while (1)
	{
		lv_task_handler(); // lvgl的事务处理
	}	
}

心态炸了 ⏰ 又是报错,这次报错的原因是栈空间不够,一下子59条,具体如下所示.
lv_ver_res_max

网上找一下LVGL的栈大小设置,发现如下

#define LV_MEM_SIZE (128U * 1024U)          /*[bytes]*/

继续修改,减小一点栈的空间大小。

#define LV_MEM_SIZE (32U * 1024U)          /*[bytes]*/

改完之后无error!!!!


4.3 添加点灯程序

首先从\LVGL\examples\widgets\led中的led的例子,代码如下:

void lv_example_led_1(void)
{
    /*Create a LED and switch it OFF*/
    lv_obj_t * led1  = lv_led_create(lv_scr_act());
    lv_obj_align(led1, LV_ALIGN_CENTER, -80, 0);
    lv_led_off(led1);

    /*Copy the previous LED and set a brightness*/
    lv_obj_t * led2  = lv_led_create(lv_scr_act());
    lv_obj_align(led2, LV_ALIGN_CENTER, 0, 0);
    lv_led_set_brightness(led2, 150);
    lv_led_set_color(led2, lv_palette_main(LV_PALETTE_RED));

    /*Copy the previous LED and switch it ON*/
    lv_obj_t * led3  = lv_led_create(lv_scr_act());
    lv_obj_align(led3, LV_ALIGN_CENTER, 80, 0);
    lv_led_on(led3);
}

然后再修改相应的mian函数,使用当前的LVGL,代码如下所示。

int main(void)
{ 

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);  //初始化延时函数
	uart_init(115200);		//初始化串口波特率为115200
	
	TIM3_Int_Init(1000-1,84-1);	//定时器时钟84M,分频系数84,所以84M/84=1Mhz的计数频率,计数1000次为1ms
	
	LED_Init();					//初始化LED 
 	LCD_Init();					//LCD初始化 
	KEY_Init(); 				//按键初始化  
	tp_dev.init();				//触摸屏初始化
	
	lv_init();			  // lvgl系统初始化
	lv_port_disp_init();  // lvgl显示接口初始化,放在lv_init()的后面
	lv_port_indev_init(); // lvgl输入接口初始化,放在lv_init()的后面
	lv_example_led_1();
	
	while (1)
	{
		lv_task_handler(); // lvgl的事务处理
	}	
}

4.4 接着报错,遥遥无期:LVGL屏幕点灯并未成功!!!

心态接着炸呀!!!!

4.4.1 发现未加定时器心跳

首先发现忘记修改TIM3_IRQHandler的中断函数,最终代码如下所示:

//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
	{
		LED1=!LED1;//DS1翻转
		lv_tick_inc(1);
	}
	TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除中断标志位
}
4.4.2 发现未添加屏幕接口

要修改相应的屏幕接口函数,主要是屏幕的刷新函数需要修改成自己的。

#include "lv_port_disp_template.c"中添加头文件#include "lcd.h"

其次修改屏幕的接口刷新函数如下所示:

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,(uint16_t *)color_p);
    /*IMPORTANT!!!
     *Inform the graphics library that you are ready with the flushing*/
    lv_disp_flush_ready(disp_drv);
}

改完之后屏幕有反应,但却是乱点,心碎。。。初步判断刷新函数错误

LCD_Color_Fill(area->x1,area->y1,area->x2,area->y2,(uint16_t *)color_p);

因为函数进行到此之后总是进入harddefault的死循环中。


4.5 LVGL点灯成功!!!!(修改STM32的栈大小)

昨晚折腾的比较久了,心力交瘁,真的很想放弃,但是一想都忙了半天了,没有理由放弃,接着搞tm的,有看了很多视频,发现屏幕总只能点亮一部分,最后看了很多视频,最后在 快速入门LVGL第二期–显示驱动移植_bilibili 视频中找到灵感,应该是stm32的栈设置小了,直接开干!

打开startup_stm32f4_f0xxx.s启动文件,找到这一行,

Stack_Size      EQU     0x00000400

改完

Stack_Size      EQU     0x00000800

点灯成功!!!!

最终效果如下所示:

lv_ver_res_max

工程下载

再次说明:本文所使用硬件为正点原子探索者f4;屏幕大小为3.5寸;若硬件不同,仅需对照本文第三节:lvgl中间层修改相应参数就好,最后本工程下载地址为:不知道为啥csdn下载不了,想要的话评论区吧


能看到这儿的都是勇士,正如您所见,我移植的过程中也充满了坎坷,但是遇到问题不要怕,所有的代码都是人写出来的,一定使能克服的。而且每个你成功解决的问题,都是可以明天用来吹的NB ​
最后送你一个小图标​🐮​🐮​🐮​🐮​🐮​🐮​🐮​🐮​🐮​🐮​🐮​🐮​🐮​🐮​🐮​🐮​🐮文章来源地址https://www.toymoban.com/news/detail-794858.html

到了这里,关于stm32f407移植LVGL8.3.1实况(所有bug调试现场,最终成功点灯)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)

    因为板子是stm32F407的第二版的,所以开始下的资料是旧版本的,但是旧版本的FreeRTOS工程没有hal库的,都是标准库的,这里是下载stm32F407最新版的资料,进行移植。 资料可以在正点原子官网下载,如下: http://www.openedv.com/docs/boards/stm32/index.html 一定要下载最新的资料(开始用

    2024年02月06日
    浏览(72)
  • 从STM32F407到AT32F407(一)

    雅特力公司的MCU有着性能超群,价格优越的巨大优势,缺点是相关资料少一些,我们可以充分利用ST的现有资源来开发它。 我用雅特力的STM32F437开发板,使用原子 stm32f407的开发板自带程序,测试串口程序,原设定串口波特率为115200,但是输出乱码,波特率改成230400,串口输

    2024年02月02日
    浏览(50)
  • LVGL学习笔记(二):从0到1移植LVGL8.1到STM32平台上(完结篇)

    目录 一:TFT-LCD屏触摸 二:STM32CubeMX配置 三:FT5206触摸芯片驱动代码移植 四:LVGL 移植 4.1 源码下载 4.2 代码移植  4.3 添加源码至工程 4.4 指定头文件路径 4.5 设置编译参数  4.6 修改LVGL源文件   4.7 修改显示驱动接口    4.8 修改输入设备驱动接口  五:下载验证  六:工

    2024年02月03日
    浏览(38)
  • EtherCAT主站源码 基于STM32F407和STM32H743两款芯片 通过移植开源SOME主站代码,使两款芯片具有EtherCAT主站功能,支持DC同步功能

    EtherCAT主站源码基于STM32F407和STM32H743两款芯片,通过移植开源SOME主站代码,使两款芯片具有EtherCAT主站功能,支持DC同步功能。可支持汇川IS620N、松下A5B/A6B、欧姆龙G5系列、埃斯顿ProNet、迈信EP3E、台达A2-E,伟创SD700这几款EtherCAT总线伺服。支持的这些驱动器可以混用,主站自动

    2024年02月04日
    浏览(37)
  • STM32移植LVGL8.0.2超详细的保姆级教程附移植好的工程文件

    网上教程那么多,为什么你要写这个教程? 问的好,csnd上很多类似的教程,他们写的都很好,但是有些过于简洁,对刚上手的小伙伴不太友好,移植到一半遇到bug就想放弃。一些第三方的教程很详细,但是由于lvgl的版本迭代很快,移植的过程有了一些变化,所谓失之毫厘差

    2024年02月03日
    浏览(37)
  • STM32F407的介绍

    内核 32位 高性能ARM Cortex-M4处理器 时钟: 高达168MHz,实际还可以超频一点点 stm32f407的主频通过PLL倍频后能够达到168MHz,而且芯片内置一个16MHz的晶振和一个32KHz的晶振,可以满足不同功耗的需求。 支持FPU(浮点运算)和DSP指令 144引脚 114个IO口 存储器容量: 1024K FLASH, 192K

    2024年02月10日
    浏览(42)
  • STM32F407的时钟

    时钟源用来为环形脉冲发生器提供频率稳定且电平匹配的方波时钟脉冲信号。它通常由石英 晶体振荡器和与非门组成的正反馈振荡电路组成,其输出送至环形脉冲发生器。 F4开发指南P107 F4开发指南P108 HSI高速内部时钟源 High Speed Internal。RC 振荡器,频率为 16MHz。可以直接作为

    2024年02月10日
    浏览(43)
  • STM32F407——串口通信

    本文将对串口通信的分类和基于 stm32 的串口配置进行介绍,以及如何使用串口调试助手进行串口收发功能的调试,旨在帮助还不会使用 stm32 单片机串口资源进行通信的家人们快速学会如何使用串口来进行通信。 (纯干货、快速上手、零基础也能会!!!) (1)串口,即串

    2023年04月08日
    浏览(40)
  • 初识 STM32和STM32F407简介

    2007 年 6 月,ST 在北京发布了全球第一款基于 ARM Cortex M3 内核的 32 位通用微控制 器芯片:STM32F103,以优异的性能,丰富的资源,超高的性价比,迅速占领市场,从此一鸣 惊人,一发不可收拾,截止到 2020 年 6 月,STM32 累计出货量超过 45 亿颗。 战舰开发板使用的 STM32F103ZET6

    2023年04月08日
    浏览(64)
  • STM32F407 --USART使用

    目录 1. 串口配置--普通模式 2. 实现数据的传输主函数 1)单引号双引号的应用数组传输 2)将调试信息用串口打印传送到电脑上 1. 串口配置--普通模式 F407使用的M4内核与F103使用的M3内核不一样,导致在使用配置上有区别。需要在F103配置的基础上专门将GPIO的PIN配置成复用功能

    2024年02月16日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包