#include
void delayu()
{
_nop_();
}
//延时a * 1ms
void delaym(uint a)
{
uint i, j;
for(i = a; i > 0; i--)
for(j = 110; j > 0; j--);
}
//检测LCD是否处于忙状态, 若忙返回1, 空闲返回0 bit checkBusy()
{
bit busy;
RS = 0;
RW = 1;
E = 1;
delayu();
busy = (bit)(LCD_DA TA&0x80);
E = 0;
return busy ;
}
//等待LCD到空闲
void wait()
{
while(checkBusy());
}
//写命令
void write_com(uchar cmd)
{
wait();
RS = 0;
RW = 0;
E = 0;
LCD_DATA = cmd;
delayu();
E = 1;
E = 0;
}
//写数据
void write_data(uchar dat)
{
wait();
RS = 1;
RW = 0;
E = 0;
LCD_DATA = dat;
delayu();
E = 1;
E = 0;
}
//读数据
uchar read_data(void)
{
uchar dsp_data;
wait();
LCD_DATA=0xFF;
RS = 1;
RW = 1;
E=0;
E=1;
delayu();
dsp_data=LCD_DA TA;
E = 0;
return(dsp_data);
}
//初始化LCD
void init()
{
write_com(0x30); //基本指令, 扩充指令为34H write_com(0x0c); //显示开, 关光标
write_com(0x01); //清屏
delaym(10);
}
void setPosition(uchar x, uchar y)
{
uchar p;
switch(y%4)
{
case 0: p = 0x80; break; //第一行开始地址
case 1: p = 0x90; break; //第二行
case 2: p = 0x88; break; //第三行
case 3: p = 0x98; break; //第四行
}
p += x;
write_com(p);
}
void writestring(uchar * str)
{
uchar i = 0;
while(str[i] != '\0')
{
write_data(str[i++]);
}
}
void lcd_DisplayImage(unsigned char *str)
{
unsigned char i;
unsigned char j;
unsigned char k;
unsigned char bGDRAMAddrX = 0x80; //GDRAM水平地址
unsigned char bGDRAMAddrY = 0x80; //GDRAM垂直地址
for(i = 0; i < 2; i++) // 在绘图GDRAM中写满屏图片数据
{
for(j = 0; j < 32; j++)
{
for(k = 0; k < 8; k++)
{
write_com(0x34);
write_com(bGDRAMAddrY + j);//垂直地址
write_com(bGDRAMAddrX + k);//水平地址
write_com(0x30);
write_data(*str++);
write_data(*str++);
}
}
bGDRAMAddrX = 0x88;
}
write_com(0x36);
write_com(0x30);
}
//任意坐标写汉字
void write_sfm(uchar x,uchar y,uchar date)
{
uchar shi,ge;
shi=date/10;
ge=date%10;
switch(y)
{
case 0:
{
write_com(0x80+x);
write_data(0x30+shi);
write_data(0x30+ge);
}break;
case 1:
{
write_com(0x90+x);
write_data(0x30+shi);
write_data(0x30+ge);
}break;
case 2:
{
write_com(0x88+x);
write_data(0x30+shi);
write_data(0x30+ge);
}break;
case 3:
{
write_com(0x98+x);
write_data(0x30+shi);
write_data(0x30+ge);
}break;
}
}
//*************点显示子程序************************
//*** 0<=x<=127表示横坐标,0<=y<=63表示纵坐标colour=0表示删除点colour=1表示现实点
void lcd_DisplayDot(uchar x,uchar y,uchar colour)
{
uchar i,j,l,h,h1,l1;
uint k=0x01;
unsigned char bGDRAMAddrX = 0x80; //GDRAM水平地址
unsigned char bGDRAMAddrY = 0x80;
if(y>31)
{
y-=32;
bGDRAMAddrX = 0x88;
}
i=x/16;
j=15-(x%16);
k=k<>8);
write_com(0x34);
write_com(bGDRAMAddrY + y);//垂直地址
write_com(bGDRAMAddrX + i);//水平地址
write_com(0x30);
read_data();
h1=read_data();
l1=read_data();
write_com(0x34);
write_com(bGDRAMAddrY + y);//垂直地址
write_com(bGDRAMAddrX + i);//水平地址
write_com(0x30);
if(colour==0)
{
write_data((~h)&h1);write_data((~l)|l1);
}
else
{
write_data(h|h1);write_data(l|l1);
}
write_com(0x36);
write_com(0x30);
}
//画横直线
void lcd_DisplayHLine(unsigned char x0, unsigned char x1, unsigned char y, unsigned char color) {
unsigned char bak;
if(x0>x1) // 对x0、x1大小进行排列,以便画图
{
bak = x1;
x1 = x0;
x0 = bak;
}
do
{
lcd_DisplayDot(x0, y, color); // 从左到右逐点显示,描出垂直线
x0++;
}while(x1>=x0);
}
//画纵直线
void lcd_DisplayRLine(unsigned char x, unsigned char y0, unsigned char y1, unsigned char color) {
unsigned char bak;
if(y0>y1) // 对y0、y1大小进行排列,以便画图
{
bak = y1;
y1 = y0;
y0 = bak;
}
do
{
lcd_DisplayDot(x, y0, color); // 从上到下逐点显示,描出垂直线
y0++;
}while(y1>=y0);
}
//画任意一直线
void lcd_DisplayLine(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char color)
{
unsigned char bak;
char dx; // 直线x轴差值变量
char dy; // 直线y轴差值变量
char dx_sym; // x轴增长方向,为-1时减值方向,为1时增值方向
char dy_sym; // y轴增长方向,为-1时减值方向,为1时增值方向
char dx_x2; // dx*2值变量,用于加快运算速度
char dy_x2; // dy*2值变量,用于加快运算速度
char di; // 决策变量
dx = x1-x0; // 求取两点之间的差值
dy = y1-y0;
if(x0==x1) //判断是否为垂直线
{
lcd_DisplayRLine(x0,y0,y1,color); //画垂直线
return;
}
if(y0==y1) //判断是否为水平线
{
lcd_DisplayHLine(x0,x1,y0,color); //画水平线
return;
}
dx = x1-x0; // 求取两点之间的差值
dy = y1-y0;
/* 判断增长方向,或是否为水平线、垂直线、点*/
if(dx>0) // 判断x轴方向
{
dx_sym = 1; // dx>0,设置dx_sym=1
}
else
{
if(dx<0)
{
dx_sym = -1; // dx<0,设置dx_sym=-1 }
else
{
// dx==0,画垂直线,或一点
lcd_DisplayRLine(x0, y0, y1, color);
return;
}
}
if(dy>0) // 判断y轴方向
{
dy_sym = 1; // dy>0,设置dy_sym=1
}
else
{
if(dy<0)
{
dy_sym = -1; // dy<0,设置dy_sym=-1 }
else
{
// dy==0,画水平线,或一点
lcd_DisplayHLine(x0, y0, x1, color);
return;
}
}
/* 将dx、dy取绝对值*/
dx = dx_sym * dx;
dy = dy_sym * dy;
/* 计算2倍的dx及dy值*/
dx_x2 = dx*2;
dy_x2 = dy*2;
/* 使用Bresenham法进行画直线*/
if(dx>=dy) // 对于dx>=dy,则使用x轴为基准{
di = dy_x2 - dx;
while(x0!=x1)
{
lcd_DisplayDot(x0, y0, color);
x0 += dx_sym;
if(di<0)
{
di += dy_x2; // 计算出下一步的决策值
}
else
{
di += dy_x2 - dx_x2;
y0 += dy_sym;
}
}
lcd_DisplayDot(x0, y0, color); // 显示最后一点
}
else // 对于dxx1) // 若x0>x1,则x0与x1交换
{
i = x0;
x0 = x1;
x1 = i;
}
if(y0>y1) // 若y0>y1,则y0与y1交换
{
i = y0;
y0 = y1;
y1 = i;
}
//判断是否只是直线
if(y0==y1)
{
lcd_DisplayHLine(x0,x1,y0,color);
return;
}
if(x0==x1)
{
lcd_DisplayRLine(x0,y0,y1,color);
return;
}
while(y0<=y1)
{
lcd_DisplayHLine(x0,x1,y0,color); // 当前画水平线
y0++; // 下一行
}
}
//画圆函数
void lcd_DisplayCircle(unsigned char x0,unsigned char y0,unsigned char r,unsigned char color) {
char a,b;
char di;
if(r>31 ||r==0) return; //参数过滤,次液晶显示的最大圆半径为31
a=0;
b=r;
di=3-2*r; //判断下个点位置的标志
while(a<=b)
{
lcd_DisplayDot(x0-b,y0-a,color); //3
lcd_DisplayDot(x0+b,y0-a,color); //0
lcd_DisplayDot(x0-a,y0+b,color); //1
lcd_DisplayDot(x0-b,y0-a,color); //7
lcd_DisplayDot(x0-a,y0-b,color); //2
lcd_DisplayDot(x0+b,y0+a,color); //4
lcd_DisplayDot(x0+a,y0-b,color); //5
lcd_DisplayDot(x0+a,y0+b,color); //6
lcd_DisplayDot(x0-b,y0+a,color);
a++;
/***使用Bresenham算法画圆**/
if(di<0)
di +=4*a+6;
else
{
di +=10+4*(a-b);
b--;
}
lcd_DisplayDot(x0+a,y0+b,color);
}
}