MCU移植LVGL

简介: MCU移植LVGL

       今天给大家带来的是LVGL移植的详细过程,有需要的小伙伴可以拿去尝试一下啦,感谢本文的笔者“想象之中”提供技术文章。

       

       大家使用过SGUI的,也可以做了对比,两者小编认为都是不错的东西,其他的废话不多说,一起来看下详细的移植过程吧,另外,还没关注过的小伙伴抓紧关注起来哦!会有开发板、核心板等不定时参与活动赠送哦,目前已经赠送了2波啦!


/* 正文  */

       官网下载LVGL源码,(可以通过github下载,也可以打包下载)甚至可以选择以前的版本进行下载

解压,得到下面的文件,我们暂时只用得上下面框住的文件

移植当中需要注意的是examples\porting文件夹下的文件,

还有就是src下面的源文件

准备好可以驱动显示器的MCU程序,这里以战舰板驱动3.5寸屏幕为例!!!

先在工程文件目录下创建文件夹“GUI”,在GUI文件夹下创建文件夹LVGL(文件夹的位置和名字不重要,在工程当中能够找到相关源程序即可)并将下载的源码文件夹下的所有文件复制到GUI文件夹下的LVGL文件夹下(我使用的是lvgl-8.0.3-dev)

把LVGL文件夹下的文件“lv_conf_template.h”剪切到上一层目录“GUI”下(注意是剪切),并将文件名改为lv_conf.h(你也可以不改,主要为了命名规范一点)

将GUI\LVGL\examples\porting文件夹下的文件命名进行更改,(你也可以不改,主要为了命名规范一点)如下图所示,暂时只用到显示部分,其他文件名暂时不更改。

打开工程,在工程当中创建三个文件夹,如下图所示:

然后将GUI文件夹目录下的文件“lv_conf.h”添加到“LVGL/USER”当中,将GUI\LVGL\examples\porting文件夹目录下的文件“lv_port_disp.c”添加到“LVGL/PORT”当中,将GUI\LVGL\src文件夹目录下的所有C文件添加到“LVGL/SRC”当中。

(GUI\LVGL\src\gpu文件夹下的文件暂时用不到,可以不用添加到工程当中,不过我还是添加到工程当中了)

添加头文件路径到工程当中,同时勾选上C99编译!!!

编译!!!查看错误

工程移植的差不多了,解析来就是移植LVGL的API了

首先打开文件“lv_port_disp.c”并使能,更改头文件名称(如果之前更改了GUI\LVGL\examples\porting文件夹目录下的文件名称的话),并添加显示屏的头文件,例如我的是:#include "nt35310_lcd.h"

然后打开对应的头文件“lv_port_disp.h”并使能,并添加函数”void lv_port_disp_init(void)“的声明

接下来我们需要更改函数“lv_port_disp.c”的内部实现方法!!!

首先我们需要对屏幕进行初始化,使用函数为:”disp_init()“,在函数内部实现对屏幕的初始化!!

我在初始化完将屏幕刷新成浅蓝色了。

static void disp_init(void)
{
    /*You code here*/
    NT35310_LCD_Init();//LCD初始化
    NT35310_LCD_Clear(LIGHTBLUE);//填充浅蓝色  
}

然后是更改函数”void lv_port_disp_init(void)“,其在内部提供有三种设置缓冲区的方法,这里我们使用第一种,将其他方式先屏蔽掉,这里用到了头文件"nt35310_lcd.h"当中定义了表示屏幕分辨率的宏,我们需要使用到它,用来告诉LVGL屏幕的大小,更改内容如下:

