首页 > 其他分享 >LVGL 移植到 STM32 通法 ( 例:LVGL 9.2.2 到 STM32F429 )

LVGL 移植到 STM32 通法 ( 例:LVGL 9.2.2 到 STM32F429 )

时间:2024-12-22 09:00:11浏览次数:10  
标签:lv lvgl .. 文件 lvgls STM32 src 通法 LVGL

 

心法:

以往看过很多的移植教程、在 Keil 里面添加很多的文件分组、进到 LVGL 源码文件夹,进进出出多级目录添加很多的源码文件、这个添加,那个不需要添加,着实吓人 + 劝退人。

 

1. Keil 里面的文件分组的 组织结构、取名对编译根本不重要,只是方便程序员管理文件。 不过要注意,需要把 。C文件添加 (实际就是让 Keil 记录该文件的路径) 到 Keil 工程,Keil 才会编译该源码文件,生成对应的 。O文件。

2. 其实把 LVGL 源码全添加进 Keil 编译也是没问题的、把  。C 文件编译成 。O 二进制文件,在链接阶段,链接器需要哪个。O文件自己拿去链接就行,对这方面感到疑惑的可以看 C/C++编译过程。

对于各种工程绝大部分情况下、多余添加源码文件进编译是没问题的,不被调用的函数 链接器 不会使用 那个函数所在的 。O文件,影响只有增加编译时间、产生多一点的 。O文件占用电脑硬盘,编译出来的最终文件即烧录进 STM32 的那个文件保持不变。

极少数情况下,多添加文件进行编译会产生冲突,比如 STM32F429 的 FMC 和 FSMC 源文件,同时只能编译一个,这还可能是 库文件设计者 有意为之。

而少添加原文件必定出问题,比如 undefine symbol。

 

材料准备:

1. 获取 LVGL 源码

建议电脑安装 TortoiseGit ,可以以图形界面方式使用 Git。

选择一个文件夹,右键点击 Git Clone , 输入 LVGL 源码链接 https://github.com/lvgl/lvgl.git,将LVGL 源码克隆到本地。

进到 LVGL 源码目录,如需回退源码到最新发布的版本,以图更稳定可靠,可右键选择 TortoiseGit--》 Switch/Checkout --》选择 Tag 。 往下拉选择最新的 Tag。 

 按需 取消勾选 Create New Brach。 

 LVGL 9.2.2 源码文件夹 如下图:

不管版本如何变,移植到 STM32 (用 Keil 编译) 时,src 文件夹和 源码根目录 下的 。h 。C 文件都一概先复制过去。

下图高亮的是本次移植用到的文件(夹)

2. STM32 触摸屏工程

 广告:如 野火的工程:( 野火的教程、代码风格真是好,SMT32 和 FreeRTOS 教会了我很多,感谢野火。)

可惜我当年不懂得,错买了正点的板子。所以呢,我这个列子用的是 正点原子 的板子 STM32F429,搭载的是 SPI 接口的 4.3 寸 MCU 电容式触摸屏。

吐槽:鉴于 教程信息密度、源码风格、PDF手册权限等问题,建议不买正点原子的东西。

 

文件路径及结构

一级 lvgls:

在 触摸屏 工程根目录下创建一个 lvgls 文件夹 ( 可以取名其它英文字母名 )。

二级 lvgl 及 lv_app:

lvgls 下创建 lvgl 和 lv_app 文件夹,同理 这两个文件夹也可以取名其它英文字母名 。

三级源码文件(夹):

lvgl 下的 demos、src 文件夹 直接原封不动从 lvgl 源码文件夹复制过来。

examples 文件夹也可以直接从 lvgl 源码文件夹原封不动复制过来,但实际只需要里面的 porting 文件夹,所以自己精简。

lvgl 源码文件夹根目录的 。C 。h文件一并复制过来。

lvgl 下的 lv_conf_template.h 复制到上一层目录,并改名为  lv_conf.h 。

 将 lvgl / examples / porting 中选中的文件复制到 与 lv_conf.h 文件同一目录下,并把 template 字眼去掉。分别是 ( **disp )显示 设备和 (**indev )输入设备的接口。

 完成后  lvgls 文件夹下 :

 

