#ifndef _lcd_h
#define _lcd_h
#include"reg51.h"
#define uchar unsigned char
#define uint unsigned short
//#define port P0
//sbit cd=P2^0;
//sbit rd=P2^1;
//sbit wr=P2^2;
//sbit ce=P2^3;
extern void lcd_init();
extern void lcd_writecom(uchar dat);
extern void sel_big(uchar x,uchar y);
extern void erect(uchar y0,uchar y1,uchar x);
extern void horizontal(uchar x0,uchar x1,uchar y);
extern void graph_mode_writeword(uchar x,uchar y,uchar *dat);
extern void word_byte(uchar row ,uchar list, uchar *pdat);
extern void lcd_writecom_two(uchar onedat,uchar twodat,uchar com);
extern void lcd_writedat_onebyte(uchar onedat,uchar com);
extern void lcd_writedat_nbyte(uchar *dat,uchar len);
extern void clear_point(uchar x,uchar y);
extern void sel_point(uchar x,uchar y);
extern void clr_big(uchar x,uchar y);
extern void draw_circle(int x, int y, int r);
extern void clr_lcd(void);
#endif
#include"lcd.h"
unsigned char pdata *addr;
sbit cd=P2^0;
/**********************************
读取lcd状态
**********************************/
uchar lcd_readcom()
{
uchar temp;
cd=1;
addr = 0xFF;
temp = *addr;
return temp;
}
/*********************************
判断指令/数据读写忙碌状态
*********************************/
void check_busy()
{
uchar temp;
do{
temp=lcd_readcom();
}while((temp&0x03)!=0x03);
}
/*********************************
判断数据自动写忙碌状态
*********************************/
void check_auto_write_busy()
{
uchar temp;
do{
temp=lcd_readcom();
}while((temp&0x08)!=0x08);
}
/*********************************
向lcd写命令
*********************************/
void lcd_writecom(uchar dat)
{
check_busy();
cd=1;
addr = 0xFF;
*addr = dat;
}
/************************************
向lcd写数据
************************************/
void lcd_writedat(uchar dat)
{
check_busy();
cd=0;
addr = 0xFF;
*addr = dat;
}
/********************************
从lcd读数据
*********************************/
uchar lcd_readdat()
{
uchar temp;
cd=0;
addr = 0xFF;
temp = *addr;
return temp;
}
/************************************************
发出命令控制 参数 onedat twodat 命令com
*************************************************/
void lcd_writecom_two(uchar onedat,uchar twodat,uchar com)
{
lcd_writedat(onedat);
lcd_writedat(twodat);
lcd_writecom(com);
}
/****************************************
一次读/写一个数据
****************************************/
void lcd_writedat_onebyte(uchar onedat,uchar com)
{
lcd_writedat(onedat);
lcd_writecom(com);
}
/*uchar lcd_readdat_onebyte(uchar com)
{
uchar dat;
lcd_writedat(com);
dat=lcd_readdat();
return dat;
}*/
/****************************************
一次写n个数据
****************************************/
void lcd_writedat_nbyte(uchar *dat,uchar len)
{
lcd_writecom(0xb0);
check_auto_write_busy();
while(len)
{
lcd_writedat(*dat);
dat++;
len--;
}
lcd_writecom(0xb2);
}
/************************************************
清除一个点坐标 X,Y 左上角第一个点为0,0
************************************************/
void clear_point(uchar x,uchar y)
{
uint addr;
uchar temp1,temp2;
addr=y*30+(x>>3);//32+8
temp1=addr&0x00ff;
temp2=addr>>8;
lcd_writecom_two(temp1,temp2,0x24);
lcd_writecom(0xf7-(x&0x07));
}
/************************************************
点亮一个点 坐标 X,Y 左上角第一个点为0,0
************************************************/
void sel_point(uchar x,uchar y)
{
uint addr;
uchar temp1,temp2;
addr=y*30+(x>>3);//32+8
temp1=addr&0x00ff;
temp2=addr>>8;
lcd_writecom_two(temp1,temp2,0x24);
lcd_writecom(0xff-(x&0x07));
}
void clr_lcd(void)
{
unsigned int len ;
len=30<<7;
lcd_writecom_two(0,0x00,0x24);
lcd_writecom(0xb0);
check_auto_write_busy();
while(len)
{
lcd_writedat(0x00);
len--;
}
lcd_writecom(0xb2);
}
/*sel_big(uchar x,uchar y)
{
uint addr;
uchar temp1,temp2,n;
addr=y*160+(x>>1);//x/8*4;
for(n=0;n<4;n++)
{
temp1=addr%256;
temp2=addr>>8;
lcd_writecom_two(temp1,temp2,0x24);
if(x%2)
{
lcd_writecom(0xfb);
lcd_writecom(0xfa);
lcd_writecom(0xf9);
lcd_writecom(0xf8);
}
else
{
lcd_writecom(0xff);
lcd_writecom(0xfe);
lcd_writecom(0xfd);
lcd_writecom(0xfc);
}
addr+=40;
}
}*/
void sel_big(uchar x,uchar y)
{
uint addr;
uchar temp1,temp2,n;
addr=y*240+(x);//x/8*4;y*320=y*(256+64)=(y<<8)+(y<<6)
for(n=0;n<8;n++)
{
temp1=addr&0x00ff;//addr%256
temp2=addr>>8;
lcd_writecom_two(temp1,temp2,0x24);
lcd_writecom(0xfb);
lcd_writecom(0xfa);
lcd_writecom(0xf9);
lcd_writecom(0xf8);
lcd_writecom(0xff);
lcd_writecom(0xfe);
lcd_writecom(0xfd);
lcd_writecom(0xfc);
addr+=30;
}
}
void clr_big(uchar x,uchar y)
{
uint addr;
uchar temp1,temp2,n;
addr=y*240+(x);//x/8*4;y*320=y*(256+64)=(y<<8)+(y<<6)
for(n=0;n<8;n++)
{
temp1=addr&0x00ff;//addr%256
temp2=addr>>8;
lcd_writecom_two(temp1,temp2,0x24);
lcd_writecom(0xf3);
lcd_writecom(0xf2);
lcd_writecom(0xf1);
lcd_writecom(0xf0);
lcd_writecom(0xf7);
lcd_writecom(0xf6);
lcd_writecom(0xf5);
lcd_writecom(0xf4);
addr+=30;
}
}
void graph_mode_writeword(uchar x,uchar y,uchar *dat)
{
uint addr;
uint temp1; //4
uchar n;
temp1=y;temp1=temp1*480;//512+128 640
addr=temp1+2*x;
for(n=0;n<16;n++)
{
lcd_writecom_two((addr&0x00ff),(addr>>8),0x24);
lcd_writedat_onebyte(*dat,0xc0);
dat++;
lcd_writedat_onebyte(*dat,0xc4);
dat++;
addr=addr+30;
}
}
void word_byte(uchar row ,uchar list, uchar *pdat)
{
uchar addr_h,addr_l,n;
uint p_addr;
for(n=0;n<16;n++)
{
p_addr=(list+n)*30+row;
addr_h=p_addr>>8;
addr_l=p_addr%256;
lcd_writecom_two(addr_l,addr_h,0x24);
lcd_writecom(0xb0);
lcd_writedat(*(pdat+n));
lcd_writecom(0xb2);
}
}
void horizontal(uchar x0,uchar x1,uchar y)
{
uchar temp,n;
if(x0>x1)
{
temp=x0;
x0=x1;
x1=temp;
}
n=x1-x0;
for(;n>0;n--)
{
sel_point(x0+n,y);
}
}
void erect(uchar y0,uchar y1,uchar x)
{
uchar temp,n;
if(y0>y1)
{
temp=y0;
y0=y1;
y1=temp;
}
n=y1-y0;
for(;n>0;n--)
{
sel_point(x,y0+n);
}
}
void Draw_line(uchar x0,uchar y0,uchar x1,uchar y1)
{
int dx,dy; //定义X.Y轴上增加的变量值
int sub;
int temp; //起点、终点大小比较,交换数据时的中间变量
uchar flag;
if(x0>x1) //X轴上,起点大于终点,交换数据
{
temp=x1;
x1=x0;
x0=temp;
temp=y1;
y1=y0;
y0=temp;
}
dx=x1-x0; //X轴方向上的增量
dy=y1-y0; //Y轴方向上的增量
if(dx==0)
//Draw_shu(x0,y0,y1);
erect(y0,y1,x0);
if(dy==0)
//Draw_zhi(x0,x1,y0);
horizontal(x0,x1,y0);
if(dy>0)
flag=1;
else
flag=0;
if((dx!=0)&&(dy!=0))
{
// 布兰森汉姆(Bresenham)算法画线 /
if(flag==1)
{
if(dx>=dy) //靠近X轴
{
sub=2*dy-dx; //计算下个点的位置
while(x0!=x1)
{
sel_point(x0,y0); //画起点
x0++; // X轴上加1
if(sub>0) // 判断下下个点的位置
{
y0++; // 为右上相邻点,即(x0+1,y0+1)
sub+=2*dy-2*dx;
}
else
sub+=2*dy; // 判断下下个点的位置
}
sel_point(x0,y0);
}
else
{
sub=2*dy-dx; //靠近Y轴
while(y0!=y1)
{
sel_point(x0,y0); //画起点
y0++;
if(sub>0) //判断下下个点的位置
{
x0++;
sub+=2*dx-2*dy;
}
else
sub+=2*dx;
}
sel_point(x0,y0);
}
}
else
{
dy=y0-y1;
if(dx>=dy) //靠近X轴
{
sub=2*dy-dx; //计算下个点的位置
while(x0!=x1)
{
sel_point(x0,y0); //画起点
x0++; // X轴上加1
if(sub>0) // 判断下下个点的位置
{
y0--; // 为右上相邻点,即(x0+1,y0+1)
sub+=2*dy-2*dx;
}
else
sub+=2*dy; // 判断下下个点的位置
}
sel_point(x0,y0);
}
else
{
sub=2*dx-dy; //靠近Y轴
while(y0!=y1)
{
sel_point(x0,y0); //画起点
y0--;
if(sub>0) //判断下下个点的位置
{
x0++;
sub+=2*dx-2*dy;
}
else
sub+=2*dx;
}
sel_point(x0,y0);
}
}
}
}
void draw_circle(int x, int y, int r)
{
int a, b, num;
a = 0;
b = r;
while(2 * b * b >= r * r) // 1/8圆即可
{
sel_point(x + a, y - b); // 0~1
sel_point(x - a, y - b); // 0~7
sel_point(x - a, y + b); // 4~5
sel_point(x + a, y + b); // 4~3
sel_point(x + b, y + a); // 2~3
sel_point(x + b, y - a); // 2~1
sel_point(x - b, y - a); // 6~7
sel_point(x - b, y + a); // 6~5
a++;
num = (a * a + b * b) - r*r;
if(num > 0)
{
b--;
a--;
}
}
}
void lcd_init()
{
lcd_writecom_two(0x00,0x00,0x24);
lcd_writecom_two(0x01,0x01,0x21);
lcd_writecom_two(0x00,0x00,0x42);
lcd_writecom_two(0x1e,0x00,0x43);
lcd_writecom_two(0x00,0x10,0x40);
lcd_writecom_two(0x1e,0x00,0x41);
lcd_writecom(0xa0);
lcd_writecom(0x9c);
lcd_writecom(0x80);
}
#include"lcd.h"
main()
{
lcd_init();
draw_circle(120, 64, 60);
while(1);
}