提高LCD屏幕刷新效率

项目中,需要在屏幕上刷新波形。

原来的方式是通过两点之间画线,来描出曲线,但是刷新速度不理想,且时间不固定。

后来查阅LCD控制芯片手册,可以利用 “填充区域” 的方法提高刷新效率。

如下是2个LCD的基本通用的函数,设置范围和画点。

通过这两段代码可以分析:如果通过画线方式来刷新波形,由于点的所属区域不连贯,所以每画1个点,就需要设置1次行地址、列地址。

这里假设 LCD_SetCursor() 的耗时为n1,LCD_WR_DATA() 的耗时为n2 。

通过实测可以发现n1远大于n2。

void LCD_SetCursor(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
    LCD_WR_REG(0x2A);
    LCD_WR_DATA(x1 >> 8);	//0x2A为列地址 所以注意当前模式下X坐标是列坐标,Y坐标为行坐标!!!
    LCD_WR_DATA(x1);		//起始地址
    LCD_WR_DATA(x2 >> 8);
    LCD_WR_DATA(x2);		//结束地址

    LCD_WR_REG(0x2B);		//0x2B为行地址
    LCD_WR_DATA(y1 >> 8);	//起始地址
    LCD_WR_DATA(y1);
    LCD_WR_DATA(y2 >> 8);	//结束地址
    LCD_WR_DATA(y2);
	
	LCD_WR_REG(0x2C);
}

void LCD_DrawPoint(uint16_t x,uint16_t y)
{
	LCD_SetCursor(x, y, x, y);
    LCD_WR_DATA( POINT_COLOR );
}

而且通过对比发现,刷新一个正弦波数据时,即使波形点只占据大约1/10屏幕时,也要大于刷整屏的时间(波形点的数量过半时更夸张,耗时远大于刷新整屏)。

所以我们可以借鉴 LCD_Fill() 函数的思路,来刷新我们的波形数据。

void LCD_Fill(uint16_t sx,uint16_t sy,uint16_t ex,uint16_t ey,uint32_t color)
{
	uint16_t i,j;
	
    LCD_SetCursor(sx,sy,ex,ey);
	
    for(j = 0; j < (ey-sy+1); j++)
	for(i = 0; i < (ex-sx+1); i++)
    LCD_WR_DATA( color );
}

void LCD_FillColor_Buf(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *color)
{
	uint16_t i,j;
	
    LCD_SetCursor(x1,y1,x2,y2);
	
	for(j = 0; j < (y2-y1+1); j++)
	for(i = 0; i < (x2-x1+1); i++)
	LCD_WR_DATA( *color++ );
}

假设波形刷新区域大小为300*200(即宽度300个像素点,高度200个像素点),我们用一块内存区存储每个点的颜色,即需要300*200*2=117K字节大小的数组。

每次刷新之前,计算需要点亮哪些网格点,计算出需要刷新哪些像素点,等等,最后直接调用 LCD_FillColor_Buf() 函数刷新。

计算的方法,可参考如下代码

    //设置默认颜色 即背景色
    memset(WaveBufBit, List_c[OSC_M_WAVE].Back, OSC_WIDTH*OSC_HEIGHT*2);


    //X轴、Y轴上,每25个点就点亮1个点,其它点不变
    for(i = 1; i < 12; i++)
	{
		for(j = 1; j < 200 - 1; j++){
			if(i!=6) j++;
			WaveBufBit[j][25*i] = List_c[OSC_M_CELL].Point;
		}
	}
	for(i = 1; i < 8; i++)
	{
		for(j = 1; j < 300 - 1; j++){
			if(i!=4) j++;
			WaveBufBit[25*i][j] = List_c[OSC_M_CELL].Point;
		}
	}


    //从第2个点开始,每2个坐标点之间,可以计算出当前Y轴上需要点亮哪些点,然后依次计算出所有亮点
    //#define OSC_PIXEL_GetMin(X1,X0) 	((X1>=X0)?(OSC_HEIGHT-X1):(OSC_HEIGHT-X0))
    //#define OSC_PIXEL_GetNum(X1,X0) 	((X1>X0)?(X1-X0):((X1==X0)?1:X0-X1))
    for(X = 2; X < OSC_WIDTH; X++)
	{
		LCD_Y_Min = OSC_PIXEL_GetMin(WaveBuf[X],WaveBuf[X-1]);//起始点亮点
		LCD_Y_Num = OSC_PIXEL_GetNum(WaveBuf[X],WaveBuf[X-1]);//点亮数目
		
		for(y = LCD_Y_Min; y < LCD_Y_Min + LCD_Y_Num; y++){
			WaveBufBit[y][X] = List_c[OSC_M_WAVE].Point;
		}
	}

KD028FM屏幕(ST7789芯片)+STM32F429条件下,一次刷新时间固定在22ms。

这样,刷新时间就只取决于2个方面:1、像素点计算时间,2、LCD_Fill()刷新速度。

LCD刷新时间取决于硬件(芯片LCD接口的速率),软件提升空间不大。

像素点计算时间取决于代码执行效率,无非是空间换时间。

如果芯片无法支持117K字节大小的数组,也可以减半。不保存颜色(uint16_t类型)而保存颜色的枚举值,再到写入时根据枚举值填充不同的颜色。

猜你喜欢

转载自blog.csdn.net/weixin_38743772/article/details/129046384