Keil 工程:

src 文件分组

根据 lvgl / src 下的文件夹 (左) 在 keil 中创建相应的分组 (右),并多加一个 LVGL_SRC  用于添加 lvgl /src 下的 。C 文件,本例子中是 lv_init.c 。

 

没有注明的话,src 文件夹包括 各级子文件夹 所有 。C文件都添加到 Keil 的相应分组中。

当然根据文章开头说的,不嫌麻烦可以一股脑添加完所有 。C文件进 Keil 编译。

draw 中不需要添加 nxp 、renesas 、sdl 文件夹,其他均添加。

drivers 文件夹 都不 添加

libs 一定要添加 bin_decoder , 实际操作我把 图里 框中的都加上了,其它都不加。

 

千万记得 lvgl / src 下面的 。C 文件也要添加进 Keil , 本例中加到 LVGL_SRC 分组,本例中是 lv_init.c 。

 把头文件路径加到 Keil : 深度只需要到 lvgl / src /core 这个级别。当然,手动添加头文件路径有点烦,后面有骚操作

 

骚操作:你可以先保存好 Keil 工程、关闭工程,用高级一点的文本编辑器打开 Keil 工程文件( .uvprojx 文件),所谓的高级一点为的是 能 设置、区分 Windows、Unix、Macintosh文件?结尾 ,

这么说只是为了更保险,一般编辑软件都可以。

工程文件中搜索 IncludePath ,观察已有的 头文件路径信息,确定好该往这个位置加入新的头文件路径,即可复制我的路径去使用。如果你的 lvgl 文件位置和文件夹名称和我的一样,就可以啥也不改,直接黏贴。

..\lvgls;..\lvgls\lvgl;..\lvgls\lvgl\src;..\lvgls\lvgl\src\core;..\lvgls\lvgl\src\display;..\lvgls\lvgl\src\draw;..\lvgls\lvgl\src\drivers;..\lvgls\lvgl\src\font;..\lvgls\lvgl\src\indev;..\lvgls\lvgl\src\layouts;..\lvgls\lvgl\src\libs;..\lvgls\lvgl\src\misc;..\lvgls\lvgl\src\osal;..\lvgls\lvgl\src\others;..\lvgls\lvgl\src\stdlib;..\lvgls\lvgl\src\themes;..\lvgls\lvgl\src\tick;..\lvgls\lvgl\src\widgets;..\lvgls\lvgl\demos;..\lvgls\lvgl\demos\benchmark;..\lvgls\lvgl\demos\widgets;..\lvgls\lvgl\demos\scroll;..\lvgls\lvgl\demos\music

其实 Keil 中的文件分组也可以用这个套路快速添加,我添加的时候 修改两个工程文件,那个修改包含太多文字,就不贴出来了,大家还是多熟悉一下操作。

Keil 中再 创建 LVGL_PORTING 和 LVGL_DEMO 分组:

LVGL_PORTING 添加 lvgls 文件夹下的 。C 文件,把 lv_conf.h 也加进来便于修改。

LVGL_DEMO 添加  lvgl /demos  根目录下的 。C文件 ( 本例是 lv_demos.c) 以及 widgets 子文件夹下所有 。C文件,我们先跑 widgets 这个例子。

还想跑其他例子,就自己加相应例子文件, 实际我还加了 bechmark、scroll、music 例子的。

 给 Keil 添加头文件路径:

 

至此 文件添加工作完成。

 

修改代码:

涉及的文件:

 

改堆栈 大小 

启动文件 startup_stm32f429xx.s 改 stack 和 heap 大小, 都为 0x2000 ,即 8 K 

 

给 lvgl 加心跳

伴随 HAL_IncTick(); 所在位置,本例是 stm32f4xx_it.c  文件中:

 #include "lv_tick.h"

/****其它******/

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

当然也可以 改为 选择在 定时器中断中 执行   lv_tick_inc(1); 。 

 

lv_confg.h 中 :

