LCD单色图像显示的基础研究

前言

最近用到了240*160的LCD屏,对于图像显示有一个基础研究,用的是单片机的RAM作为GRAM显存的方案。在任意位置显示任意大小的图像、字符。

有纰漏请指出,转载请说明。

学习交流请发邮件 1280253714@qq.com

驱动芯片及其扫描方式

用ST75256作为LCD的驱动芯片时,每8个像素点占用一个字节。

这里需要注意设置的扫描方向,在取模时需要注意取模方向跟扫描方向对应上。

将图像数据直接传输到LCD上

/*
	--------------x
	|
	|
	y
*/
/*
	*说明		利用图像取模软件,将取模后的图像数据pGram,直接传输到LCD上
	*设计思路	
		pGram数组前6字节为0X21,0X01,0X20,0X00,0X38,0X00,为图像头数据
			第一个字节为扫描模式,第二个字节为输出灰度(色彩)
			第三四个字节为图像宽度,第五六个字节为图像高度
		先调用LcdAddress,进行开窗,即设置将要显示的x、y坐标轴及窗口大小
		将pGram数组内的数据,依照扫描方式,调用LcdTransferData,直接传输到LCD					
*/
void LcdDisplayNxN(int x, int y, const char pGram[]) 
{
	int i,j; 
	int charCnt; 
	u16 nByte = 0;
	u16 w = pGram[3] << 8 | pGram[2];
	u16 h = pGram[5] << 8 | pGram[4];
	y=y>>3;
	h=h>>3;
	LcdAddress(x,y,w,h); 
	 for(i=0;i<h;i++) 
	 { 
		 for(j=0;j<w;j++) 
		 { 
			 LcdTransferData(pGram[charCnt+6]); 
			 charCnt++; 
		 } 
	 }
}

这种方式存在一个缺陷,虽然是160行的像素,但无法设置其具体到160行的某一行,也就是像初学1602那样,设置第一行/第二行显示的内容。

用单片机的RAM作为图像的显存GRAM

这里用了一种方式,也就是用单片机的一部分RAM,作为图像的显存GRAM,然后可以做固定频率的刷新,也可以GRAM内容更新时才进行屏幕刷新。这时是将一整屏图像写进LCD。

240*160/8=4800byte字节,单片机用u8 LcdGram[240][20]作为LCD的GRAM。

u8 LcdGram[240][20] = {0};

/*
	*说明		清除Gram数据
	*设计思路	调用memset库函数将整个LcdGram数据清楚			
*/
void LcdClearGram(void)
{
	memset(&LcdGram,0,sizeof(LcdGram));
}
	
/*
	*说明		更新Gram显存到LCD	
	*设计思路	设置对应的行地址和列地址,将数据传输到LCD			
*/
void LcdRefreshGram(void)
{
	u8 i,j;		
	LcdAddress(0,0,240,20);    
	for(i=0;i<240;i++)  
	{  
		for(j=0;j<20;j++)LcdTransferData(LcdGram[i][j]); 
	}   
}


/*
	*说明		将对应的x、y坐标的点数据更新到Gram	
	*设计思路	
		x、y不能超过屏幕范围
		由于是单色点,8个点用一个byte数据,240*160屏幕用到了240行*20列个byte数据
		在寻址y对应到Gram的列位置时,需要将y/8,具体到某个byte的某个bit,需要y%8
*/
void LcdDrawPoint(u8 x,u8 y,u8 t)
{
	u8 pos,bx,temp=0;
	if(x>240||y>160)return;//超出范围了.
	pos=y/8;
	bx=y%8;
	temp=1<<bx;
	if(t)LcdGram[x][pos]|=temp;
	else LcdGram[x][pos]&=~temp;	    
}



