#include<reg52.h>
#include<intrins.h>
#include<math.h >
#define uchar unsigned char
#define uint unsigned int
#define date_12864 P0
#define nop _nop_()
sbit RS = P2^5; //并
sbit RW = P2^6; //并
sbit EN = P2^7; //并
//sbit BUSY=P0^7; //并
//sbit PSB = P0^1; //串并选择信号
//sbit RST = P0^0; //复位信号
void write_date12864(uchar date); //送数据
uchar LCD_ram_date();
void Draw_point(uchar X_add,uchar Y_add,uchar flag);
void Draw_point(uchar X_add,uchar Y_add,uchar State);
uchar ram_date[2]={0x00,0x00};
uchar vDATA_SET[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};//画点
uchar vDATA_CLR[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//清除点
/********************************************************
函数功能: LCM12864写指令和数据
入口参数:
出口参数: bf 忙标志
********************检忙******************************/
void Parallel_Check_Busy(void) //读指令时候测忙
{
date_12864 = 0xff; //输入前置1
RS=0; //指令
RW=1; //读模式
EN=1; //使能
while(BUSY);//等待不忙
EN=0;
}
/*******************送指令*************************/
void write_com12864(uchar com)
{
Parallel_Check_Busy();
RS=0;
RW=0;
date_12864=com;
EN=1;
EN=0;
}
/*******************送数据********************/
void write_date12864(uchar date)
{
Parallel_Check_Busy();
RS=1;
RW=0;
date_12864=date;
EN=1;
EN=0;
}
/*******************液晶初始化******************/
void init()
{
write_com12864(0x30); //基本指令集功能设定
write_com12864(0x0c); //显示开关
write_com12864(0x01); //清屏指令
write_com12864(0x06); //进入点设定
}
/********************清绘图********************/
void clear_display() //要遵守先送垂直地址!再送水平地址!
{
uchar i,j;
write_com12864(0x34);//扩展指令集,先关闭图形显示功能
for(j=0;j<32;j++) //清除上半屏
{
for(i=0;i<8;i++)
{
write_com12864(0x80+j);//设定垂直坐标y轴0~31行
write_com12864(0x80+i);//设定水平坐标x轴8*8就是8个字节每个字节8位共64个点
write_date12864(0x00); //放入高字节
write_date12864(0x00); //放入低字节
}
}
for(j=32;j<64;j++)//清除下半屏
{
for(i=8;i<16;i++)
{
write_com12864(0x80+j-32);//设定垂直坐标Y32~63
write_com12864(0x80+i);//设定水平坐标X 8*8就是8个字节每个字节8位共64个点
write_date12864(0x00);//放入高位字节D15---D8
write_date12864(0x00);//放入低位字节D7----D0
}
}
write_com12864(0x36);//开绘图显示
}
/***********************读RAM******************************/
uchar LCD_read_arm() //其实都是和那个时序图没什么区别,只是在
{ //读取数据的时候要有一个预读取,相当于读取两次
uchar ram_date=0;
Parallel_Check_Busy(); //测忙
date_12864=0xff;
RS=1;
RW=1;
EN=0;
EN=1;
ram_date=date_12864;
EN=0;
return(ram_date);
}
/*****************************************************************************************
函数名称:void LCD_Draw_Dot(unsigned char X_add,unsigned char Y_add,unsigned char State)
函数功能:在(x,y)处绘制一个点或清除一个点
形式参数:unsigned char X_add,unsigned char Y_add,unsigned char State
行参说明:x轴坐标,y轴坐标,要画的点或要清除的点
返回参数:无
使用说明:此函数适用于 12864型液晶
x: 取值范围:0~127
y: 取值范围:0~63 (针对 12864型液晶)
State:取值范围,1画点;0清
液晶屏坐标说明:
----------------------------------------------------------------------------
|(0,0) (1,0),(2,0),(3,0), (127,0)|
|(0,1) (1,1),(2,1),(3,1), (127,1)|
|(0,2) (1,2) (127,2)|
| |
|(0,63),(1,63), (127,63)|
----------------------------------------------------------------------------
*****************************************************************************************/
void Draw_point(uchar X_add,uchar Y_add,uchar flag) //通过
{
unsigned char X_temp,X_count;
unsigned char LCD_X,LCD_Y;//重新定义的新坐标
X_temp=X_add;
X_count=0x00;
while(X_temp>15)//X_add加够1个字节,又从0开始0~15一个循环。
{
X_count++;//0~7,8个字,分上下屏16*8.X轴在此功能不再自加
X_temp=X_temp-16; //0~127
}
if(X_temp<=15)
{
if(Y_add<32)
{
LCD_X=0x80+X_count;
LCD_Y=0x80+Y_add;
}
else
{
LCD_X=0x88+X_count;
LCD_Y=0x80+Y_add-32;//下半屏
}
write_com12864(0x34);//关闭绘图
write_com12864(LCD_Y);
write_com12864(LCD_X);//把地址写过去
write_com12864(0x30);//功能设定
LCD_read_arm(); //读ram
ram_date[0]=LCD_read_arm();//前8格 //一个汉字有两个字节,防止重复打点
ram_date[1]=LCD_read_arm();//后8格
if(X_temp<8)
{
write_com12864(0x34);//关闭绘图
write_com12864(LCD_Y);
write_com12864(LCD_X);//把地址写过去
write_com12864(0x30);//功能设定
if(flag)
{
write_date12864(ram_date[0]|vDATA_SET[X_temp]);//点亮
write_com12864(0x36);
}
else
{
write_date12864(ram_date[0]&vDATA_CLR[X_temp]);//qingdian
write_com12864(0x36);
}
}
else
{
write_com12864(0x34);//关闭绘图
write_com12864(LCD_Y);
write_com12864(LCD_X);//把地址写过去
write_com12864(0x30);//功能设定
if(flag)
{
write_date12864(ram_date[0]);
write_date12864(ram_date[1]|vDATA_SET[X_temp-8]);//点亮
write_com12864(0x36);
}
else
{
write_date12864(ram_date[0]);
write_date12864(ram_date[1]&vDATA_CLR[X_temp-8]);//清点
write_com12864(0x36);
}
}
}
}
/****************************************************************************************
函数名称:void LCD_Draw_Dot_Adjust(unsigned char X_add,unsigned char Y_add,unsigned char State)
函数功能:在(x,y)处绘制一个点或清除一个点,对坐标轴的方向经过了调整
形式参数:unsigned char X_add,unsigned char Y_add,unsigned char State
行参说明:x轴坐标,y轴坐标,要画的点或要清除的点
返回参数:无
使用说明:此函数适用于 12864型液晶
X_add: 取值范围:0~127
Y_add: 取值范围:0~63 (针对12864型液晶)
State:取值范围,1画点;0清点
经过调整的液晶屏坐标如下:
|(0,63) (127,63) |
|(0,62) (127,62) |
| |
| |
|(0,0),(,1,0),(2,0) (127,0) |
*********************************************************************************************/
/*void LCD_Draw_Dot_Adjust(uchar X_add,uchar Y_add,uchar State)
{
unsigned char Y_temp=0x00; //可要可不要,作用是将(x,y)变成(x,63-y)
Y_temp=63-Y_add;
Draw_point(X_add, Y_temp,State);
} */
/**********************************************************************
函数名称:void LCD_Draw_Two_Dot(uchar x1,uchar y1,uchar x2,uchar y2)
函数功能:任意两点画直线
形式参数:uchar x1, uchar y1, uchar x2, uchar y2
行参说明:X 0~127 Y 0~63 针对12864写的
返回参数: 无
使用说明:x1,y1定第一点,x2,y2定第一点
*********************************************************************/
void LCD_Draw_Two_Dot(uchar x1,uchar y1,uchar x2,uchar y2)//已通过
{ //LCD_Draw_Two_Dot((xn,yn),(xi,yi));
unsigned int x,y; //两点 (x1,y1).(x2,y2)
unsigned int d_x,d_y; //d_x=x2-x1; d_y=y2-y1;
unsigned char temp=0;
int err=0;
if(y1>y2) //x1与x2交换,y1与y2交换
{
x =x1; y =y1;
x1=x2; y1=y2;
x2= x; y2= y;
}
d_y=y2-y1;
if (d_y==0)
{
if(x1>x2) { x=x1; x1=x2; x2=x; }
for ( x=x1;x<=x2;x++ ) { Draw_point(x,y1,1); }
}
else
{
if(x2>=x1) { temp=1; d_x=x2-x1; }
else { d_x=x1-x2; }
x=x1; y=y1;
Draw_point(x,y,1);
if(temp&&(d_y<=d_x))
{
while(x!=x2)
{
if(err<0) { x=x+1;err=err+(y2-y); }
else
{