[经验] 【极海APM32F407 Tiny Board】 2.LVGL8.2移植体验

zght   2024-3-3 18:11 楼主

一、移植准备

下载LVGL源码:https://github.com/lvgl/lvgl/,解压后,文档如下所示:
180541ov7ikziy5mlu497v.png
将lv_conf_template.h改成lv_conf.h,命令可以随意更改,一个配置文件,同时打开文件,将#if0调整为# if 1,不然编译的回收会出很多错。
180541v9a2mjaa8fx2rafr.png
接下来删除一下文件,也可以不删除,删除了方便管理
180541hee0w1p8g0k8rb01.png

二、移植过程

在之前的基础上添加lvgl的源码,文件比较多,不一一说明,同时这里添加的时候可以进行分类添加,这样就没有这么乱,查找也方便
180541wb0tvmwz9x2mhowh.png
添加头文件路径:
180541eqqvq3rlqq8b7k0v.png
添加定时器初始化,定时1ms,,添加lvgl头文件
180541rro33oeu3ie46irp.png
添加LVGL与LCD的接口处理:
/**
 * [url=home.php?mod=space&uid=1307177]@File[/url] lv_port_disp_templ.c
 *
 */

 /*Copy this file as "lv_port_disp.c" and set this value to "1" to enable content*/
#if 1

/*********************
 *      INCLUDES
 *********************/
#include "lv_port_disp_template.h"
#include "../../lvgl.h"
#include "./BSP/LCD/lcd.h"
#include "gui.h"
#include "lv_demo_keypad_encoder.h"

#define MY_DISP_HOR_RES (320) 
#define MY_DISP_VER_RES (240) 

/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/
static void disp_init(void);

static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);
//static void gpu_fill(lv_disp_drv_t * disp_drv, lv_color_t * dest_buf, lv_coord_t dest_width,
//        const lv_area_t * fill_area, lv_color_t color);

/**********************
 *  STATIC VARIABLES
 **********************/

/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
 **********************/

void lv_port_disp_init(void)
{
    /*-------------------------
     * 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.
     */

    /* 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*/

    /*-----------------------------------
     * 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 = lcddev.width;
    disp_drv.ver_res = lcddev.height;

    /*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);
		
	
}

/**********************
 *   STATIC FUNCTIONS
 **********************/

/*Initialize your display and the required peripherals.*/
static void disp_init(void)
{
    /*You code here*/
		LCD_Init();
		LCD_direction(1);
}

/*Flush the content of the internal buffer the specific area on the display
 *You can use DMA or any hardware acceleration to do this operation in the background but
 *'lv_disp_flush_ready()' has to be called when finished.*/
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*/

			lcd_color_fill(area->x1,area->y1,area->x2,area->y2,color_p);
//		LCD_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);
}

/*OPTIONAL: GPU INTERFACE*/

/*If your MCU has hardware accelerator (GPU) then you can use it to fill a memory with a color*/
//static void gpu_fill(lv_disp_drv_t * disp_drv, lv_color_t * dest_buf, lv_coord_t dest_width,
//                    const lv_area_t * fill_area, lv_color_t color)
//{
//    /*It's an example code which should be done by your GPU*/
//    int32_t x, y;
//    dest_buf += dest_width * fill_area->y1; /*Go to the first line*/
//
//    for(y = fill_area->y1; y <= fill_area->y2; y++) {
//        for(x = fill_area->x1; x <= fill_area->x2; x++) {
//            dest_buf[x] = color;
//        }
//        dest_buf+=dest_width;    /*Go to the next line*/
//    }
//}


#else /*Enable this file at the top*/

/*This dummy typedef exists purely to silence -Wpedantic.*/
typedef int keep_pedantic_happy;
#endif

修改LCD的颜色填充函数:


void lcd_color_fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, lv_color_t *color)
{
	uint32_t y=0; 
	u16 height, width;
	width = ex - sx + 1;            
  height = ey - sy + 1;         
	
	LCD_SetWindows(sx,sy,ex,ey);
	
	for(y = 0; y <width*height; y++) 
	{
		Lcd_WriteData_16Bit(color->full);
		color++;
  }
}

 

添加测试代码,如下所示:
int main(void)
{
    NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_3);   
    sys_apm32_clock_init(336, 8, 2, 7);                 
    delay_init(168);                                   
    usart_init(115200);                                
		btmr_tmrx_int_init(10-1, 8400-1);
    led_init();
	  lv_init();
		lv_port_disp_init();
		lv_obj_t *label = lv_label_create(lv_scr_act());
		lv_label_set_text(label,"APM32F407 LVGL8.2");
		lv_obj_center(label);
                                          
#if 0	
	  nes_main();
#endif
	
    while (1)
    {
				lv_timer_handler();
        LED0_TOGGLE();
				delay_ms(500);
			
    }
}

 

三、结果

显示效果如下,有兴趣的可以继续跑一下官方例程,或者自己写一个

180541m5j5bzv6any7oy5n.jpg

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复