本文作者:林子木
学历有限,如有纰漏敬请见谅!
首先看下12864的绘图显示原理
注意,不要简单的认为12864 是y轴64 x轴128 ;那是点阵的分布,不是读写的分布。
正的如图,y轴32行 从0~31 X轴16 从0~15;0~7为上半屏幕,8~15在下半屏幕
特别注意:X一个地址里面,有两个自己的内容,就是16位的数据
y 和 x的其实地址都是一样0x80,代表0(具体为什么,相见数据手册说明,前面的第8位为规定H,7、6为规定L,5~0为地址输入数值);
现在了解了以上的分布方式,那就简单了嘛,对不?
画一个点,只要找到那个点的x,y坐标不就可以了嘛,对不?
下面是我写的一段画图的代码,全部的文件,会在文章最后给出这里只是一个函数:
/******************************************* 函数名称:Draw_Point 功 能:在整个液晶屏幕上画图 参 数:无 返回值 :无 ********************************************/ void Draw_Point(unsigned char x,unsigned char y) { uint dat = 0; //读取需要写入的两个字节的值 if(x>127) x = 127; if(y>63) y = 63; uchar y_Byte,y_bit,x_Byte,x_bit; y_Byte = y/32; //0:上半屏幕 1:下半屏幕 y_bit = y%32; //y的行号 x_Byte = x/16; //x的列号 x_bit = x%16; //x的位 Write_Cmd(0x34); //打开扩展指令集 Write_Cmd(0x80+31-y_bit); //因为液晶y是从上往下的,这里简单的转换成从下往上 Write_Cmd(0x80+x_Byte+(1-y_Byte)*8);//(1-y_Byte)*8 代表上下半页 if(x_bit>7) //因为是地址是两个字节,但是写入还是一个一个字节的,所以需要判断 { Write_Data(0x00); Write_Data((0x80>>x_bit%8);//因为液晶显示,高位在前 } //如如果想把第八位点亮 直接写0x80 那么会 成100000000 else //而不是我们要的从左到右的 第八位 00000001 所以需要转换下 { Write_Data((0x80>>x_bit%8)); Write_Data(0x00); } Write_Cmd(0x36); //打开绘图显示 Write_Cmd(0x30); //回到基本指令集 } 哈哈,简单吧,不过问题又来了! 什么问题?那就是,简单的这样的话,画一个孤立的点是没为题,可是问题是,如果我要画一条直线就不行了,为什么? 因为,我想吧莫个点点亮,我写入的时候,不知道这个点所在的X轴的地址中的两个字节的内容是否已经有点了,所以我只能将其他位变为0 也就是说,其他位被清零了!纠结呀,这可怎么办呢? 哈哈,还好,记得不,液晶还有读的功能,记住这点就ok了,那就是添加一个读的功能! 代码如下: 红色部分为修改的 /******************************************* 函数名称:Draw_Point 功 能:在整个液晶屏幕上画图 参 数:无 返回值 :无 ********************************************/ void Draw_Point(unsigned char x,unsigned char y) { uint dat = 0; //读取需要写入的两个字节的值 dat = Read_Add(x,y); //注意,因为read 或者 write之后 地址指针AC会自动加+ 想对莫一块进行读和写的工作,就需要重新写入地址 if(x>127) x = 127; if(y>63) y = 63; uchar y_Byte,y_bit,x_Byte,x_bit; y_Byte = y/32; //0:上半屏幕 1:下半屏幕 y_bit = y%32; //y的行号 x_Byte = x/16; //x的列号 x_bit = x%16; //x的位 Write_Cmd(0x34); //打开扩展指令集 Write_Cmd(0x80+31-y_bit); //因为液晶y是从上往下的,这里简单的转换成从下往上 Write_Cmd(0x80+x_Byte+(1-y_Byte)*8);//(1-y_Byte)*8 代表上下半页 if(x_bit>7) //因为是地址是两个字节,但是写入还是一个一个字节的,所以需要判断 { Write_Data(0x00|((dat>>8)&0xff)); Write_Data((0x80>>x_bit%8)|(dat&0xff));//因为液晶显示,高位在前 } //如如果想把第八位点亮 直接写0x80 那么会 成100000000 else //而不是我们要的从左到右的 第八位 00000001 所以需要转换下 { Write_Data((0x80>>x_bit%8)|((dat>>8)&0xff)); Write_Data(0x00|(dat&0xff)); } Write_Cmd(0x36); //打开绘图显示 Write_Cmd(0x30); //回到基本指令集 } 下面贴出具体的读的代码: 注意两个函数的区别 /******************************************* 函数名称:Read_Data 功 能:读取液晶屏幕的值 参 数:无 返回值 :无 ********************************************/ uchar Read_Data(void) { uchar lcdtemp = 0; uchar dat = 0; LCD_RS_L; LCD_RW_H; LCD_DataIn; //设置为输入方式 do //判忙 { LCD_EN_H; _NOP(); lcdtemp = LCD2MCU_Data; LCD_EN_L; } while(lcdtemp & 0x80); LCD_RS_H; //置高 LCD_RW_H; //置高 _NOP(); LCD_EN_H; //使能 _NOP(); dat = LCD2MCU_Data; //读数据 _NOP(); LCD_EN_L; return (dat); } /******************************************* 函数名称:Read_Add 功 能:读取液晶屏幕某一点的值 参 数:无 返回值 :无 ********************************************/ unsigned int Read_Add(unsigned char x,unsigned char y) { unsigned int dat; uchar dat_H = 0,dat_L = 0; if(x>127) x = 127; if(y>63) y = 63; uchar y_Byte,y_bit,x_Byte,x_bit; y_Byte = y/32; //0:上半屏幕 1:下半屏幕 y_bit = y%32; //y的行号 x_Byte = x/16; //x的列号 x_bit = x%16; //x的位 Write_Cmd(0x34); //打开扩展指令集 Write_Cmd(0x36); //打开绘图显示 Write_Cmd(0x80+31-y_bit); Write_Cmd(0x80+x_Byte+(1-y_Byte)*8); Read_Data(); //注意:读操作要先执行有一个空读命令 dat_H = Read_Data(); dat_L = Read_Data(); Write_Cmd(0x30); //回到基本指令集 dat = dat_H*0x0100 + dat_L; return dat; }
由于百度文章的篇幅限制,剩下的代码,将在百度文库中给出,下面是连接地址:
http://wenku.baidu.com/view/25f763748e9951e79b892783.html