声明:本文主要参考 stm32移植lvgl_NULL_1969的博客-CSDN博客_lvgl stm32 及 STM32移植LVGL8.0.2超详细的保姆级教程附移植好的工程文件 ,底层驱动主要采用正点原子触摸屏实验和定时器实验
主要需要触摸屏来实现屏幕的显示及触摸。
触摸屏需要底层的接口进行交互,GUI的主要工作就是用户交互,如果你想做带触摸功能的屏幕,就需要这些底层的函数。
LVGL主要是中间层的一些函数,负责联系底层的硬件驱动与上层的应用层,本文采用正点原子的触摸屏实验的源码,移植成功之后源码已上传至stm32f07+lvgl8.3工程(适配正点原子stm32拯救者开发板,3.5寸屏),并且后期的触摸屏移植及相关实验请参考lvgl触摸屏实验。
要定时进行屏幕刷新,定义刷新的时间。
主要步骤是在一个触摸屏的程序中添加一个定时器。
与所有的添加驱动方法类似,1234部基本可以搞定。主要步骤如下所述:
- 文件夹中添加驱动程序文件源文件
timer.c- 在keil的组中添加进来
timer.c文件,左侧菜单栏文件夹中右击ADD Exiting Files ...- 添加库文件
stm32xx_TIM.c,方法同上述步骤2- 添加头文件路径
菜单魔术棒->C/C++->Including Paths
github下载源码: GitHub地址
下载完毕后文件夹内容:

主要移植的部分所用的文件如上图所示。
因为源码中有头文件名称是:
#ifndef LV_CONF_H
#define LV_CONF_H
但其文件名为:lv_conf_template.h
因此先将文件名该为lv_conf.h,即文件移植配置文件,此处是必须的。
同时更改文件中宏定义(此处修改宏定0–>1的作用是使能这部分内容):

所有的移植程序都是需要将所需的文件按照前文所述的1、2、3、4步骤进行移植,只不过每次要建立的分组或者移植的程序稍有差别。
文件夹中添加驱动程序文件源文件
SRC文件夹,examples->poprting文件夹,lvgl.h,lv_conf_template.h添加进新工程的文件夹中在keil的中新建两个组
LVGLSRC,LVGLPORT。组中添加进来SRC文件夹及examples->poprting文件夹所有文件,
添加库文件,本节内容无,不需要库文件
添加头文件路径
LVGL等文件
很可怕,但从前往后看注意到第一个是C语言语法方面的错误,因此修改C标准,使用C99

这只是警告枚举类型应该用枚举里面所包含的元素,(即你在枚举里面使用了RESET = 0,但下面你使用枚举变量时定义的是0,但没有用RESET就会报这个警告)无需管
这个警告有点意思,主要参考 寂寞才学习的博客
大致总结如下所述:
🅰️ 变量初始化
🅱️ 使用了goto,并且goto之后又定义了变量,修改也比较简单,将变量声明提到goto前面
🆎 使用了switch,修复方法为对swich的每个case分支都加一个花括号
本处感觉不用修改
也不大需要改,这个错误的出现主要是数据类型报的错( 无符号转换成有符号数,但是数据的最高位是符号位 ),但此处为成熟代码,无需修改
我看见的错误就这一个,报错如本节标题所示错误,定位位置如下所述

我为了方便起见,直接只保留#include "lvgl.h"引用这个头文件就行了,就是把所有if结构除了#include "lvgl.h"全部删掉
改完上节的错误,有两个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) 中的部分,直接把example2和example3直接注释就好
/**
* 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
🥇大功告成,至少不报错了🥇

main.c中添加头文件
#include "lvgl.h"
#include "lv_port_disp_template.h"
#include "lv_port_indev_template.h"
按照步骤增加初始化函数和事务处理函数,代码及结构如下所示:
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条,具体如下所示.

网上找一下LVGL的栈大小设置,发现如下
#define LV_MEM_SIZE (128U * 1024U) /*[bytes]*/
继续修改,减小一点栈的空间大小。
#define LV_MEM_SIZE (32U * 1024U) /*[bytes]*/
改完之后无error!!!!
首先从\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的事务处理
}
}
心态接着炸呀!!!!
首先发现忘记修改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); //清除中断标志位
}
要修改相应的屏幕接口函数,主要是屏幕的刷新函数需要修改成自己的。
在#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的死循环中。
昨晚折腾的比较久了,心力交瘁,真的很想放弃,但是一想都忙了半天了,没有理由放弃,接着搞tm的,有看了很多视频,发现屏幕总只能点亮一部分,最后看了很多视频,最后在 快速入门LVGL第二期–显示驱动移植_bilibili 视频中找到灵感,应该是stm32的栈设置小了,直接开干!
打开startup_stm32f4_f0xxx.s启动文件,找到这一行,
Stack_Size EQU 0x00000400
改完
Stack_Size EQU 0x00000800
点灯成功!!!!
最终效果如下所示:

