LVGL是个很好用的东西,现在网上出的教程也越来越多,很多是针对V7及以下的版本的,但是V8针对V7的升级还是很大的,很多控件的使用方法也不一样了,所以需要有个合适的移植工程来使用。
这两天一直在想办法移植,也出了很多问题,但是最终还是成功了,特将过程记录下,供大家参考。
首先,针对的是正点原子的阿波罗开发板。核心是STM32F429IGT6,显示屏是分辨率480*272的RGB电容触摸屏。
先看下效果图
然后说下大概的移植过程及过程中问题的解决吧。
一开始我是直接下载的官方的lvgl源码,配合正点原子的触摸屏例程移植的,但是这个过程报错太多太多,解决一个会出来无数个,我估计这也是目前为止V8的移植教程不多的原因。
然后在官网找到了针对F429的移植例程:贴上地址 https://github.com/lvgl
就是上图的lv_port_stm32f429_disco。使用git拉取内容,注意一定要把lvgl文件夹下的子模块对应的拉取出来,使用命令:git clone --recurse-submodules https://github.com/lvgl/lv_port_stm32f429_disco.git
该方法前提是你科学上网没问题,如果网速不行,可以直接下载我提供的包。
文档中的内容如下图所示
我们需要使用到的就是红框中的4个。为什么不直接使用这个工程呢?因为这个工程是基于CUBEIDE编辑的,我还是更熟悉Keil,所以必须要移植过去。
接下来准备正点原子官方的触摸例程,这个主要图省事,而且屏幕和触摸初始化都做好了,避免了很多麻烦。在工程目录下新建一个文件夹“lvgl” 用来存上述4个文件。然后将上述4个文件拷贝到lvgl文件夹内。路径要放正确,因为内部的文件是要靠这个路径找头文件的。放在哪儿,见下图
好了,最让人纠结的基本上结束了,因为你已经拿到了可以移植的文件了。这个是困扰我很久的,因为很多源文件拿过来根本没法移植,也是因为我太菜了吧。
然后打开工程,在目录下新建3个目录,如下
简单说明一下:lvgl/src这个是存放.c源文件的;lvgl/ports是存放显示和触摸接口的;lvgl/app是用来存放官方demo例程和你将来的显示代码的。
lvgl/src存放的文件路径在下图的路径
打开这个文件夹,里面有多少c文件就都添加进去,包括子文件夹里面的内容也需要添加。
lvgl/ports存放的文件路径如下图
c文件添加好了记得添加库路径!然后编译一次。会报一些错误
上图是截自lv_port_disp_template.c。红框中的定义会报找不到,所以需要到lv_conf.h文件中定义这两个量,用宏定义就可以
#define MY_DISP_HOR_RES 480
#define MY_DISP_VER_RES 272
就是确定你的屏幕的分辨率。这个改完之后再编译还会报错,Library reports error: __use_no_semihosting was requested 如果大家遇到这个错误可以参考这个文章:https://blog.csdn.net/baidu_37973494/article/details/81168704
我的验证是方法三可用;使用方法一会解决这个报错,但会引入新的报错。
如果你还有关于GPU方面的报错,那就先去lv_conf.h中把下面的宏定义改成0,我们不使用GPU
/*-------------
* GPU
*-----------*/
/*Use STM32's DMA2D (aka Chrom Art) GPU*/
#define LV_USE_GPU_STM32_DMA2D 0
#if LV_USE_GPU_STM32_DMA2D
大的问题好像就是上面这些,可能还有的零散的小问题,有遗漏的可以自己查查看看。
然后就是针对LVGL的一些代码方面的修改了。
int main(void)
{
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhz
delay_init(180); //初始化延时函数
uart_init(115200); //初始化USART
TIM3_Init(999,89);
LED_Init(); //初始化LED
KEY_Init(); //初始化按键
SDRAM_Init(); //初始化SDRAM
// LCD_Init(); //初始化LCD
//tp_dev.init(); //触摸屏初始化
lv_init();
lv_port_disp_init();
lv_port_indev_init();
lv_demo_widgets();
while (1)
{
tp_dev.scan(0);
lv_task_handler();
}
}
main函数其实很简单,stm32的硬件初始化了就开始初始化LVGL。代码中注释掉的两行初始化LCD和触摸屏初始化,我把它们移动到了下面的lv_port_disp_init和lv_port_indev_init中初始化了,因为我发现先初始化屏幕会显示不出来。
lv_port_disp_init如下
void lv_port_disp_init(void)
{
/*-------------------------
* Initialize your display
* -----------------------*/
disp_init();
/*-----------------------------
* Create a buffer for drawing
*----------------------------*/
/* 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*/
/*-----------------------------------
* 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);
}
/*Initialize your display and the required peripherals.*/
static void disp_init(void)
{
/*You code here*/
LCD_Init(); //初始化LCD
if(lcdltdc.pwidth!=0)
LCD_Display_Dir(1);//如果是RGB屏的话,则强制设置为横屏显示 这一句还是很重要的,一开始没加,屏幕也没显示
}
lv_port_indev_init如下
void lv_port_indev_init(void)
{
static lv_indev_drv_t indev_drv;
/*------------------
* Touchpad
* -----------------*/
/*Initialize your touchpad if you have*/
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*/
tp_dev.init(); //触摸屏初始化
}
/*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(tp_dev.sta&TP_PRES_DOWN)//触摸按下了
{
last_x = tp_dev.x[0];
last_y = tp_dev.y[0];
data->point.x = last_x;
data->point.y = last_y;
data->state = LV_INDEV_STATE_PR;
}else{
data->point.x = last_x;
data->point.y = last_y;
data->state = LV_INDEV_STATE_REL;
}
}
然后就是添加官方demo进来了
注意这4个文件都要加进来,不然会报错,找不到文件。
这次编译应该就不会有问题了。下载验证就可以了。
以上就是我在移植LVGL8的过程中的总结,相关的工程请大家移步到QQ群:795010850。欢迎大家指正。