/*
	--------------x
	|
	|
	y
*/
/*
	*说明		利用图像取模软件,将取模后的图像存放在pGram数组里,调用此函数将数组内容放在显存里
	*设计思路	
		pGram数组前6字节为0X21,0X01,0X20,0X00,0X38,0X00,为图像头数据
			第一个字节为扫描模式,第二个字节为输出灰度(色彩)
			第三四个字节为图像宽度,第五六个字节为图像高度
		将pGram数组内的数据,依照扫描方式,调用画点函数,存放在LcdGram显存内
		若图像宽为32,高为56,则pGram除头数据外,还有32*56/8=224个字节
		如果高度不是8的倍数,则直接退出
		这里用垂直扫描模式,当一列数据写Gram完成后,相应地x坐标需要加1,同时y回到起始位置
				
					
*/
void LcdDisplayNxN(int x, int y, const u8 pGram[]) 
{
	int charCnt,charNum; 
	u8 dotCnt,charTmp,hightCnt; 
	u8 y0 = y;
	u16 w = pGram[3] << 8 | pGram[2];
	u16 h = pGram[5] << 8 | pGram[4];
	if ((h%8)!=0)
		return;
	h=h>>3;
	charNum = w*h;
	
	for(charCnt=0;charCnt<charNum;charCnt++)
    {   
		charTmp = pGram[charCnt+6];

        for(dotCnt=0;dotCnt<8;dotCnt++)
		{
			if(charTmp&0x01)LcdDrawPoint(x,y,1);
			else LcdDrawPoint(x,y,0);
			charTmp>>=1;
			y++;
		}  	 
		hightCnt++;
		if (hightCnt>=h) {
			hightCnt = 0;
			y = y0;
			x++;
		}
    }
}


/*
	*说明		利用字模软件,将取模后的字符数据存放在asciiNxN数组里,调用此函数将数组内容放在显存里
	*设计思路	
		取模时,从空格符开始,依次对下列字符进行取模
		 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
		code为需要显示的ascii字符,字符需要减去第32个字符即空格字符的偏移
		取到字符的字模数据后,依照扫描方式,调用画点函数,存放在LcdGram显存内
		若字符宽为16,高为24,则一个字符共有16*24/8=48个字节
		这里用垂直扫描模式,当一列数据写Gram完成后,相应地x坐标需要加1,同时y回到起始位置								
*/
void LcdDispAscii(u8 x, u8 y, u8 code, u8 size)
{
	u8 charTmp,charCnt,dotCnt,charNum;
	u8 y0=y;
	
	if(size==__SIZE_08_16) {
		code = code- ' ';//得到偏移后的值
		charNum = 16;
	} else if(size==__SIZE_16_24) {
		code = code- ' ';//得到偏移后的值
		charNum = 48;
	} else {
		return;
	}
	
    for(charCnt=0;charCnt<charNum;charCnt++)
    {   
		if(size==__SIZE_08_16) {
			charTmp=ascii8x16[code][charCnt];	//调用1608字体
		} else if(size==__SIZE_16_24) {
			charTmp=ascii16x24[code][charCnt];	//调用2412字体
		} else {
			return;
		}

        for(dotCnt=0;dotCnt<8;dotCnt++)
		{
			if(charTmp&0x01)LcdDrawPoint(x,y,1);
			else LcdDrawPoint(x,y,0);
			charTmp>>=1;
			y++;
			if((y-y0)==size)
			{
				y=y0;
				x++;
				break;
			}
		}  	 
    }
}

图像刷新率多少比较合适

可以算一下,如果是8080接口,8位并口,若传输一byte数据大概需要1US,那么传输速度大概是1Mbyte/S,一帧图像有4800byte数据,传输一帧图像需要 4800byte ÷ (1024 × 1024 byte/S)即4600ms,一秒大概传输 1,048,576 byte/S ÷ 4800 byte/帧即218.45帧。

一般来说,当帧率达到或超过每秒12帧时,人眼开始能够感知到连续的运动,从而看起来像是动画。但是,为了获得更加流畅和自然的动画效果,通常建议使用更高的帧率。

在标准的电影和视频制作中,常见的帧率有24fps(每秒24帧)、25fps(主要用于PAL制式的电视广播)和30fps(主要用于NTSC制式的电视广播和某些网络视频)。这些帧率已经足够高,可以产生流畅且自然的动画效果。

考虑到单片机需要执行其他任务,如果显示的是动图,这里可以设置24fps,理论上看起来是比较流畅的,且不会占用太多单片机资源。

注意:

如果使用的是常见的LCD屏幕,一般的刷新率可以达到60Hz(即60帧/秒)。但实际刷新率也可能受到其他因素的限制,例如屏幕驱动器的性能和显示数据传输速度等。

具体刷新优化方案参考以下博文:

[STM32L4]基于STM32L4R5 LCD刷新率优化_ili9341刷新率太低-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值