再次说明:本文所使用硬件为正点原子探索者f4;屏幕大小为3.5寸;若硬件不同,仅需对照本文第三节:lvgl中间层修改相应参数就好,最后本工程下载地址为:不知道为啥csdn下载不了,想要的话评论区吧
能看到这儿的都是勇士,正如您所见,我移植的过程中也充满了坎坷,但是遇到问题不要怕,所有的代码都是人写出来的,一定使能克服的。而且每个你成功解决的问题,都是可以明天用来吹的NB
最后送你一个小图标🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮
GivenIamadumbprogrammerandIamusingrspecandIamusingsporkandIwanttodebug...mmm...let'ssaaay,aspecforPhone.那么,我应该把“require'ruby-debug'”行放在哪里,以便在phone_spec.rb的特定点停止处理?(我所要求的只是一个大而粗的箭头,即使是一个有挑战性的程序员也能看到:-3)我已经尝试了很多位置,除非我没有正确测试它们,否则会发生一些奇怪的事情:在spec_helper.rb中的以下位置:require'rubygems'require'spork'
使用Ruby1.9.2运行IDE提示说需要gemruby-debug-base19x并提供安装它。但是,在尝试安装它时会显示消息Failedtoinstallgems.Followinggemswerenotinstalled:C:/ProgramFiles(x86)/JetBrains/RubyMine3.2.4/rb/gems/ruby-debug-base19x-0.11.30.pre2.gem:Errorinstallingruby-debug-base19x-0.11.30.pre2.gem:The'linecache19'nativegemrequiresinstall
我有:When/^(?:|I)follow"([^"]*)"(?:within"([^"]*)")?$/do|link,selector|with_scope(selector)doclick_link(link)endend我打电话的地方:Background:GivenIamanexistingadminuserWhenIfollow"CLIENTS"我的HTML是这样的:CLIENTS我一直收到这个错误:.F-.F--U-----U(::)failedsteps(::)nolinkwithtitle,idortext'CLIENTS'found(Capybara::Element
文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,
Ruby是否有逐步调试器,类似于Perl的“perl-d”? 最佳答案 ruby-debug(对于ruby1.8),debugger(对于ruby1.9),byebug(对于ruby2.0)以及trepanning系列都有一个-x或--trace选项。在调试器内部,命令setlinetrace将打开或关闭线路跟踪。这是themanualforruby-debug原来的答案已经修改,因为数据噪声文章的链接,唉,不再有效了。还添加了ruby-debug的后继者 关于ruby-Ruby
我给自己买了一个新的8gigUSBkey,我正在寻找一个合适的解决方案来拥有一个可移植RoR环境来学习。我在谷歌上搜索了一下,发现了一些可能性,但我很想听听一些现实生活中的经历和意见。谢谢! 最佳答案 我喜欢InstantRails,非常容易使用,无需安装程序,也不会修改您的系统环境。 关于ruby-on-rails-可移植RubyonRails环境,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/q
动画/*INITIALIZEANANIMATION 初始化一个动画*-----------------------*/lv_anim_ta;lv_anim_init(&a);/*MANDATORYSETTINGS 必选设置*------------------*//*Setthe"animator"function 设置“动画”功能*/lv_anim_set_exec_cb(&a,(lv_anim_exec_xcb_t)lv_obj_set_x);/*Setthe"animator"function*/lv_anim_set_var(&a,obj);/*Lengthoftheanim
LL库和HAL库简介LL:Low-Layer,底层库HAL:HardwareAbstractionLayer,硬件抽象层库LL库和hal库对比,很精简,这实际上是一个精简的库。LL库的配置选择如下:在STM32CUBEMX中,点击菜单的“ProjectManager”–>“AdvancedSettings”,在下面的界面中选择“AdvancedSettings”,然后在每个模块后面选择使用的库总结:1、如果使用的MCU是小容量的,那么STM32CubeLL将是最佳选择;2、如果结合可移植性和优化,使用STM32CubeHAL并使用特定的优化实现替换一些调用,可保持最大的可移植性。另外HAL和L
文章目录一、项目场景二、基本模块原理与调试方法分析——信源部分:三、信号处理部分和显示部分:四、基本的通信链路搭建:四、特殊模块:interpretedMATLABfunction:五、总结和坑点提醒一、项目场景 最近一个任务是使用simulink搭建一个MIMO串扰消除的链路,并用实际收到的数据进行测试,在搭建的过程中也遇到了不少的问题(当然这比vivado里面的debug好不知道多少倍)。准备趁着这个机会,先以一个很基本的通信链路对simulink基础和相关的debug方法进行总结。 在本篇中,主要记录simulink的基本原理和基本的SISO通信传输链路(QPSK方式),计划在下篇记
我已经开始使用RubyMine6。我正在处理Rails4、Ruby2.1.1项目。我无法找到如何使用Pow作为服务器调试到RubyMine。你能给我指明正确的方向吗? 最佳答案 我能够使用远程调试从RubyMine进行调试。我正在使用RubyMine6、Rails3、Ruby2.1.1。首先创建一个.powenv文件并添加:exportRUBY_DEBUG_PORT=1234exportPOW_WORKERS=1将以下gem添加到您的Gemfile:gem'ruby-debug-ide'gem'debase'创建一个新的初始化器st