lvgl移植到 stm32 (stm32H743IIT6)

lvgl移植到stm32(stm32H743IIT6

  • 1.简介
  • 2.移植准备
    • 硬件准备
    • lvgl源码
  • 3.移植过程
  • 4.连接底层
  • 5.屏幕配置
  • 6.给lvgl一个心跳
  • 7. 移植demos

1.简介

LVGL(轻巧而多功能的图形库)是一个免费的开放源代码图形库,它提供创建具有易于使用的图形元素,精美的视觉效果和低内存占用的嵌入式GUI所需的一切。

2.移植准备

硬件准备

我使用的是正点原子的stm32H743IIt6核心板+7寸 ALENTEK 7’’ RGB TFTLCDC触摸屏。(其他屏幕也可以,但是必须包含lcd与touch驱动函数)

lvgl源码

我使用的是lvgl 7.10.1

源码
demos

3.移植过程

1.准备一个lcd触摸屏的例程
工程文件
2.在工程目录下新建一个GUI文件夹,GUI文件夹下包含两个子文件夹

3.移植lvgl
打开下载的lvgl-8.0.1
下载的
把刚才下载的lvgl-8.0.1里所有内容复制在lvgl文件夹下,lvgl_app文件夹暂时留空。
4.porting文件更名操作
我们把刚才复制后的GUI\lvgl\examples\porting下的文件进行一个改名
(1)原始
在这里插入图片描述
(2)更改名字之后
在这里插入图片描述
5.把GUI\lvgl\下的lv_conf_template.h文件复制到GUI文件夹下并更名为lv_conf.h:在这里插入图片描述
5.keil
(1)新建Group
在这里插入图片描述
(1)lvgl_app暂时空着
(2)将显示函数与触摸函数导入lvgl_porting中

在这里插入图片描述

(3)将lvgl源码中所有的.c文件全部导入lvgl_src
在这里插入图片描述
并且导入这些.c的路径
在这里插入图片描述
6.修改堆栈大小
在这里插入图片描述

7.设计c99模式
在这里插入图片描述
8.使能l条件编译
要使能lv_conf.h,lv_port_indev.c。lv_port_indev.h,lv_port_disp.c,lv_port_disp.h的条件编译,如下
在这里插入图片描述
下面部分注释掉,只留一个即可,否则会报错
在这里插入图片描述

即可编译通过
在这里插入图片描述

4.连接底层

显示移植
与touch.h相关

这个连接的画点函数,比较慢
// An highlighted block
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)*/GUI_DrawPoint(x,y,color_p->full);color_p++;}}/* IMPORTANT!!!* Inform the graphics library that you are ready with the flushing*/lv_disp_flush_ready(disp_drv);
}

下面展示一些 内联代码片

直接调用颜色块会很快
// An highlighted block
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)*/
//				    LCD_Fast_DrawPoint(x,y,color_p->full);
//            color_p++;
//        }
//    }//    /*IMPORTANT!!!
//     *Inform the graphics library that you are ready with the flushing*/
//    LCD_Color_Fill(area->x1,area->y1,area->x2,area->y2,(u16*)color_p);//最后必须得调用,通知lvgl库你已经flushing拷贝完成了lv_disp_flush_ready(disp_drv);
}

两者选一个就可以
触摸移植
下面展示一些 内联代码片

// An highlighted block
/*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;tp_dev.scan(0);if (tp_dev.sta & TP_PRES_DOWN) //{printf("x坐标:%d,Y坐标:%d\r\n", tp_dev.x[0], tp_dev.y[0]);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;}
}

有外部sdram时
可以这样定义
下面展示一些 内联代码片

// An highlighted block
*********************/ 
#define LTDC_LCD_FRAMEBUF_SIZE		(1280*800*2)		//ltdc.c中ltdc_lcd_framebuf缓冲区的大小
#define COLOR_BUF_SIZE		(1024*10)	//全屏的大小static lv_color_t color_buf[COLOR_BUF_SIZE]	__attribute__((at(LCD_FRAME_BUF_ADDR+LTDC_LCD_FRAMEBUF_SIZE+COLOR_BUF_SIZE*2))); //分配到外部SDRAM,需要跳过ltdc.c中分配的帧缓冲区
static lv_color_t color_buf2[COLOR_BUF_SIZE]	__attribute__((at(LCD_FRAME_BUF_ADDR+LTDC_LCD_FRAMEBUF_SIZE+COLOR_BUF_SIZE*4)));//lvgl的第二个缓冲区,紧跟在第一个缓冲区的后面

5.屏幕配置

挺重要的,有时候搞完一直出不来,可能就是屏幕横屏竖屏没弄好
下面展示一些 内联代码片

