📄 lcd.c
字号:
/*******************************************************
程序功能:LCD汉字及图形点阵显示
作者:FEDLT
广西工学院电子信息工程03级
e-mail:fedlt@163.com
QQ:282695105
*********************************************************
接线说明:
89C51 LM1264ldc
P0.0~7 --- DB0~7(7~14)
P2.0---RS(4)
P2.1---R/W(5)
P2.2---E(6)
P2.3---CS1(15)
P2.4---CS2(16)
P2.5---RST(17)
*********************************************************/
#include<reg51.h>
#include<math.h>
#include<INTRINS.H>
#define Uchar unsigned char
/*注:89c51的晶振频率为12MHz*/
/***********液晶显示器接口引脚定义***************/
sbit RS=P2^7; /*RS控制信号*/
sbit RW=P2^6; /*R/W控制信号*/
sbit E=P2^5; /*使能信号*/
sbit CS1=P2^4; /*CS1控制信号*/
sbit CS2=P2^3; /*CS2控制信号*/
sbit RST=P2^2; /*RST清零控制信号*/
sfr Data=0x80; /*数据口*/
/***********常用操作命令和参数定义***************/
#define DISPON 0x3f /*显示on*/
#define DISPOFF 0x3e /*显示off */
#define DISPFIRST 0xc0 /*显示起始行定义*/
#define SETX 0xb8 /*X定位设定指令(页)*/
#define SETY 0x40 /*Y定位设定指令(列)*/
#define Lcdbusy 0x80 /*LCM忙判断位*/
/**************显示分区边界位置*****************/
#define MODL 0x00 /*左区*/
#define MODR 0x40 /*左区和右区分界*/
#define LCDLIMIT 0x80 /*显示区的右边界*/
/****************全局变量定义*******************/
Uchar row=0,col=0,cbyte; /*行(页)x,列y,输出数据*/
bit xy; /*画线方向标志:1水平,0垂直*/
/*****************函数列表**********************/
void Lcdinit(void); /*液晶模块初始化*/
void Delay(Uchar); /*延时,入口数为Ms */
void lcdbusyL(void); /*busy判断、等待(左区)*/
void lcdbusyR(void); /*busy判断、等待(右区)*/
void Putedot(Uchar); /*半角字符输出*/
void Putcdot(Uchar); /*全角(汉字)输出*/
void Wrdata(Uchar); /*数据输出给LCD*/
void Lcdclr(void); /*LCD全屏幕清零(填充0) */
void wtcom(void); /*公用busy等待*/
void Locatexy(void); /*光标定位*/
void WrcmdL(Uchar); /*左区命令输出 */
void WrcmdR(Uchar); /*右区命令输出 */
void Putstr(Uchar posx,Uchar posy,Uchar *puts,Uchar i); /*中英文字符串输出*/
void Rollscreen(Uchar x); /*屏幕向上滚动*/
void Rddata(void); /*从液晶片上读数据*/
void Linehv(Uchar posx,Uchar posy,Uchar length,Uchar XY); /*横(竖)方向画线*/
void point(Uchar posx,Uchar posy); /*打点*/
void Linexy(Uchar posx,Uchar posy,Uchar endx,Uchar endy);
void WR_rowcol(Uchar x,Uchar y); /*把x,y的坐标值写到行列对应的值中*/
/******************数组列表*********************/
Uchar code Ezk[]; /*ASCII常规字符点阵码表 */
Uchar code Hzk[]; /*自用汉字点阵码表*/
Uchar code STR1[]; /*自定义字符串*/
Uchar code STR2[];
Uchar code STR3[];
Uchar code STR4[];
Uchar code STR5[];
/****************************************主程序*****************************************/
void main(void)
{
Uchar x=0;
Delay(40); /*延时大约40Ms,等待外设准备好*/
Lcdinit(); /*液晶模块初始化,包括全屏幕清屏*/
Putstr(0,48,STR1,9); /*第一行字符输出,12字节*/
Putstr(2,2,STR2,14); /*第二行字符输出,14字节*/
Putstr(4,2,STR3,15); /*第三行字符输出,11字节*/
Putstr(6,2,STR4,14); /*第四行字符输出,12字节*/
Putstr(2,18,STR5,1);
Linehv(0,0,128,1); /*画一条横线(0,0)-(0,127)*/
Linehv(16,0,128,1); /*画一条横线(15,0)-(15,127)*/
Linehv(32,0,128,1); /*画一条横线(32,0)-(32,127)*/
Linehv(48,0,128,1);
Linehv(63,0,128,1);
Linehv(0,47,16,0);
Linehv(1,0,63,0); /*画一条竖线(1,0)-(31,0)*/
Linehv(1,127,63,0); /*画一条竖线(1,127)-(31,127)*/
Linexy(0,0,16,48); /*画一段斜线(63,0)-(31,44) */
point(10,3);
point(10,5);
point(10,7);
point(10,9);
point(10,11);
while(1){
Rollscreen(x); /*定位新的显示起始行*/
x++;
Delay(100); /*延时,控制滚动速度*/
};
}
/*************************************液晶屏初始化**************************************/
void Lcdinit(void)
{
cbyte = DISPOFF; /*关闭显示屏*/
WrcmdL(cbyte);
WrcmdR(cbyte);
cbyte = DISPON; /*打开显示屏*/
WrcmdL(cbyte);
WrcmdR(cbyte);
cbyte = DISPFIRST; /*定义显示起始行为零*/
WrcmdL(cbyte);
WrcmdR(cbyte);
Lcdclr(); /*清屏*/
Locatexy();
}
/*********************************制定坐标函数******************************************/
void WR_rowcol(Uchar x,Uchar y)
{row=x;
col=y;
}
/*********************************命令输出到左区控制口*********************************/
void WrcmdL(Uchar X)
{
lcdbusyL(); /*确定分区,返回时保留分区状态不变*/
RS= 0; /*命令操作*/
RW = 0; /*写输出*/
Data= X; /*数据输出到数据口*/
E = 1;_nop_();E= 0; /*读入到LCD*/
}
/*********************************命令输出到右区控制口********************************/
void WrcmdR(Uchar X)
{
lcdbusyR(); /*确定分区,返回时保留分区状态不变*/
RS= 0; /*命令操作*/
RW= 0; /*写输出*/
Data = X; /*命令输出到数据口*/
E = 1;_nop_();E = 0; /*读入到LCM*/
}
/************************分区操作允许等待,返回时保留分区选择状态*************************/
void lcdbusyL(void)
{
CS1 = 1; CS2 = 0; /*置CS1为1,CS2为0,选择左区*/
wtcom(); /*等待使能*/
}
void lcdbusyR(void)
{
CS1= 0; CS2=1; /*置CS1为0,CS2为1,选择右区*/
wtcom(); /*等待使能*/
}
void wtcom(void)
{
RS= 0; /*清零RS*/
RW = 1; /*置RW为1*/
Data = 0xFF;
E= 1;_nop_();
while(Data & Lcdbusy);
E = 0;
}
/************************************清屏,全屏幕清零***********************************/
void Lcdclr( void )
{
for(row=0;row<8;row++)
for(col=0;col<LCDLIMIT;col++) Wrdata(0);
}
/******************根据设定的坐标数据,定位LCD上的下一个操作单元位置******************/
void Locatexy(void)
{ Uchar x,y;
switch (col&0x40) /* col与0xC0*/
{ /*条件分支执行 */
case 0: {lcdbusyL();break;} /*左区*/
case 0x40: {lcdbusyR();break;} /*右区*/
}
x = row&0x07|SETX;
y = col&0x3F|SETY;
wtcom(); /*等待使能*/
RS= 0; /*清零rs */
RW= 0; /*清零RW*/
Data = x;
E= 1;_nop_();E = 0;
wtcom();
RS = 0;
RW= 0;
Data= y;
E = 1;_nop_();E = 0;
}
/*************************************数据写输出/**************************************/
void Wrdata(Uchar X)
{
Locatexy(); /*坐标定位,返回时保留分区状态不变*/
RS= 1; /*数据输出*/
RW = 0; /*写输出*/
Data = X; /*数据输出到数据口*/
E = 1; /*读入到LCD*/
_nop_();
E = 0;
}
/***********************画线,任意方向的斜线,不支持垂直的或水平线***********************/
void Linexy(Uchar posx,Uchar posy,Uchar endx,Uchar endy)
{
Uchar t;
int xerr=0,yerr=0,delta_x,delta_y,distance;
Uchar incx,incy;
WR_rowcol(posx,posy) ;
delta_x=endy-row; /*计算两个方向的距离*/
delta_y=endx-col;
if(delta_x>0) incx=1; /*计算增量方向,增量为0表示既不是垂直线也不是水平线*/
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;
delta_x = cabs( delta_x ); /* 判定哪个距离比较大*/
delta_y = cabs( delta_y );
if( delta_x > delta_y ) distance=delta_x;
else distance=delta_y;
/*开始画线*/
for( t=0;t <= distance+1; t++ ) {
point(row,col);
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 posx,Uchar posy,Uchar length,Uchar XY)
{ Uchar xs,ys;
if(XY==0x00)
xy=0;
else xy=1;
WR_rowcol(posx,posy);
if (xy)
{ys = col;
for (xs=0;xs<length;xs++)
{ col = ys + xs;
point(row,col);}
}
else {xs = row;
for (ys=0;ys<length;ys++)
{
row = xs + ys;
point(row,col);}
}
}
/*****************************************画点******************************************/
void point(Uchar posx,Uchar posy)
{ Uchar x1,y1,x,y;
WR_rowcol(posx,posy);
x1=col;
y1=row;
row=y1>>3; /*取Y方向分页地址*/
Rddata();
y=y1&0x07; /*字节内位置计算*/
x=0x01;
x=x<<y; /*移入所画点*/
Wrdata(cbyte|x); /*画上屏幕*/
col=x1; /*恢复xy坐标*/
row=y1;
}
/**************************************屏幕滚动定位*************************************/
void Rollscreen(Uchar x)
{
cbyte = DISPFIRST|x; /*定义显示起始行为x?*/
WrcmdL(cbyte);
WrcmdR(cbyte);
}
/**************************************一个字串的输出***********************************/
void Putstr(Uchar posx,Uchar posy,Uchar *puts,Uchar i)
{ Uchar j,X;
WR_rowcol(posx,posy);
for (j=0;j<i;j++)
{
X = puts[j];
if (X&0x80)
{
Putcdot(X&0x7f);/*只保留低7位*/
}
else Putedot(X-0x20); /*ascii码表从0x20开始*/
}
}
/*********************************半角字符点阵码数据输出********************************/
void Putedot(Uchar Order)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -