📄 液晶.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 + -