⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 液晶.h

📁 环境 keil 利用c51F 中断刷新 LCD (128*64) 内部ram做显示缓存
💻 H
字号:
/*---------------------------------------------------------------------------
;	Copyright (C) 2007 8 29
; 	All rights reserved.
;
;
; 	文件名  : 液晶.H 
; 	驱动对象: FYD12864-0402B
;	软件环境: C8051F020
;	系统要求: data>=52.0 xdata>=72 code>=2771
			  占用T0,P5,P3^0(RS),P3^1(RW),P3^2(E),P3^5(REST)  中断周期>=128Hz(与显示效果及效率相关)
; 	摘要	: 具体函数功能见下面函数声明
; 	版本	: 1.0
;
;---------------------------------------------------------------------------*/

#include "C8051F020.H"

void Tint0(void);

//液晶处理类函数
void SAd(unsigned char adress);//直接写屏地址设置(不推荐使用)
void StartFYD(void);//液晶初始化函数
void SetAd(unsigned char adress);//设定显示地址
void OutCH(unsigned char ch);//显示一个AISC码
void OutStr(unsigned char *str);//显示一个串 屏幕益出截断
void OutStrS(unsigned char *str);//显示一个串 益出自动到屏幕开始
void OutStrH(unsigned char *str,unsigned char len);//显示一个串 自动滚动屏幕
void OutS(unsigned char *str);//显示一个串 自动滚动屏幕 支持转义字符'\n'  屏幕结束处的最后一个\n将被忽略
void OutALL();//强制刷新屏幕
void OpenMark();//开游标
void SetMark(unsigned char adress);//设定游标地址
void CloseMark();//关闭游标
unsigned char ReadMark();//读取游标地址
void Clr();//清屏
//void ChickOK();//检查液晶 直到可以再接受指令   如此定义,可以直接嵌入代码提高,执行速度
#define ChickOK(); 	{ DataPortIn; RS=0; RW=1; do {E=0; E=1; DataPort=0xFF; } while(DataPort&0x80); }

void Print(unsigned long Data,unsigned char lena,unsigned char lenb);//显示数据  左边长度  右边截断长度
void Cover();//封面


//液晶控制端口
sbit RS=P3^0;	//Output
sbit RW=P3^1;	//Output
sbit E=P3^2;	//Output
sbit REST=P3^5;	//Output
//液晶数据端口	方便修改端口
#define DataPortIn P74OUT&=0xF3
#define DataPortOut P74OUT|=0x0C
#define DataPort P5


//液晶数据镜象
static unsigned char xdata CHbuf[64],CHnew[8];
static unsigned char XY,nowXY,markXY;//XY坐标 当前刷新坐标  反白显示的坐标
static unsigned char newCount;//新数据



///////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////函数调试区///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
void Tint0(void) interrupt 1
{
	unsigned char z,bufXY;
	TL0=0;
	TH0=220;

	if(newCount!=0)//液晶需要刷新	改变if else的顺序来改变优先级
	{
		newCount--;
		bufXY=nowXY&0x38;
		for(z=bufXY;; )
		{
			if(CHnew[z>>3]!=0) break;
			z+=8;
			if((z&0x38)==bufXY) break;
		}
		if(CHnew[z>>3]!=0)//确实有更新
		{
			bufXY=nowXY&0x3F;

			if(nowXY<(z&0x38)) nowXY=(z&0x38);
			else nowXY&=0x3F;
			for( ; ; )
			{
				z=nowXY&0x07;
				if(	(CHnew[nowXY>>3]>>z)&0x01 )//CHbuf[nowXY]是新写入的
				{
					if((nowXY==bufXY)&&(((nowXY&0x0F)!=0)||(RS==0)))//上次才写了,可以直接写
					{
						ChickOK();
					 	RW=0; E=1; RS=1; DataPortOut; DataPort=CHbuf[nowXY]; E=0;
						CHnew[nowXY>>3]&=(~(0x01<<z));//清除标志位
						nowXY++;
					}
					else//要移动地址
					{
						newCount++;
						ChickOK();
						RS=0; RW=0;  DataPortOut; z=nowXY>>1;
						if(z<=7) DataPort=z+0x80;
						else if(z<=15) DataPort=z+0x88;
						else if(z<=23) DataPort=z+0x78;
						else DataPort=z+0x80;
						E=1; E=0;

						if(nowXY&0x01)//临时标志 奇数地址的特殊需要
						{
							nowXY--;
							CHnew[nowXY>>3]|=(0x01<<(nowXY&0x07));
							newCount++;
						}
					}
					break;
				}
				nowXY++;
				nowXY&=0x3F;
				if(nowXY==bufXY) break;
			}
		}
		else
		{
			for(z=0;z<8&&(CHnew[z]==0);z++);
			if(z==8) newCount=0;
		}
	}
	else if(markXY<64)
	{
		nowXY=markXY; markXY&=0x3F; markXY>>=1;
		ChickOK();
		RS=0; RW=0; DataPortOut;
		if(markXY<=7) DataPort=markXY+0x80;
		else if(markXY<=15) DataPort=markXY+0x88;
		else if(markXY<=23) DataPort=markXY+0x78;
		else DataPort=markXY+0x80;
		E=1; E=0;
		markXY<<=1;
	}
	else
	{
	}
}


