LVGL进阶优化—LTDC双缓冲+DMA2D中断
重回桃花源
2022年08月06日 12:37

    一、前言

    优化策略参考自以下视频

    这个双缓冲不是LVGL显存方式里的那个双缓冲,是人为的在SDRAM里开辟另一块缓存空间,然后进行乒乓操作。LTDC显示完第一块缓存空间后,进入中断,中断里将LTDC源地址指向第二块缓存空间。

    同时开启DMA2D,将LVGL刷屏数据刷入缓存空间。即LTDC在刷新第一块缓存空间时,DMA2D往第二块缓存空间快速刷入数据。LTDC在刷新第二块缓存空间时,DMA2D往第一块缓存空间快速刷入数据,如此往复。如下图所示:

    这样做的好处在于可以有效地避免图像撕裂情况的出现。如下:

    图像撕裂的原因就在于DMA2D在向缓存空间写入数据的同时,LTDC也从这块缓存空间里取数据,向屏幕刷新数据。所以开辟第二块显存空间就能解决这种问题。

    二、程序

    基本的编程思路如下:

    1、开辟第二块缓存空间以及新建切换标志位

    计算好第一块缓存空间的大小,进行偏移即可。

    新建全局变量,切换标志位

代码块
clike
自动换行
复制代码
volatile uint8_t ltdc_finish_state=0;
复制成功

    2、使能LTDC中断,配置为最后一行触发中断,配置中断优先级,配置影子寄存器为消隐期间重载

代码块
clike
自动换行
复制代码
	LTDC->LIPCR =lcdltdc.vsw+lcdltdc.vbp+lcdltdc.pheight-1;//配置行中断的行数为最后一行
	LTDC->IER |=LTDC_IER_LIE;//使能LTDC行中断
	MY_NVIC_Init(0,2,LTDC_IRQn,2);
	LTDC->SRCR |= (1<<1);
复制成功

    3、编写中断处理函数

代码块
clike
自动换行
复制代码
void LTDC_IRQHandler(){
if(g_gpu_state==0){
	if(LTDC->ISR & (1<<0)){
	if (ltdc_finish_state==0){
		ltdc_finish_state=1;
		ltdc_framebuf[0]=(u32*)&ltdc_lcd_framebuf1;
	}
	else{
		ltdc_finish_state=0;
		ltdc_framebuf[0]=(u32*)&ltdc_lcd_framebuf;
	}
	//层配置
	LTDC_Layer_Parameter_Config(0,(u32)ltdc_framebuf[0],LCD_PIXFORMAT,255,0,6,7,0X000000);//层参数配置,主要作用是指定层地址
	LTDC->ICR |= (1<<0);
		}
	}
}
复制成功

    4、DMA2D配置

    在disp_flush函数下,配置DMA2D,采用的是中断的形式。根据切换编制位,改变目标地址

代码块
clike
自动换行
复制代码
//DMA2D写法,中断式
		g_gpu_state = 1;
		disp_drv_p = disp_drv;
		uint32_t OffLineSrc = 480 - (area->x2 - area->x1 +1);//行偏移的值=行宽度-线的宽度
		uint32_t addr = LCD_FRAME_BUF_ADDR;
		if(ltdc_finish_state==0){
		uint32_t addr = LCD_FRAME_BUF_ADDR;//LTDC的显存地址
		}
		else{
		uint32_t addr = LCD_FRAME_BUF_ADDR+0x001f4000;//LTDC的显存地址	
		}
		RCC->AHB1ENR |= RCC_AHB1ENR_DMA2DEN;
		DMA2D->CR&=~(1<<0);				//先停止DMA2D
		DMA2D->CR=0<<16;				//存储器到存储器模式
		DMA2D->FGPFCCR = LCD_PIXFORMAT_RGB565;	//设置颜色格式
		DMA2D->OPFCCR  = LCD_PIXFORMAT_RGB565;
		DMA2D->FGOR=0;					//前景层行偏移为0
		DMA2D->OOR=OffLineSrc;				//设置行偏移 
		DMA2D->FGMAR=(u32)color_p;		//源地址
		DMA2D->OMAR=addr;				//输出存储器地址
		DMA2D->NLR=(area->y2-area->y1+1)|((area->x2-area->x1+1)<<16);	//设定行数寄存器 
		DMA2D->CR |=DMA2D_CR_TCIE; //传输完成中断使能
		DMA2D->CR|=1<<0;				//启动DMA2D		
复制成功

    其中断处理函数:

代码块
clike
自动换行
复制代码
void DMA2D_IRQHandler(void)
{	
		if((DMA2D->ISR & DMA2D_ISR_TCIF) !=0U){
						DMA2D->CR &= ~DMA2D_CR_TCIE;
						DMA2D->IFCR|=1<<1;//清除传输完成标志
			if(g_gpu_state==1){
		g_gpu_state=0;
		lv_disp_flush_ready(disp_drv_p);
			}
		}
}
复制成功