这里面屏幕的配置和你的lcd里横竖屏应该一致
// An highlighted blockvoid 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) *//*A buffer for 10 rows*/lv_disp_draw_buf_init(&draw_buf_dsc_1, color_buf, color_buf2, 1024 * 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 = 1024;disp_drv.ver_res = 600;/*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);
}
LCD_Display_Dir(1);	lcd里这个函数配置横竖屏

在 lv_conf.h里进行一些配置
色彩深度: #define LV_COLOR_DEPTH 16
DPI: #define LV_DPI 100
提供给lvgl的空间: #define LV_MEM_SIZE (32U * 1024U)

6.给lvgl一个心跳

下面展示一些 内联代码片

	TIM7_Init(10-1,20000-1);  1ms的心跳
// An highlighted blockvoid TIM7_Init(u16 arr,u16 psc)
{  TIM7_Handler.Instance=TIM7;                          //通用定时器3TIM7_Handler.Init.Prescaler=psc;                     //分频TIM7_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;    //向上计数器TIM7_Handler.Init.Period=arr;                        //自动装载值TIM7_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//时钟分频因子HAL_TIM_Base_Init(&TIM7_Handler);HAL_TIM_Base_Start_IT(&TIM7_Handler); //使能定时器3和定时器3更新中断:TIM_IT_UPDATE    
}//定时器底册驱动,开启时钟,设置中断优先级
//此函数会被HAL_TIM_Base_Init()函数调用
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{if(htim->Instance==TIM7){__HAL_RCC_TIM7_CLK_ENABLE();            //使能TIM3时钟HAL_NVIC_SetPriority(TIM7_IRQn,1,3);    //设置中断优先级,抢占优先级1,子优先级3HAL_NVIC_EnableIRQ(TIM7_IRQn);          //开启ITM3中断   }  
}//定时器3中断服务函数调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim==(&TIM7_Handler)){lv_tick_inc(1);}
}

在主函数while循环里写入 lv_task_handler();

7. 移植demos

1.复制lv_examples-7.10.1整个文件夹至GUI\lvgl_app文件夹下并更名为lv_examples:
2.把GUI\lvgl_app\lv_examples下的lv_demo_conf_template.h复制到GUI文件夹下并更名为lv_demo_conf.h
在这里插入图片描述
使用哪个就在哪个地方打开预编译
在lv_demo_conf.h中
下面展示一些 内联代码片

// An highlighted block
/*Show some widget*/
#define LV_USE_DEMO_WIDGETS        0
#if LV_USE_DEMO_WIDGETS
#define LV_DEMO_WIDGETS_SLIDESHOW  0
#endif/*Printer demo, optimized for 800x480*/
#define LV_USE_DEMO_PRINTER     0/*Demonstrate the usage of encoder and keyboard*/
#define LV_USE_DEMO_KEYPAD_AND_ENCODER     1/*Benchmark your system*/
#define LV_USE_DEMO_BENCHMARK   0/*Stress test for LVGL*/
#define LV_USE_DEMO_STRESS      0

我用的是//lv_demo_keypad_encoder();的demo
将lv_demo_keypad_encoder文件夹的c文件添加进lvgl_app

在这里插入图片描述
我的主函数
下面展示一些 内联代码片

// An highlighted block
int main(void)
{HAL_Init();				        		//初始化HAL库Stm32_Clock_Init(160,5,2,4);  		    //设置时钟,400Mhz delay_init(400);						//延时初始化uart_init(115200);						//串口初始化usmart_dev.init(200); 		    		//初始化USMART	TIM3_Init(10-1,20000-1);LED_Init();								//初始化LEDKEY_Init();								//初始化按键SDRAM_Init();                   		//初始化SDRAMLCD_Init();								//初始化LCD//	TP_Init();lv_init();lv_port_disp_init();lv_port_indev_init();tp_dev.init();				    		//触摸屏初始化 
//  	POINT_COLOR=RED;
//	LCD_ShowString(30,50,200,16,16,"Apollo STM32H7"); 
//	LCD_ShowString(30,70,200,16,16,"TOUCH TEST");	
//	LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
//	LCD_ShowString(30,110,200,16,16,"2017/8/14");	 		
//   	if(tp_dev.touchtype!=0XFF)LCD_ShowString(30,130,200,16,16,"Press KEY0 to Adjust");//电阻屏才显示
//	delay_ms(1500);
//	Load_Drow_Dialog();	 	
//	if(tp_dev.touchtype&0X80)ctp_test();//电容屏测试
//	else rtp_test(); 					//电阻屏测试  		 
//	
//  lv_demo_widgets();
// lv_demo_stress();
//  lv_demo_benchmark();
lv_demo_keypad_encoder();
//   lv_demo_test();while(1){lv_task_handler();}}

移植成功
在这里插入图片描述

第一次写博客好开心哦__,嘻嘻


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部