单片机
返回首页

C51单片机对液晶片的驱动

2023-04-13 来源:elecfans

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;

}


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 离子检测器电路分析

  • 非常简单的150W功放电路图

  • 如何使用LED驱动器LM3915制作振动计

  • 分享一个电网倾角计电路

  • 使用NE555和磁簧开关的橱柜照明电路

  • 电谐波图形均衡器示意图

    相关电子头条文章