📄 qh12864.txt
字号:
[转帖]QH12864液晶显示器驱动及单片机间通信程序
/************************************************************/
/********* QH12864液晶显示器驱动及单片机间通信程序 ***********/
/********* Author: xieqin ************/
/******** CopyRight:10/03/2004 ***********/
/** 本程序具有一次接收数据数可变和自动消隐两大扩展功能 **/
/** 本程序具有汉字编码和西文编码自动搜索功能 **/
/**** 本程序发串行通信用定时器为T2,选用AT89C52单片机 ****/
/************************************************************/
#include<absacc.h>
#include<reg52.h>
#include<string.h>
#include<stdio.h>
#include<stdarg.h>
#define D_ADD XBYTE[0x0000] //数据口
#define C_ADD XBYTE[0x0100] //地址口
unsigned char GetData[64]={0x01,0x02,0x03,0x04,0x05,0x06};
unsigned char NUM=5;//接收数据位数存放单元
unsigned char NZNUM=5;//消隐处理后有效数据位数存放单元
struct ENode{ //西文显示结点结构体声明
const char ch;
unsigned char dat;
};
struct CNode{ //汉字显示结点结构体声明
char ch[2];//字体存放单元
unsigned char dat[32];//汉字字模存放单元
};
struct ENode code newchar[]={//西文字符库
' ',0x00,'!',0x01,'"',0x02,'#',0x03,'$',0x04,'%',0x05,'&',0x06,//''',0x07,
'(',0x08,')',0x09,'*',0x0a,'+',0x0b,',',0x0c,'-',0x0d,'.',0x0e,'/',0x0f,
'0',0x10,'1',0x11,'2',0x12,'3',0x13,'4',0x14,'5',0x15,'6',0x16,'7',0x17,'8',0x18,'9',0x19,':',0x1a,';',0x1b,'<',0x1c,'=',0x1d,'>',0x1e,'?',0x1f,
//'',0x20,
'A',0x21,'B',0x22,'C',0x23,'D',0x24,'E',0x25,'F',0x26,'G',0x27,'H',0x28,'I',0x29,'J',0x2a,'K',0x2b,'L',0x2c,'M',0x2d,'N',0x2e,'O',0x2f,
'P',0x30,'Q',0x31,'R',0x32,'S',0x33,'T',0x34,'U',0x35,'V',0x36,'W',0x37,'X',0x38,'Y',0x39,'Z',0x3a,//0x3b,0x3c,0x3d,0x3e,0x3f,
'`',0x40,'a',0x41,'b',0x42,'c',0x43,'d',0x44,'e',0x45,'f',0x46,'g',0x47,'h',0x48,'i',0x49,'j',0x4a,'k',0x4b,'l',0x4c,'m',0x4d,'n',0x4e,'o',0x4f,
'p',0x50,'q',0x51,'r',0x52,'s',0x53,'t',0x54,'u',0x55,'v',0x56,'w',0x57,'x',0x58,'y',0x59,'z',0x5a,'{',0x5b,'|',0x5c,'}',0x5d,'~',0x5e,' ',0x5f
//0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
//0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
};
struct CNode code newhanzi[]={//中文汉字库
//因版面大小所限,中文字库内容被删去,大家可以用相关软件自造汉字库,模式如下所示
"中",
/*-- 文字: 中 0 --*/
/*-- 黑体11; 此字体下对应的点阵为:宽x高=14x14 --*/
/*-- 宽度不是8的倍数,现调整为:宽度x高度=16x14 --*/
0x00,0x00,0x03,0x00,0x03,0x00,0x3F,0xF0,0x23,0x10,0x23,0x10,0x23,0x10,0x23,0x10,
0x3F,0xF0,0x23,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
void delay(unsigned char times) //延时子程序
{
unsigned char data i,j,k;
for(i=0;i<times;i++)
for(j=0;j<times;j++)
for(k=0;k<10;k++);
}
void test01(void)
{ //读写指令与读写数据状态子程序
do{
ACC=C_ADD;
}while(ACC&0x03!=0x03);
}
void test2(void)
{ //数据自动读状态子程序
do{ //read_prepare
ACC=C_ADD;
}while(ACC&0x04!=0x04);
}
void test3(void)
{ //数据自动写状态子程序
do{ //write_prepare
ACC=C_ADD;
}while(ACC&0x08!=0x08);
}
void write_c_0(unsigned char com)
{ //写无参数指令子程序
test01();
C_ADD=com;
}
void write_c_1(unsigned char dat1,unsigned char com)
{ //写单参数指令子程序
test01();
D_ADD=dat1;
C_ADD=com;
}
void write_c_2(unsigned char dat1,unsigned char dat2,unsigned char com)
{ //写双参数指令子程序
test01();
D_ADD=dat1;
D_ADD=dat2;
C_ADD=com;
}
void init_LCD(void)
{ //LCD初始化子程序
write_c_2(0x00,0x00,0x40);//0x40文本区首址
write_c_2(0x20,0x00,0x41);//0x41文本区宽度
write_c_2(0x00,0x08,0x42);//0x42图形区首址
write_c_2(0x20,0x00,0x43);//0x43图形区宽度
write_c_0(0xa7);//0xa7光标形状设置
write_c_0(0x80);//0x80显示方式逻辑或
write_c_0(0x9c);//0x9c显示开关设置
}
void cls(void)
{ //LCD清屏子程序
unsigned int data i;
write_c_2(0x00,0x00,0x24);//置RAM地址指针到(0,0)
write_c_0(0xb0);//设置自动写
for(i=8192;i>0;i--)
{
test3();
D_ADD=0x00;
}
write_c_0(0xb2);//自动写与读结束
}
void set_cgram(unsigned char code *ch)
{ //建立CGRAM子程序
unsigned int i,n=0;
write_c_2(0x03,0x00,0x22);//CGRAM地址设置
write_c_2(0x00,0x1c,0x24);
write_c_0(0xb0);
for(i=224;i>0;i--)
{
test3();
D_ADD=ch[n];
n++;
}
write_c_0(0xb2);
}
void write_zifu(unsigned char o_x,unsigned char o_y,unsigned char daima,unsigned char attr)
{ //固定格式的西文编码写入子程序
unsigned int add;
unsigned char dat1,dat2;
add=(unsigned int)(o_y*16+o_x);
dat1=(unsigned char)add&0xff;
dat2=(unsigned char)((add>>8)&0xff);
write_c_2(dat1,dat2,0x24);
write_c_1(daima,0xc4);
dat2+=0x08;
write_c_2(dat1,dat2,0x24);
//write_c_1(attr,0xc4);
}
void new_write_zifu(unsigned char o_x,unsigned char o_y,char c,unsigned char attr)
{ //具有自动搜索西文编码功能的西文编码写入子程序
unsigned int add;
unsigned char dat1,dat2,k,size;
add=(unsigned int)(o_y*16+o_x);
for(k=0,size=(sizeof(newchar)/sizeof(newchar[0]));k<size;k++)
{//在字库中查询该字符
if(newchar[k].ch==c)
break;//找到该字符则跳出
}
if(k>=(sizeof(newchar)/sizeof(newchar[0])))
//return;//判断是已经找到该字还是在整个字库中未发现该字符
k=0;
dat1=(unsigned char)add&0xff;
dat2=(unsigned char)((add>>8)&0xff);
write_c_2(dat1,dat2,0x24);
write_c_1(newchar[k].dat,0xc4);
dat2+=0x08;
write_c_2(dat1,dat2,0x24);
//write_c_1(attr,0xc4);
}
void new_write_under_picture(unsigned char o_x,unsigned char o_y,char cch[2])
{ //具有自动搜索汉字编码功能的在图形方式下汉字编码写入程序
unsigned int data add;
unsigned char data dat1,dat2,i,j,size,k=0;
add=(unsigned int)(o_y*32+o_x)+0x0800;
for(k=0,size=(sizeof(newhanzi)/sizeof(newhanzi[0]));k<size;k++)
{//在字库中查询该字
if((newhanzi[k].ch[0]==cch[0])&&(newhanzi[k].ch[1]==cch[1]))
break;//找到该字则跳出
}
if(k>=(sizeof(newhanzi)/sizeof(newhanzi[0])))
return;//判断是已经找到该字还是在整个字库中未发现该字
for(i=16,j=0;i>0;i--,j+=2)
{
dat1=(unsigned char)add&0xff;
dat2=(unsigned char)((add>>8)&0xff);
write_c_2(dat1,dat2,0x24);//设置RAM地址指针
write_c_1(newhanzi[k].dat[j],0xc0);//写入左部分字模数据
write_c_1(newhanzi[k].dat[j+1],0xc0);//写入右部分字模数据
add+=32;//置偏移地址为16
}
}
/*
void print(unsigned char o_x,unsigned char o_y,char *format,...)
{ //本子程序目前尚不能调用,但具有自动写入汉字功能的可扩展性
va_list arg_ptr;
char temp[64];
unsigned char i,str_len;
va_start(arg_ptr,format);
// str_len=(unsigned char)vsprintf(temp,format,arg_ptr);
str_len=sizeof(format)/sizeof(format[0]);
sprintf(temp,format);
va_end(arg_ptr);
}
*/
void initport() //串行通信初始化子程序
{
EA=1;//开CPU中断
TH2=0XFF; //设置波特率11.0592M 为9600
TL2=0XDC;//选用定时/计数器2为波特率发生器
RCAP2H=0xFF;//对PCAP寄存器存入初始值
RCAP2L=0xDC;
T2CON=0X34;//定时/计数器2控制寄存器参数设置
SCON=0X50;//串行口控制寄存器参数设置(方式1)
}
void receive_port(unsigned char *dat)//串行口数据接收子程序
{
unsigned char sign,number,i;
do{
while(RI==0);RI=0;sign=SBUF;
if(sign==0xff)break;
}while(1);
while(RI==0);RI=0;number=SBUF;
for(i=0;i<number;i++)
{
while(RI==0);RI=0;dat[i]=SBUF;
}
NUM=number;
}
void control_NZNUM()//消隐处理子程序
{
unsigned char i;
NZNUM=2;
for(i=2;i<NUM;i++)
{
if(GetData[i]>0)NZNUM=i+1;
}
}
void write_number(unsigned char o_x,unsigned char o_y,unsigned char dat)
{ //接收数据送LCD显示,数字编码写入子程序
//(本子程序也具有西文编码写入功能)
unsigned int add;
unsigned char dat1,dat2;
add=(unsigned int)(o_y*16+o_x);
dat1=(unsigned char)add&0xff;
dat2=(unsigned char)((add>>8)&0xff);
write_c_2(dat1,dat2,0x24);
write_c_1(dat,0xc4);
dat2+=0x08;
write_c_2(dat1,dat2,0x24);
//write_c_1(attr,0xc4);
}
void main(void) //T6963液晶显示驱动与串行数据接收主程序
{
unsigned char x,y,i,last_number;//坐标
unsigned char dat[]={'2','0','0','8','.','0','m','V'};
init_LCD();
cls();
x=0;y=25;
new_write_under_picture(x+=2,y,"中");
new_write_under_picture(x+=2,y,"国");
new_write_under_picture(x+=2,y,"地");
new_write_under_picture(x+=2,y,"质");
new_write_under_picture(x+=2,y,"大");
new_write_under_picture(x+=2,y,"学");
x=1;
new_write_zifu(x++,10,'w',0);
new_write_zifu(x++,10,'w',0);
new_write_zifu(x++,10,'w',0);
new_write_zifu(x++,10,'.',0);
new_write_zifu(x++,10,'c',0);
new_write_zifu(x++,10,'u',0);
new_write_zifu(x++,10,'g',0);
new_write_zifu(x++,10,'.',0);
new_write_zifu(x++,10,'e',0);
new_write_zifu(x++,10,'d',0);
new_write_zifu(x++,10,'u',0);
new_write_zifu(x++,10,'.',0);
new_write_zifu(x++,10,'c',0);
new_write_zifu(x++,10,'n',0);
delay(255);delay(255);
cls();
x=0;y=25;
new_write_under_picture(x+=1,y,"测");
new_write_under_picture(x+=2,y,"控");
new_write_under_picture(x+=2,y,"技");
new_write_under_picture(x+=2,y,"术");
new_write_under_picture(x+=2,y,"与");
new_write_under_picture(x+=2,y,"仪");
new_write_under_picture(x+=2,y,"器");
delay(255); delay(200);
cls();
x=0,y=16;
new_write_under_picture(x+=1,y,"指");
new_write_under_picture(x+=2,y,"导");
new_write_under_picture(x+=2,y,"老");
new_write_under_picture(x+=2,y,"师");
new_write_under_picture(x+=2,y,":");
new_write_under_picture(x+=2,y,"沈");
new_write_under_picture(x+=3,y,"博");
x=0;y=32;
new_write_under_picture(x+=1,y,"ip");
new_write_under_picture(x+=6,y,"生");
new_write_under_picture(x+=2,y,":");
new_write_under_picture(x+=2,y,"谢");
new_write_under_picture(x+=3,y,"琴");
delay(255);delay(100);
cls();
// }while(1);
x=0;y=20;
new_write_under_picture(x+=2,y,"当");
new_write_under_picture(x+=2,y,"前");
new_write_under_picture(x+=2,y,"ce");
new_write_under_picture(x+=2,y,"得");
new_write_under_picture(x+=2,y,"电");
new_write_under_picture(x+=2,y,"压");
new_write_under_picture(x+=2,y,":");
y=10; x=3;
new_write_zifu(x++,y,'U',0);
new_write_zifu(x++,y,'=',0);
for(i=0;i<8;i++)
new_write_zifu(x++,y,dat[i],0);
delay(255);
initport();
do{
receive_port(GetData);//接收数据
control_NZNUM(); //消隐处理
x=5; y=10;
for(i=NZNUM-1;i>0;i--)write_number(x++,y,GetData[i]|0x10);//数据编码写入
new_write_zifu(x++,y,'.',0);
write_number(x++,y,GetData[0]|0x10);
new_write_zifu(x++,y,'m',0);
new_write_zifu(x++,y,'V',0);
for(i=0;i<8-NUM;i++)//在显示位数发生变化的情况下,自动擦除过时信息
write_number(x++,y,0x00);
}while(1);
for(;;);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -