我们知道在纸上画出一个点,我们要知道这个点在张纸上面的位置,也就是这个点在这张纸上面的坐标。而在12864上面画点也是一样,我们要先知道这个点在液晶屏上面的坐标,然后我们该坐标点黑或是点白可以了。而在这之前,我们要首先理解12864图形显示坐标。 12864的绘图显示坐标如图所示: 需要注意的是它的水平位址并不是一个点有一个位址的,它是16个格才有一个位址。它的垂直位址也分为上下两半部分。当我们给出位址是X是0,Y是0的时候,其实里面包含了16个点,也就是说我们一次要操作16个点。所有当我们要点亮一个点的时候,我们不仅要知道的位址,还要知道它在这个位址中是第几个位,也就是第几个点。 #include<reg52.h>
#define uint unsigned int #define uchar unsigned char
sbit RS=P2^6; //这个是LCD的数据命令选择端 sbit RW=P2^5; //这个是LCD的写入或是读出选择端 sbit PSB=P3^2; //这个是LCD串行还是并行选择端 sbit RST=P3^4; //这个是LCD的复位端口 sbit LCDE=P2^7; // 这个是LCD的使能端 /* 延时子函数 */ void delay(uint x) { uint y; for(;x>0;x--) for(y=110;y>0;y--); } /* 忙碌检查 */ void lcd_busy() { RS=0; RW=1; P0=0XFF; LCDE=1; delay(2); while((P0&0x80)==0x80); /*如下图1,当LCD忙碌的时候BF位是为1,而我们只需要想知道这位,所有与上0x80,当它是1的时候得到0X80,当它是0的时候得到0.*/ LCDE=0; } /* 写入命令 */ void write_com(uchar com) { lcd_busy(); /*每次操作LCD之前都需要检查一次LCD是否忙碌,不过一般LCD工作比单片机快,所有都不用检查。*/ RS=0; RW=0; LCDE=0; P0=com; delay(1); LCDE=1; delay(3); LCDE=0; } /* 写入数据 */ void write_num(uchar num) { lcd_busy(); RS=1; RW=0; LCDE=0; P0=num; delay(1); LCDE=1; delay(3); LCDE=0; } /* 读取数据 */ uchar read_data() { uchar read; lcd_busy(); RS=1; RW=1; LCDE=0; delay(1); LCDE=1; delay(3); read=P0; LCDE=0; delay(5);;
return read; } /* 画图清屏,由于LCD的清屏指令0X01不能作用在绘图中,所有只能自己写清屏子程序 */ void clear_lcd() { uchar i,j; write_com(0x34); for(i=0;i<32;i++) //因为LCD有纵坐标32格所以写三十二次 { write_com(0x80+i); //先写入纵坐标Y的值 write_com(0x80); //再写入横坐标X的值 for(j=0;j<32;j++) //横坐标有16位,每位写入两个字节的的数据,也就写入32次 { //因为当写入两个字节之后横坐标会自动加1,所以就不用再次写入地址了。 write_num(0x00); } } write_com(0x36); write_com(0x30); } /* 写入一个点的子程序。具体步骤是:计算出X轴、Y轴的地址、X轴中的第几位,然后读出该地址现在的值,因为一般写入新的点的时候,会覆盖掉16个点中其他点,当你要同时显示16个点中的两个点的时候就会冲突,所以先将显示中的点读出来,然后在或上要点亮的点,这样就可以同时点亮。注意读取数据的时候读取的第一个数据不要,从第二数据开始取,也就是说要读取三次,只取后面两次的值。还有就是读取数据之前要先写入你要读取数据的地址,读取数据之后的写入数据还要从新写入地址。最后就是输入数据地址,先输入Y轴,再输入X轴,输入数据。 */ void put_point(uchar x,uchar y) { uint bt=0,read=0; uchar x_adr,y_adr,h_bit,l_bit; y_adr=0x80+y%32; //计算Y轴的地址,应为纵坐标有64个,所有对32求余,当Y大于31时,Y的坐标是下半屏的。 if(y>31) //计算X轴的地址当Y大于31时X的地址在下半屏,从0X88开始,小于31时X的地址是在上半屏,从0X80开始 x_adr=0x88+x/16; else x_adr=0x80+x/16; bt=0x8000>>(x%16); //求这个点到底是在哪个点 write_com(0x34); write_com(0x34); write_com(y_adr); //读取数据的时候要先写入所取数据的地址 write_com(x_adr); read_data(); //读取的第一个字节不要, read=read_data(); //从第二个字节开始接收。 read<<=8; read|=read_data(); bt=bt|read; h_bit=bt>>8; l_bit=bt; write_com(y_adr); //写入点的时候,重新写入地址,因为地址已经改变。 write_com(x_adr); write_num(h_bit); write_num(l_bit); write_com(0x36); //开显示 write_com(0x30); //转回基本指令集 } /* 液晶初始化 */ void lcd_init() { PSB=1; RST=1; write_com(0x30); //基本指令操作 write_com(0x0c); //开显示 write_com(0x01); //清除LCD显示 }
void main() { float i; uchar x,y; lcd_init(); clear_lcd(); while(1) { write_com(0x34); write_com(0x34); write_com(0x80); write_com(0x88); for(i=16;i>0;i--) //画出X轴 { write_num(0xff); } for(i=0;i<64;i++) //画出Y轴 { put_point(0,i); } for(i=0;i<128;i++) { x=i; y=32-x%32; put_point(x,y); } write_com(0x36); write_com(0x30); while(1); }
}
完整代码下载:http://www.51hei.com/bbs/dpj-186495-1.html
|