本篇讲述CH32V208移植LVGL,将在前面讲过ST7735 SPILCD驱动基础上展开。
一.准备工作
下载LVGL源码:https://github.com/lvgl/lvgl/tree/release/v8.3
二.移植LVGL
1.配置1ms定时器,提供LVGL心跳。配置使用SYSTICK_Init_Config(SystemCoreClock/1000-1);
void SYSTICK_Init_Config(u64 ticks)
{
SysTick->SR = 0;
SysTick->CNT = 0;
SysTick->CMP = ticks;
SysTick->CTLR =0xF;
NVIC_SetPriority(SysTicK_IRQn, 1);
NVIC_EnableIRQ(SysTicK_IRQn);
}
void SysTick_Handler(void)
{
SysTick->SR = 0;
lv_tick_inc(1);
counter++;
if(counter>=1000)
{
counter=0;
printf("welcome to WCH\r\n");
// printf("Counter:%d\r\n",counter);
}
}
2.显示初始化。
#define MY_DISP_HOR_RES 160
#define MY_DISP_VER_RES 128
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*/
#if 0
/* 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*/
#endif
/*-----------------------------------
* 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;
/*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);
}
3.disp_flush实现
void LCD_DrawPoint(u16 x,u16 y,u16 Data)
{
LCD_SetWindows(x,y,x+1,y+1);
Lcd_WriteData_16Bit(Data);
}
/*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)
{
if(disp_flush_enabled) {
/*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)*/
LCD_DrawPoint(x,y,lv_color_to16(*color_p));
color_p++;
}
}
}
/*IMPORTANT!!!
*Inform the graphics library that you are ready with the flushing*/
lv_disp_flush_ready(disp_drv);
}
4.lv_config.h配置.这里依需配置修改
5.设计界面
void lv_ex_label_1(void)
{
lv_obj_t* btn = lv_btn_create(lv_scr_act());
lv_obj_set_pos(btn, 40, 44);
lv_obj_set_size(btn, 80, 40);
lv_obj_t* label = lv_label_create(btn);
lv_label_set_text(label, "Button");
lv_obj_center(label);
}
6.main函数实现
int main(void)
{
SystemCoreClockUpdate();
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\r\n", SystemCoreClock);
// SPI_FLASH_Init();
LCD_Init();
lv_init();
lv_port_disp_init();
SYSTICK_Init_Config(SystemCoreClock/1000-1);
lv_ex_label_1();
while (1)
{
Delay_Ms(5);
lv_task_handler();
}
}
此外,注意在MRS 添加源文件及路径以及配置文件Link.ld的调整修改等。
三.测验
编译烧录后,LCD屏显示如下:
至此实现CH32V208开发板LVGL移植。