心法:
以往看过很多的移植教程、在 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