#include"lcd12864.h"
sbit LCD12864_RS=P3^5; //寄存器选择输入
sbit LCD12864_RW=P3^6; //液晶读/写控制
sbit LCD12864_EN=P3^4; //液晶使能控制
sbit LCD12864_PSB=P3^7; //串/并方式控制
unsigned char code tab1[1024];
bit lcd12864_busy() //判断是否忙
{
bit result;
LCD12864_RS=0;
LCD12864_RW=1;
LCD12864_EN=1;
delay_us(6);
result = (bit)(P0&0x80); //为1,不接受任何指令和数据
LCD12864_EN = 0;
return(result);
}
void lcd12864_write_cmd(unsigned char cmd) //写指令
{
while(lcd12864_busy());
LCD12864_RS = 0;
LCD12864_RW = 0;
LCD12864_EN = 0;
_nop_();
_nop_();
P0 = cmd;
delay_us(6);
LCD12864_EN = 1;
delay_us(6);
LCD12864_EN = 0;
}
void lcd12864_write_dat(unsigned char dat) //写数据
{
while(lcd12864_busy());
LCD12864_RS = 1;
LCD12864_RW = 0;
LCD12864_EN = 0;
P0 = dat;
delay_us(6);
LCD12864_EN = 1;
delay_us(6);
LCD12864_EN = 0;
}
unsigned char lcd12864_read_dat()
{
unsigned char shuju;
lcd12864_busy();
P0=0xff;
LCD12864_RS = 1;
LCD12864_RW = 1;
LCD12864_EN = 0;
delay_us(6);
LCD12864_EN = 1;
shuju = P0;
delay_us(6);
LCD12864_EN=0;
return(shuju);
}
void lcd12864_init()
{
LCD12864_PSB = 1; //并口方式
lcd12864_write_cmd(0x30); //基本指令操作
delay_ms(5);
lcd12864_write_cmd(0x0C); //显示开,关光标
delay_ms(5);
lcd12864_write_cmd(0x01); //清除LCD的显示内容
delay_ms(5);
}
void lcd12864_print(uchar X,uchar Y) //设定显示位置
{
uchar pos;
if (X==0)
{X=0x80;}
else if (X==1)
{X=0x90;}
else if (X==2)
{X=0x88;}
else if (X==3)
{X=0x98;}
pos = X+Y ;
lcd12864_write_cmd(pos); //显示地址
}
/*字符显示函数*/
void lcd12864_dis_str(unsigned char x,unsigned char y,unsigned char *str)
{
lcd12864_print(x,y); //设置显示位置
while(*str!= '\0') //显示字符
{
lcd12864_write_dat(*str);
str++;
}
}
/*数值显示函数*/
void lcd12864_dis_dat(unsigned char x,unsigned char y,int dat,unsigned char length)
{
unsigned char dat1;
lcd12864_print(x,y); //设置显示位置
if(dat<0)
{
lcd12864_write_dat('-');
dat=-dat;
}
else
lcd12864_write_dat(' ');
dat1=dat/10000;
if(length>4)
lcd12864_write_dat(dat1+0x30);
dat1=dat/1000%10;
if(length>3)
lcd12864_write_dat(dat1+0x30);
dat1=dat/100%10;
if(length>2)
lcd12864_write_dat(dat1+0x30);
dat1=dat/10%10;
if(length>1)
lcd12864_write_dat(dat1+0x30);
dat1=dat%10;
lcd12864_write_dat(dat1+0x30);
}
/*绘图显示函数*/
void lcd12864_huitu(unsigned char *address) //绘图显示
{
unsigned char i,j,k,n=0x80;
lcd12864_write_cmd(0x34); //打开扩展指令集
for(i=0;i<2;i++)
{
for(j=0;j<32;j++)
{
lcd12864_write_cmd(0x80+j);
lcd12864_write_cmd(n);
for(k=0;k<16;k++)
{
lcd12864_write_dat(0x00);
}
}
n=0x88;
}
lcd12864_write_cmd(0x36); //打开绘图显示
lcd12864_write_cmd(0x30); //回到基本指令集
n=0x80;
lcd12864_write_cmd(0x34); //打开扩展指令集
for(i=0;i<2;i++)
{
for(j=0;j<32;j++)
{
lcd12864_write_cmd(0x80+j);
lcd12864_write_cmd(n);
for(k=0;k<16;k++)
{
lcd12864_write_dat(*address++);
}
}
n=0x88;
}
lcd12864_write_cmd(0x36); //打开绘图显示
lcd12864_write_cmd(0x30); //回到基本指令集
}
void lcd12864_clear() //打点前清除绘图数据
{
lcd12864_huitu(tab1);
}
/*画点函数*/
//左上角为(0,0),右下角为(63,127)
//type:0为白色;1 为黑色,2为取反
void lcd12864_drawdot(unsigned char x,unsigned char y,unsigned char type)
{
unsigned char X,Y,k; //X存储行地址,Y存储列地址,k存储点在字中的位置从左至右为0~15
unsigned char DH,DL; //存放读出数据的高字节和低字节
lcd12864_write_cmd(0x34); //扩展指令
lcd12864_write_cmd(0x36); //扩展指令加绘图模块
if(y >= 0 && y <= 63 && x >= 0 && x <= 127) //确定所画点的地址行与列地址
{
if(y < 32)
{
X = 0x80 + (x >> 4);
Y = 0x80 + y;
}
else
{
X = 0x88 + (x >> 4);
Y = 0x80 + (y - 32);
}
lcd12864_write_cmd(Y); //写入所确定的点的行位地址
lcd12864_write_cmd(X); //写入所确定的点的列字地址
lcd12864_read_dat(); //假读
DH = lcd12864_read_dat(); //读高字节
DL = lcd12864_read_dat(); //读低字节
k = x % 16; //余数为点在字中的位置
switch(type) //画点类型,1黑、0白、2取反
{
case 0:
if(k < 8) //点在高字节
DH &= ~(0x01 << (7 - k)); //修改该点同时保持其他位不变
else //点在低字节
DL &= ~(0x01 << (7 - (k % 8))); //修改该点同时保持其他位不变
break;
case 1:
if(k < 8)
DH |= (0x01 << (7 - k)); //修改该点同时保持其他位不变
else
DL |= (0x01 << (7 - (k % 8))); //修改该点同时保持其他位不变
break;
case 2:
if(k < 8)
DH ^= (0x01 << (7 - k)); //修改该点同时保持其他位不变
else
DL ^= (0x01 << (7 - (k % 8))); //修改该点同时保持其他位不变
break;
default: break;
}
lcd12864_write_cmd(Y); //写行位地址
lcd12864_write_cmd(X); //写列字地址
lcd12864_write_dat(DH); //将高字节数据写回
lcd12864_write_dat(DL); //将低字节数据写回
lcd12864_write_cmd(0x30); //转回普通指令
}
}
/*画水平线*/
//(x0,y0):水平线的起点;(x1,y0):水平线的终点
//color=1:点亮;color=0:擦除
void lcd12864_drawRowLine(unsigned char y0,unsigned char x0,unsigned char x1,unsigned char color)
{
unsigned char temp;
if(x0>x1) // 对x0、x1大小进行排列,以便画图
{
temp = x1;
x1 = x0;
x0 = temp;
}
do
{
lcd12864_drawdot(x0, y0, color); // 逐点显示,描出垂直线
x0++;
}
while(x1>=x0);
}
/*画竖直线*/
//(x0,y0):竖直线的起点;(x1,y0)竖直线的终点;
//color=1:点亮;color=0:擦除
void lcd12864_drawCollumLine(unsigned char x0,unsigned char y0,unsigned char y1,unsigned char color)
{
unsigned char temp;
if(y0>y1)
{
temp=y0;
y0=y1;
y1=temp;
}
while (y0<=y1)
{
lcd12864_drawdot(x0,y0,color);
y0++;
}
}
/*画任意两点间的直线*/
//(x0,y0):竖直线的起点;(x1,y1):竖直线的终点
//color=1:点亮;color=0:擦除
void lcd12864_drawLine(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char color)
{
int dx,dy; // 直线x,y轴差值变量
char dx_sym,dy_sym; // x,y轴增长方向,为-1时减值方向,为1时增值方向
int dx_2,dy_2; // dx*2,dy*2值变量,用于加快运算速度
int di; // 决策变量
dx = x1-x0; // 求取两点之间的差值
dy = y1-y0;
if (dx<0)
dx_sym=-1;
else
{
if(dx>0)
dx_sym=1;
else
{
lcd12864_drawCollumLine(x0,y0,y1,color);
return;
}
}
if(dy>0)
dy_sym=1;
else
{
if(dy<0)
dy_sym=-1;
else
{
lcd12864_drawRowLine(x0,y0,x1,color);
return;
}
}
dx=dx_sym*dx;
dy=dy_sym*dy;
dx_2=dx*2;
dy_2=dy*2;
if(dx>=dy)
{
di=dy_2-dx;
while(x0!=x1)
{
lcd12864_drawdot(x0,y0,color);
x0+=dx_sym;
if(di<0)
di+=dy_2;
else
di+=dy_2-dx_2;y0+=dy_sym;
}
lcd12864_drawdot(x0,y0,color);
}
else
{
di=dx_2-dy;
while(y0!=y1)
{
lcd12864_drawdot(x0,y0,color);
y0+=dy_sym;
if(di<0)
di+=dx_2;
else
di+=dx_2-dy_2;x0+=dx_sym;
}
lcd12864_drawdot(x0,y0,color);
}
}
评论2