打开 lv_conf.h ,把 第一个 # if 0  改为 # if 1 从而使能文件,下文简称 使能文件。

文件中 #define LV_COLOR_DEPTH 16  是配置屏幕色彩深度、我的 LCD 屏幕是 RGB565 , 所以保持无需变更。

有使能 demo 的宏,本例跑 widgets 例子,所以使能:

lv_port_disp.c 中:

使能文件后,添加需要的 屏幕头文件,我这里多加了 usart.h 是为了使用 printf 函数,在串口打印调试信息。

修改屏幕分辨率适配自己的屏幕。

 修改 lv_port_disp_init 函数,分配 内存,有三种分配方式,本例用了模板 的 Example 1 , 目前我的理解是 lvgl 将像素信息输出到这个内存空间,然后 STM32 从这个空间获取像素信息赋值给 屏幕显示。

比如  LVGL ——》该内存空间——》DMA2D 外设自动复制该空间的(像素)数据到 ——》 STM32另一个内存空间(通常是称为 显存 的内存空间,通常在 SDRAM 中分配)——》 LTDC 自动复制 显存中的(像素)数据到 ——》LCD屏幕。

本例中有 SDRAM 的,使用__attribute__ ((at( 0XC03E8000))) 分配到了 SDRAM 中,本例中SDRAM 开始的地址为 0XC0000000,之所以放到 0XC03E8000 是因为前面的空间可能被其他工程代码用作 LCD 的显存。

 修改 disp_flush 函数。这个得阅读 屏幕驱动函数了,就是找 在一个矩形空间填充彩色像素能用哪个函数,或者用绘制一个彩色点的函数一个个像素点绘制(会比较慢)。

其中  px_map 是指向像素数据的指针,目前我的理解是传入 屏幕驱动函数 如 LCD_Color_Fill  时,px_map 被强制转换成相应的类型,如本例的 (u16* ) 本质是与 屏幕颜色深度相关、

其次是与 LCD_Color_Fill 函数原型相关。

lv_port_indev.c 中:

使能文件、添加必要的 触摸屏头文件如 #include "touch.h"

函数 lv_port_indev_init 中仅保留 touchpad 部分的代码,其他可以用 # if  0   及 #endif 编译宏失能。 

 修改 touchpad_is_pressed 和 touchpad_get_xy 函数 :

main.c 中:

引入头文件

#include "lvgl.h"
#include "lv_port_disp.h"
#include "lv_port_indev.h"
#include "lv_demos.h"
#include "lv_demo_widgets.hint main(void){    HAL_Init();                     //初始化HAL库   

mian 函数

int main(void)
{
    HAL_Init();                      //初始化HAL库   
    Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz
    delay_init(180);                //初始化延时函数
    uart_init(115200);              //初始化USART
    LED_Init();                     //初始化LED 
    KEY_Init();                     //初始化按键
    SDRAM_Init();                   //初始化SDRAM
    LCD_Init();                     //初始化LCD
    tp_dev.init();                  //触摸屏初始化 

#if 1
    LCD_Display_Dir(1);       // LCD 设为横屏
    tp_dev.touchtype = 1;   // 触摸屏 设为横屏
    lv_init();
    lv_port_disp_init();
    lv_port_indev_init();

    lv_demo_widgets();
    //lv_demo_scroll();
    //lv_demo_benchmark();
    //lv_demo_music();

    while (1)
    {
        lv_timer_handler();
        HAL_Delay(5);
    }

#endif 
}

设置 Keil 使用 C99 标准编译:

 

 

编译、烧录、运行、大功告成。

 

标签:lv,lvgl,..,文件,lvgls,STM32,src,通法,LVGL
From: https://www.cnblogs.com/Huae/p/18621614