void P7int(void) interrupt 19
{
	P3IF&=0x7F;//清中断
}

void SAd(unsigned char adress)//直接写屏地址设置
{
	DataPortIn;
	E=1; RS=0; RW=1;
	do {E=0; E=1; DataPort=0xFF; } 
	while(DataPort&0x80);
	RS=0; RW=0; E=1; DataPortOut; DataPort=adress; E=0;
}

void OutALL()//直接写屏
{
	unsigned char i;

	TR0=0;
	for(i=0;i<8;i++) CHnew[i]=0;
	nowXY=0; newCount=0;

	SAd(0x80);
	for(i=0;i<16;i++)
	{
		DataPortIn; E=1; RS=0; RW=1;
		do { E=0; E=1; DataPort=0xFF; } 
		while( DataPort&0x80 );
		RS=1; RW=0; E=1; DataPortOut; DataPort=CHbuf[i]; E=0;
	}
	SAd(0x90);
	for(;i<32;i++)
	{
		DataPortIn; E=1; RS=0; RW=1;
		do { E=0; E=1; DataPort=0xFF; } 
		while( DataPort&0x80 );
		RS=1; RW=0; E=1; DataPortOut; DataPort=CHbuf[i]; E=0;
	}
	SAd(0x88);
	for(;i<48;i++)
	{
		DataPortIn; E=1; RS=0; RW=1;
		do { E=0; E=1; DataPort=0xFF; } 
		while( DataPort&0x80 );
		RS=1; RW=0; E=1; DataPortOut; DataPort=CHbuf[i]; E=0;
	}
	SAd(0x98);
	for(;i<64;i++)
	{
		DataPortIn; E=1; RS=0; RW=1;
		do { E=0; E=1; DataPort=0xFF; } 
		while( DataPort&0x80 );
		RS=1; RW=0; E=1; DataPortOut; DataPort=CHbuf[i]; E=0;
	}
	if(markXY<64)
	{
		nowXY=markXY; markXY&=0x3F; markXY>>=1;

		DataPortIn; E=1; RS=0; RW=1;
		do { E=0; E=1; DataPort=0xFF; } 
		while( DataPort&0x80 );

		if(markXY<=7) DataPort=markXY+0x80;
		else if(markXY<=15) DataPort=markXY+0x88;
		else if(markXY<=23) DataPort=markXY+0x78;
		else DataPort=markXY+0x80;
		E=1; E=0;
		markXY<<=1;
	}
	TR0=1;

}





void StartFYD(void)
{
	XBR2=0x40;
	P3MDOUT|=0x27;
	REST=0;	
	for(XY=0;XY<255;XY++);//Delay(1)
	REST=1;
	for(XY=0;XY<255;XY++);//Delay(1);
	for(XY=0;XY<255;XY++);//Delay(1);
	for(XY=0;XY<255;XY++);//Delay(1);
	for(XY=0;XY<255;XY++);//Delay(1);
	RS=0; RW=0; E=1; DataPortOut; DataPort=0x34; E=0;//8位数据 基本指令 
	ChickOK();
	RS=0; RW=0; E=1; DataPortOut; DataPort=0x01; E=0;//清除显示
	ChickOK();
	RS=0; RW=0; E=1; DataPortOut; DataPort=0x02; E=0;//地址归位

	ChickOK();
	RS=0; RW=0; E=1; DataPortOut; DataPort=0x0C; E=0;//关游标 开显示 开反白

	RS=1;
	newCount=0;
	for(XY=0;XY<64;XY++) CHbuf[XY]=' ';
	for(XY=0;XY<8;XY++) CHnew[XY]=0;
	XY=nowXY=markXY=0;

	//T0设置
	ET0=0;
	TMOD=(TMOD&0xFD)|0x01;//16位定时器
	CKCON|=0x04;//T0 工作在系统时钟
	ET0=1;

	TR0=1;
}

void Cover()//封面
{
	SetAd(0x00);
	OutS("┌──────┐");
	OutS("│  欢迎使用  │");
	OutS("│  ¨……¨  │");
	OutS("└──────┘");
}

void Clr()
{
	unsigned char i;
	newCount=0;
	for(i=0;i<64;i++) CHbuf[i]=' ';
	for(i=0;i<8;i++) CHnew[i]=0;
	XY=nowXY=markXY=0;
	i=RS; TR0=0; ChickOK(); RS=0; RW=0; E=1; DataPortOut; DataPort=0x01; E=0; RS=i; TR0=1;//清除显示
}