void lv_port_disp_init(void)
{
    //#defineNT35310_LCD_WIDTH320//LCD水平分辨率
    //#defineNT35310_LCD_HEIGHT480//LCD垂直分辨率
    /*-------------------------
     * Initialize your display
     * -----------------------*/
    disp_init();
    /*-----------------------------
     * Create a buffer for drawing
     *----------------------------*/
    /**
     * 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.
     */
/*-----------------------------------
     * 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 = NT35310_LCD_WIDTH;
    disp_drv.ver_res = NT35310_LCD_HEIGHT;
    /*Used to copy the buffer's content to the display*/
    disp_drv.flush_cb = disp_flush;
    /* Example for 1) */
    static lv_disp_draw_buf_t draw_buf_dsc_1;
    static lv_color_t buf_1[NT35310_LCD_WIDTH * 10];                          /*A buffer for 10 rows*/
    lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, NT35310_LCD_WIDTH * 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_1[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_1, 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_1[MY_DISP_HOR_RES * MY_DISP_VER_RES];            /*An other 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*/
//    /*-----------------------------------
//     * 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 = 480;
//    disp_drv.ver_res = 320;
//    /*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;
    /*Required for Example 3)*/
    //disp_drv.full_refresh = 1
    /* Fill a memory array with a color if you have GPU.
     * Note that, in lv_conf.h you can enable GPUs that has built-in support in LVGL.
     * But if you have a different GPU you can use with this callback.*/
    //disp_drv.gpu_fill_cb = gpu_fill;
    /*Finally register the driver*/
    lv_disp_drv_register(&disp_drv);
}

因为STM32F103没有GPU(DMA2D)功能,所以只能使用函数”disp_flush“进行刷新,在函数内部替换成我们的画点函数,更改代码如下

static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
    /*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)*/
NT35310_LCD_DrawPoint(x, y, (color_p)++->full);
        }
    }
    /*IMPORTANT!!!
     *Inform the graphics library that you are ready with the flushing*/
    lv_disp_flush_ready(disp_drv);
}

到这里我们的显示API就移植的差不多了,解析来就是要开启LVGL!

开启LVGL需要调用以下函数,但是咱们暂时只用到了显示器,所以只需要调用前两个函数即可,后三个函数与下examples\porting文件夹下的文件一一对应。

lv_init();                  // lvgl初始化函数,在使用LVGL前必须调用
lv_port_disp_init();        // 显示器初始化
lv_port_indev_init();       // 输入设备初始化
lv_port_fs_init();          // 文件系统设备初始化

然后是使得LVGL进行心跳,需要调用以下函数

lv_tick_inc(LVGL_TICK);// tick 提供时钟,LVGL_TICK 一般为 5ms 即可
lv_timer_handler(); // 运行所有lvgl的timer

咱们暂时不使用RTOS,所以通过下面的方式进行初始化:

//添加头文件
#include "lv_port_disp.h"
#include <lvgl.h>
#define LVGL_TICK 5
int main(void)
{
    lv_init();
    lv_port_disp_init();        // 显示器初始化
    while(1)
    {
        // 先调用 lv_tick_inc 再调用 lv_timer_handler
        lv_tick_inc(LVGL_TICK);// tick 提供时钟,LVGL_TICK 一般为 5ms 即可
        lv_timer_handler(); // 运行所有lvgl的timer
        DelayMs(LVGL_TICK);
    }
}

最后一步,配置LVGL!!

打开配置文件"lv_conf.h"并使能,选择自己屏幕对应的颜色深度!!!

更改LVGL运行所使用的RAM大小:

开启监控设置

最后在主程序当中写入例子程序!!!

编译下载运行,结果如下:


更改堆栈空间的方法:



至此移植就全部结束啦,感谢“想象之中”分享的技术文章。如果你也有好的文章、笔记分享,也和小编联系吧!


 如果觉得本篇文章多少有点帮助的话大家不要忘了,点赞、关注、评论、转发哦,你们的支持是小编创作的最大动力。

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
相关文章
|
缓存 Java C语言
嵌入式 LVGL移植到STM32F4
嵌入式 LVGL移植到STM32F4
STM32CubeIDE移植ARM DSP库
STM32CubeIDE移植ARM DSP库
|
Linux 开发工具 git
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十二)LED模板驱动程序的改造:设备树
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十二)LED模板驱动程序的改造:设备树
338 1
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十二)LED模板驱动程序的改造:设备树
|
Ubuntu 网络协议 Linux
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(四)传输文件
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(四)传输文件
919 1
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(四)传输文件
|
Ubuntu Linux 开发工具
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十一)第一次写驱动程序
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十一)第一次写驱动程序
274 1
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十一)第一次写驱动程序
|
存储 异构计算
|
Linux 开发工具 git
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十)LED模板驱动程序的改造:总线设备驱动模型
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十)LED模板驱动程序的改造:总线设备驱动模型
227 1
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十)LED模板驱动程序的改造:总线设备驱动模型
|
Ubuntu Linux 编译器
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十七)具体单板的LED驱动程序
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十七)具体单板的LED驱动程序
196 0
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十七)具体单板的LED驱动程序
|
Linux C语言 芯片
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十二)LED硬件原理
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十二)LED硬件原理
148 0
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十二)LED硬件原理
|
Linux 芯片
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十五)最简单的LED驱动程序
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十五)最简单的LED驱动程序
156 0
嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十五)最简单的LED驱动程序