相关文章

  • 基于 STM32F767 的 4 位数码管显示与数字递减设计
    基于STM32F767的4位数码管显示与数字递减设计一、实验设计电路数码管连接-**段选引脚连接**:采用共阴极数码管,其段选引脚`a-g`分别连接到STM32F767开发板的GPIOA的0-7引脚。这种连接方式使得通过控制GPIOA相应引脚的电平状态,能够输出不同的段码,从而在......
  • 关于stm32f407 cherryusb初始化失败“This dwc2 version does not support dma mode,
    初学cherryusb,照着论坛帖子操作,将cherryusb软件包加入到407工程,编译完成后,下载,出现如下问题:[I/USB]dwc2has1channelsanddfifodepth(32-bitwords)is0[E/USB]Thisdwc2versiondoesnotsupportdmamode,sostopworking通过反复确认,各种定位尝试,最终发现是usb模......
  • 2024新版本如何配置CLion与cubeMX开发STM32
    2024新版本如何配置CLion与cubeMX开发STM321.为什么我要在网上有很多教程的情况下再做一个新版各种大佬们给出的配置教程原本很详细,但是在时间过了这么久之后已经不完全符合现在的环境了。昨天在教群里萌新安装CLION+CUBEMX时我才发现,在配置过程中新出现的一些变化甚至没有清......
  • STM32工程 如何设置堆栈大小(Heap和Stack)
    在STM32工程中,合理设置堆栈大小对于确保程序的稳定运行至关重要。堆栈大小的设置涉及到内存管理,特别是对于资源受限的嵌入式系统。1.理解堆栈的概念在嵌入式系统中,堆(Heap)和栈(Stack)是两种不同的内存区域,它们在程序运行中扮演着重要的角色:栈(Stack):由编译器自动管理,用于存......
  • 嵌入式开发:STM32 硬件 CRC 使用
    STM32微控制器内置了硬件CRC计算单元,可以用于计算多种CRC多项式,从而提高数据处理的效率和准确性。以下是STM32硬件CRC的详细使用步骤和代码示例。1.硬件CRC的优势硬件CRC不占用MCU的资源,计算速度快,适合于对实时性要求较高的场合。它通过直接对数据进行处理,减少了软件CRC......
  • STM32F767控制7位数码管0-9-a-f显示
    实验设计电路数码管连接:5161AS通常是共阴极数码管。共阴极数码管是指将所有数码管的阴极(一般是小段的负极)连接在一起接地。当给特定的阳极(小段的正极)施加高电平的时候,对应的小段就会发光。段选引脚连接:使用共阴极数码管,数码管的段选引脚(通常标记为a-g以及可能有......
  • LVGL学习 - Visual Studio外部“.c.h”文件添加
    一、首先把文件添加至工程,现有项选择所需添加的“.c.h”文件但还是会有如下报错,解决方法在第2步。二、“.c”文件需要添加“extern"C"”下图截至官方文档我试了只添加“extern"C"”,多个地方添加过还是不行,后面仿照LVGL官方代码,添加如下图,原报错搞定。点击查看代码#ifd......
  • STM32 水质水位检测项目 (水位测量模块)
    逻辑传感器捕捉到的是压力,压力转换成电压值是模拟电压,然后通过ADC转换成数字电压,然后输入给芯片,最后芯片进行运算,然后再lcd屏幕上显示。通过逻辑梳理,可以知道电压值和水深是成为线性关系,y=a*x+b;需要求得a和b,所以需要两个固定的值来验证,这里用x水深0cm和10cm来,推断a和b......
  • STM32F407VET6使用寄存器点亮LED
    一,目的:通过实验学会查看寄存器手册,学会通过寄存器驱动MCU1)下图是手册中对于GPIO输出的描述 2)在10类GPIO寄存器中选择需要配置的部分 3)注意时钟也要配置二,实验现象:PA6连接的LED闪烁三,实验步骤:1-查看《STM32F407中文手册(完全版)高清完整pdf版》和《Cortex-M4权威指南(英......
  • BH1750光照强度传感器详解(STM32)
    传感器介绍BH1750是一款数字型光照强度传感器,能够获取周围环境的光照强度。内置16bitAD转换器,其测量范围在0~65535lx(勒克斯,光照强度的单位),不区分环境光源。BH1750可用于调节手机屏幕和键盘的背光功率,或者用于智能灯光控制,比如,随着外界光照强度的变化调节灯光亮度。  以下......