void Print(unsigned long Data,unsigned char lena,unsigned char lenb)//显示数据  左边到右截取长度  右边截断长度
{
	//显示位数设定
	unsigned char i,k;
	unsigned long E10,Lbuf;
	unsigned char buf;

	E10=1000000000L; Lbuf=Data;
	k=0; i=0;
	for( ; ; )
	{
		buf=(char)(Lbuf/E10)+'0';
		Lbuf%=E10;
		E10=E10/10;
		if((i+k)<(10-lena)) {k++; continue; }

		if((i==0)&&(buf=='0')&&(k!=9-lenb))
		{
			k++;
			if(k>lenb) OutCH(' ');
		}
		else
		{
			i++;
			OutCH(buf);
		}
		if((i+k)>=(10-lenb)) break;
	}
	return;
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////游标处理类////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
void SetMark(unsigned char adress)//设定游标地址
{
	markXY=adress;
}

void OpenMark()//打开游标
{
	unsigned char i;
	TR0=0; i=RS; ChickOK(); RS=0; RW=0; E=1; DataPortOut; DataPort=0x0F; E=0; ChickOK(); RS=i; TR0=1;//  游标 开显示 开反白
}

void CloseMark()//关闭游标
{
	unsigned char i;
	if(markXY>64) markXY>>=1;
	TR0=0; i=RS; ChickOK(); RS=0; RW=0; E=1; DataPortOut; DataPort=0x0C; E=0; ChickOK(); RS=i; TR0=1;//关游标 开显示 开反白
}

unsigned char ReadMark()//读取游标地址
{
	return markXY>64?markXY>>1:markXY;
}



//////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////显示字符及字符串处理类////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
void SetAd(unsigned char adress)//设定显示地址
{
	XY=adress;
}

void OutCH(unsigned char ch)//显示一个AISC码
{
	XY&=0x3F;
	CHbuf[XY]=ch;
	CHnew[XY>>3]|=(0x01<<(XY&0x07));
	newCount=newCount<250?newCount+1:250;
	XY++;
	markXY=(XY&0x3F);
	if(markXY==0) markXY=64;
}

void OutStr(unsigned char *str)//显示一个串 屏幕益出截断
{
	unsigned char i;
	XY&=0x3F;
	for(i=0;str[i];i++)
	{
		CHbuf[XY]=str[i];
		CHnew[XY>>3]|=0x01<<(XY&0x07);
		if(XY==63)
		{//屏幕益出
			break;
		}
		else XY++;
	}
	newCount=(newCount<250-i)?newCount+i:250;
	markXY=(XY&0x3F);
	if(markXY==0) markXY=64;
}

void OutStrS(unsigned char *str)//显示一个串 自动到屏幕开始
{
	unsigned char i;
	XY&=0x3F;
	for(i=0;str[i];i++)
	{
		CHbuf[XY]=str[i];
		CHnew[XY>>3]|=0x01<<(XY&0x07);
		XY=XY<63?XY+1:0;
	}
	newCount=(newCount<250-i)?newCount+i:250;
	markXY=(XY&0x3F);
}

void OutStrH(unsigned char *str,unsigned char len)//显示一个串 自动滚动屏幕
{
	unsigned char i,j;

	if(len<=64-XY)//直接写
	{
		for(i=0;i<len;i++)
		{
			CHbuf[XY]=str[i];
			CHnew[XY>>3]|=0x01<<(XY&0x07);
			XY++;
		}
		newCount=(newCount<250-i)?newCount+i:250;
	}
	else//复制 及更新
	{
		i=len+XY;
		if(i!=(i&0xF0)) i=(i&0xF0)+16;//扩展总长度
		j=i-64;
		i=XY;
		for(XY=0;XY<64;j++,XY++)
		{
			if(j<i) CHbuf[XY]=CHbuf[j];
			else if(j-i>=len) CHbuf[XY]=' ';
			else CHbuf[XY]=str[j-i];
		}
		//生成地址
		i+=len;
		if(i!=(i&0xF0)) XY=(i&0x0F)+48;
		else XY=64;
		for(i=0;i<8;i++) CHnew[i]=0xFF;
		newCount=64;
	}
	markXY=(XY&0x3F);
	if(markXY==0) markXY=64;
}

void OutS(unsigned char *str)//显示一个串 自动滚动屏幕 可以打印转义字符 \n
{
	//最后一个字符为\n会被忽略
	unsigned char i,len,z;
	for(i=0,len=0;str[len];len++)
	{
		if(str[len]=='\n')
		{
			if(i!=len) OutStrH(str+i,len-i);
			z=16-(XY&0x0F);
			OutStrH("                ",z);
			i=len+1;
		}
	}
	if(len!=i)
	{
		OutStrH(str+i,len-i);
	}
	markXY=(XY&0x3F);
	if(markXY==0) markXY=64;
}




/*void ChickOK(void)
{
	//可能对RS进行修改  但是对定时刷新不影响
	DataPortIn;
	RS=0; RW=1;
	do {E=0; E=1; DataPort=0xFF; } 
	while(DataPort&0x80);
}*/



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -