一、前言
优化策略参考自以下视频

这个双缓冲不是LVGL显存方式里的那个双缓冲,是人为的在SDRAM里开辟另一块缓存空间,然后进行乒乓操作。LTDC显示完第一块缓存空间后,进入中断,中断里将LTDC源地址指向第二块缓存空间。
同时开启DMA2D,将LVGL刷屏数据刷入缓存空间。即LTDC在刷新第一块缓存空间时,DMA2D往第二块缓存空间快速刷入数据。LTDC在刷新第二块缓存空间时,DMA2D往第一块缓存空间快速刷入数据,如此往复。如下图所示:

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

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

1、开辟第二块缓存空间以及新建切换标志位
计算好第一块缓存空间的大小,进行偏移即可。

新建全局变量,切换标志位
volatile uint8_t ltdc_finish_state=0; 2、使能LTDC中断,配置为最后一行触发中断,配置中断优先级,配置影子寄存器为消隐期间重载
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、编写中断处理函数
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,采用的是中断的形式。根据切换编制位,改变目标地址
//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 其中断处理函数:
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);
}
}
}