Keil C51编写的192*64液晶片驱动程序,感谢许多网友供给了参阅源程序,
本程序是在网友们供给的程序基础上改写而成,有许多当地得到高手们的耐
心辅导,在此深表谢意。这是一个完好的C51源程序,我觉得对一位初学C51
的人来说,供给一个完好的简略程序比较简单上手。
————————————————————————————————–*/
/*写汉字液晶子程 液晶屏分为4行*12列汉字,悉数运用模仿接口方法。
/* TGLCMLIMIT64A接口程序(模仿方法)
液晶模块供货商:
Email:
;***************************************************************************
;连线图:
;*LCM—89C52* *LCM—89C52* *LCM——-89C52* *LCM———-89C52* *
;*DB0—P0.0* *DB4—P0.4* *D/I——-P2.6* *CS1———-P2.4* *
;*DB1—P0.1* *DB5—P0.5* *R/W——-P2.7* *CS2———-P2.5* *
;*DB2—P0.2* *DB6—P0.6* *RST——–VCC* *CS3———-P3.2* *
;*DB3—P0.3* *DB7—P0.7* *E———P2.3* *
;注:89C52的晶振频率为12MHz *
;***************************************************************************/
//画线部分请参照avr的c程序。
/*#pragma src /*生成ASM文件开关,必要时翻开 */
#include
#include
#include
#define Uchar unsigned char
/***********液晶显现器接口引脚界说***************/
sbit Elcm= P2^3; //
sbit CS1LCM= P2^4; //
sbit CS2LCM= P2^5; //
sbit CS3LCM= P3^2; /*这个衔接仅仅做试验的暂时接法。*/
sbit Dilcm= P2^6; //
sbit Rwlcm= P2^7; //
sfr Datalcm= 0x80; //数据口
/***********常用操作指令和参数界说***************/
#define DISPON 0x3f /*显现on */
#define DISPOFF 0x3e /*显现off */
#define DISPFIRST 0xc0 /*显现开端行界说 */
#define SETX 0x40 /*X定位设定指令(页) */
#define SETY 0xb8 /*Y定位设定指令(列) */
#define Lcdbusy 0x80 /*LCM忙判别位 */
/**************显现分区鸿沟方位*****************/
#define MODL 0x00 /*左区 */
#define MODM 0x40 /*左区和中区分界 */
#define MODR 0x80 /*中区和右区分界 */
#define LCMLIMIT 0xC0 /*显现区的右鸿沟 */
/****************全局变量界说*******************/
Uchar col,row,cbyte; /*列x,行(页)y,输出数据 */
bit xy; /*画线方向标志:1水平 */
/*****************函数列表**********************/
void Lcminit(void); /*液晶模块初始化 */
void Delay(Uchar); /*延时,进口数为Ms */
void lcdbusyL(void); /*busy判别、等候(左区) */
void lcdbusyM(void); /*busy判别、等候(中区) */
void lcdbusyR(void); /*busy判别、等候(右区) */
void Putedot(Uchar); /*半角字符输出 */
void Putcdot(Uchar); /*全角(汉字)输出 */
void Wrdata(Uchar); /*数据输出给LCM */
void Lcmcls( void ); /*LCM全屏幕清零(填充0) */
void wtcom(void); /*共用busy等候 */
void Locatexy(void); /*光标定位 */
void WrcmdL(Uchar); /*左区指令输出 */
void WrcmdM(Uchar); /*中区指令输出 */
void WrcmdR(Uchar); /*右区指令输出 */
void Putstr(Uchar *puts,Uchar i); /*中英文字符串输出 */
void Rollscreen(Uchar x); /*屏幕向上翻滚演示 */
void Rddata(void); /* 从液晶片上读数据 */
void Linehv(Uchar length); /*横(竖)方向画线 */
void point(void); /*打点 */
void Linexy(Uchar endx,Uchar endy);
/******************数组列表*********************/
Uchar code Ezk[]; /*ASCII惯例字符点阵码表 */
Uchar code Hzk[]; /*自用汉字点阵码表 */
Uchar code STR1[]; /*自界说字符串 */
Uchar code STR2[]; //
Uchar code STR3[]; //
Uchar code STR4[]; //
/********************************/
/* 演示主程序 */
/********************************/
void main(void)
{
Uchar x;
col=0;
row=0;
Delay(40); /*延时大约40Ms,等候外设准备好 */
Lcminit(); /*液晶模块初始化,包含全屏幕清屏*/
Putstr(STR2,24); /*榜首行字符输出,24字节 */
col=0;
row=2;
Putstr(STR1,12); /*第二行字符输出,12字节 */
col=0;
row=4;
Putstr(STR3,24); /*第三行字符输出,24字节 */
col=0;
row=6;
Putstr(STR4,24); /*第四行字符输出,12字节 */
x=0;
col=0;
row=0;
xy = 1; /*方向标志。定为水平方向 */
Linehv(192); /*画一条横线(0,0)-(191,0) */
col=0;
row=15;
xy = 1;
Linehv(192); /*画一条横线(0,15)-(191,15) */
col=0;
row=32;
xy = 1;
Linehv(192); /*画一条横线(0,32)-(191,32) */
col=0;
row=1;
xy = 0; /*方向标志。定为笔直方向 */
Linehv(31); /*画一条竖线(0,1)-(0,31) */
col=191;
row=1;
xy = 0;
Linehv(31); /*画一条竖线(191,1)-(191,31) */
col=0; /*设定斜线的起点坐标 */
row=63;
Linexy(44,31); /*画一段斜线(0,63)-(44,31) */
col=44;
row=31;
Linexy(190,62); /*持续画斜线(44,31)-(191,63) */
while(1){
Rollscreen(x); /*定位新的显现开端行 */
x++;
Delay(100); /*延时,操控翻滚速度 */
};
}
/************************************************/
/*画线。恣意方向的斜线,不支持笔直的或水平线 */
/************************************************/
void Linexy(Uchar endx,Uchar endy)
{
register Uchar t;
int xerr=0,yerr=0,delta_x,delta_y,distance;
Uchar incx,incy;
/* compute the distance in both direcTIons */
delta_x=endx-col;
delta_y=endy-row;
/* compute the direcTIon of the increment ,
an increment of “0” means either a verTIcal or horizontal lines */
if(delta_x》0) incx=1;
else if( delta_x==0 ) incx=0;
else incx=-1;
if(delta_y》0) incy=1;
else if( delta_y==0 ) incy=0;
else incy=-1;
/* determine which distance is greater */
delta_x = cabs( delta_x );
delta_y = cabs( delta_y );
if( delta_x 》 delta_y ) distance=delta_x;
else distance=delta_y;
/* draw the line */
for( t=0;t 《= distance+1; t++ ) {
point();
xerr += delta_x ;
yerr += delta_y ;
if( xerr 》 distance ) {
xerr-=distance;
col+=incx;
}
if( yerr 》 distance ) {
yerr-=distance;
row+=incy;
}
}
}
/****************************************/
/*画线。只供给X或Y方向的,不支持斜线 */
/****************************************/
void Linehv(Uchar length)
{
Uchar xs,ys;
if (xy){ys = col;
for (xs=0;xscol = ys + xs;
point();}
}
else {xs = row;
for (ys=0;ysrow = xs + ys;
point();}
}
}
/****************************************/
/* 画点 */
/****************************************/
void point(void)
{
Uchar x1,y1,x,y;
x1=col;
y1=row;
row=y1》》3; /*取Y方向分页地址 */
Rddata();
y=y1&0x07; /*字节内方位核算 */
x=0x01;
x=x《Wrdata(cbyte|x); /*画上屏幕 */
col=x1; /*康复xy坐标 */
row=y1;
}
/****************************************/
/* 屏幕翻滚定位 */
/****************************************/
void Rollscreen(Uchar x)
{
cbyte = DISPFIRST|x; /*界说显现开端行为x?*/
WrcmdL(cbyte);
WrcmdM(cbyte);
WrcmdR(cbyte);
}
/****************************************/
/* 一个字串的输出 */
/****************************************/
void Putstr(Uchar *puts,Uchar i)
{
Uchar j,X;
for (j=0;j{
X = puts[j];
if (X&0x80)
{
Putcdot(X&0x7f); /*只保存低7位*/
}
else Putedot(X-0x20); /*ascii码表从0x20开端*/
}
}
/****************************************/
/* 半角字符点阵码数据输出 */
/****************************************/
void Putedot(Uchar Order)
{
Uchar i,bakerx,bakery; /*共界说4个局部变量 */
int x; /*偏移量,字符量少的能够界说为UCHAR */
bakerx = col; /*暂存x,y坐标,已备下半个字符运用 */
bakery = row;
x=Order * 0x10; /*半角字符,每个字符16字节 */
/*上半个字符输出,8列 */
for(i=0;i《8;i++)
{
cbyte = Ezk[x]; /*取点阵码,rom数组 */
Wrdata(cbyte); /*写输出一字节 */
x++;
col++;
if (col==LCMLIMIT){col=0;row++;row++;}; /*下一列,假如列越界换行*/
if (row》7) row=0; /*假如行越界,回来忆行 */
} /*上半个字符输出完毕 */
col = bakerx; /*列对齐 */
row = bakery+1; /*指向下半个字符行 */
/*下半个字符输出,8列 */
for(i=0;i《8;i++)
{
cbyte = Ezk[x]; /*取点阵码 */
Wrdata(cbyte); /*写输出一字节 */
x++;
col++;
if (col==LCMLIMIT){col=0;row=row+2;}; /*下一列,假如列越界换行*/
if (row》7) row=1; /*假如行越界,回来忆行 */
} /*下半个字符输出完毕 */
row=bakery;
} /*整个字符输出完毕 */
/****************************************/
/* 全角字符点阵码数据输出 */
/****************************************/
void Putcdot(Uchar Order)
{
Uchar i,bakerx,bakery; /*共界说3个局部变量 */
int x; /*偏移量,字符量少的能够界说为UCHAR */
bakerx = col; /*暂存x,y坐标,已备下半个字符运用 */
bakery = row;
x=Order * 0x20; /*每个字符32字节 */
/*上半个字符输出,16列 */
for(i=0;i《16;i++)
{
Wrdata(Hzk[x]); /*写输出一字节 */
x++;
col++;
if (col==LCMLIMIT){ col=0;row++;row++;} /*下一列,假如列越界换行*/
if (row》6) row=0; /*假如行越界,回来忆行 */
} /*上半个字符输出完毕 */
/*下半个字符输出,16列 */
col = bakerx;
row = bakery+1;
for(i=0;i《16;i++) /*下半部分*/
{
Wrdata(Hzk[x]);
x++;
col++;
if (col==LCMLIMIT){col=0;row++;row++;} /*下一列,假如列越界换行*/
if (row》7) row=1; /*假如行越界,回来忆行 */
} /*下半个字符输出完毕 */
row = bakery;
} /*整个字符输出完毕 */
/****************************************/
/* 清屏,全屏幕清零 */
/****************************************/
void Lcmcls( void )
{
for(row=0;row《8;row++)
for(col=0;col}
/****************************************/
/* 从液晶片上读数据,保存在全局变量中 */
/****************************************/
void Rddata(void)
{
Locatexy(); /*坐标定位,回来时保存分区状况不变 */
Datalcm=0xFF;
Dilcm = 1; /*数据*/
Rwlcm = 1; /*读数据*/
Elcm = 1; /*读入到LCM*/
_nop_();
cbyte = Datalcm; /*虚读一次 */
Elcm = 0;
Locatexy(); /*坐标定位,回来时保存分区状况不变 */
Datalcm=0xFF;
_nop_();
Dilcm = 1; /*数据*/
Rwlcm = 1; /*读数据*/
Elcm = 1; /*读入到LCM*/
_nop_();
cbyte = Datalcm; /*从数据口读数据,真读 */
Elcm = 0;
}
/****************************************/
/* 数据写输出 */
/****************************************/
void Wrdata(Uchar X)
{
Locatexy(); /*坐标定位,回来时保存分区状况不变 */
// wtcom();
Dilcm = 1; /*数据输出*/
Rwlcm = 0; /*写输出 */
Datalcm = X; /*数据输出到数据口 */
Elcm = 1; /*读入到LCM*/
_nop_();
Elcm = 0;
}