您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 其它行业文档 > 玩转12864液晶屏(ST7920)
在我们常用的人机交互显示界面中,除了数码管,LED,以及我们之前已经提到的LCD1602之外,还有一种液晶屏用的比较多。相信接触过单片机的朋友都知道了,那就是12864液晶。顾名思义,12864表示其横向可以显示128个点,纵向可以显示64个点。我们常用的12864液晶模块中有带字库的,也有不带字库的,其控制芯片也有很多种,如KS0108T6963,ST7920等等。在这里我们以ST7920为主控芯片的12864液晶屏来学习如何去驱动它。(液晶屏采用金鹏的OCMJ4X8C)关于这个液晶屏的更多信息,请参考它的DATASHEET,附件中有下载。我们先来了解一下它的并行连接情况。下面是电路连接图从上面的图可以看出,液晶模块和单片机的连接除了P0口的8位并行数据线之外,还有RS,RW,E等几根线。其中R/S是指令和数据寄存器的选择控制线(串行模式下为片选),R/W是读写控制线(串行模式下是数据线),E是使能线(串行模式下为时钟线)。通过这几根控制线和数据线,再结合它的时序图,我们就可以编写出相应的驱动程序啦。看看并行模式下的写时序图:根据这个时序图,我们就可以写出写数据或者写命令到LCD12864液晶的子程序。读时序图如下:根据这个时序图我们就可以从LCD12864液晶模块内部RAM中读出相应的数据,我们的忙检测函数就是根据这个时序图写出来的。以及后面章节中讲的画点函数等都要用到读时序。有了这两个时序图,然后我们再看看OCMJ4X8C的相关指令集,就可以编写出驱动程序了。这里要注意的是指令集分为基本指令集和扩充指令集,其中扩充指令集主要是与绘图相关,在此后的章节中会有相应的介绍。下面让我们根据这些编写出它的驱动程序吧。我的硬件测试条件为:STC89C516(11.0592MHz)+OCMJ4X8C实际显示效果图片如下:程序部分如下,请结合液晶模块的DATASHEET看程序,这样能够更加快速的弄懂程序的流程。大致有如下几个函数:写数据,写指令,忙检测,初始化,指定地址显示字符串等等。#includereg52.h#includeintrins.hsbitio_LCD12864_RS=P1^0;sbitio_LCD12864_RW=P1^1;sbitio_LCD12864_EN=P1^2;#defineio_LCD12864_DATAPORTP0#defineSET_DATAio_LCD12864_RS=1;#defineSET_INCio_LCD12864_RS=0;#defineSET_READio_LCD12864_RW=1;#defineSET_WRITEio_LCD12864_RW=0;#defineSET_ENio_LCD12864_EN=1;#defineCLR_ENio_LCD12864_EN=0;voidv_Lcd12864CheckBusy_f(void)//忙检测函数{unsignedintnTimeOut=0;SET_INCSET_READCLR_ENSET_ENwhile((io_LCD12864_DATAPORT&0x80)&&(++nTimeOut!=0));CLR_ENSET_INCSET_READ}voidv_Lcd12864SendCmd_f(unsignedcharbyCmd)//发送命令{v_Lcd12864CheckBusy_f();SET_INCSET_WRITECLR_ENio_LCD12864_DATAPORT=byCmd;_nop_();_nop_();SET_EN_nop_();_nop_();CLR_ENSET_READSET_INC}voidv_Lcd12864SendData_f(unsignedcharbyData)//发送数据{v_Lcd12864CheckBusy_f();SET_DATASET_WRITECLR_ENio_LCD12864_DATAPORT=byData;_nop_();_nop_();SET_EN_nop_();_nop_();CLR_ENSET_READSET_INC}voidv_DelayMs_f(unsignedintnDelay)//延时{unsignedinti;for(;nDelay0;nDelay--){for(i=125;i0;i--);}}voidv_Lcd12864Init_f(void)//初始化{v_Lcd12864SendCmd_f(0x30);//基本指令集v_DelayMs_f(50);v_Lcd12864SendCmd_f(0x01);//清屏v_DelayMs_f(50);v_Lcd12864SendCmd_f(0x06);//光标右移v_DelayMs_f(50);v_Lcd12864SendCmd_f(0x0c);//开显示}voidv_Lcd12864SetAddress_f(unsignedcharx,y)//地址转换{unsignedcharbyAddress;switch(y){case0:byAddress=0x80+x;break;case1:byAddress=0x90+x;break;case2:byAddress=0x88+x;break;case3:byAddress=0x98+x;break;default:break;}v_Lcd12864SendCmd_f(byAddress);}voidv_Lcd12864PutString_f(unsignedcharx,unsignedchary,unsignedchar*pData){v_Lcd12864SetAddress_f(x,y);while(*pData!='\0'){v_Lcd12864SendData_f(*pData++);}}voidmain(void){v_Lcd12864Init_f();v_Lcd12864PutString_f(0,0,电子工程师之家);v_Lcd12864PutString_f(2,1,欢迎光临);v_Lcd12864PutString_f(0,2,*LCD12864ST7920*);v_Lcd12864PutString_f(0,3,★○◇◆※☆■△);while(1);}怎么样,你弄出来了吗,很简单吧~~下一章节内容将学习如何在LCD12864液晶屏上画图。尽请期待^_^下面我们来看一下12864液晶更高级的用法。首先是它的绘图功能。让我们先来显示一整副的图片吧,也就是128x64大小。在使用绘图功能时,先要打开扩充指令集,然后再打开绘图功能。接着就是送数据显示了。这里我们首先要弄明白ST7920的显示坐标关系。其显示坐标如下。从图中可以看出,X方向共有8个字(16个字节)Y方向共有0~31行分为上下两个屏。弄懂了之后我们就可以依照此坐标来显示一整屏的图片了。随便用一个图片的提取转换软件,讲一副126X64大小的图片转换成字节数据,总共字节大小为128*64/8=1024个字节。下面我们来看看这个显示整屏图像的函数voidv_Lcd12864DrawPicture_f(unsignedcharcode*pPicture){unsignedchari,j,k;for(i=0;i2;i++)//分上下两屏写{for(j=0;j32;j++){v_Lcd12864SendCmd_f(0x80+j);//写Y坐标if(i==0)//写X坐标{v_Lcd12864SendCmd_f(0x80);}else{v_Lcd12864SendCmd_f(0x88);}for(k=0;k16;k++)//写一整行数据{v_Lcd12864SendData_f(*pPicture++);}}}v_Lcd12864SendCmd_f(0x30);}看看效果图片如下:显示一个人的图像下面来看看如何在任意一个位置显示或者是擦除一个点对于12864这种二值显示屏来说,其显示状态无外乎显示和不显示一个点这两种状态。而在任意位置画点,是我们随心所欲的画线,画圆,画矩形的等GUI函数的基础。为了让这个位置有一个参考点,我们有必要定义一个坐标系在这里,我定义的坐标系如下0,0------------------------------------127,0||||||||0,63----------------------------------127,630,0代表屏幕的左上角,127,63代表屏幕的右下角。对于屏幕上面任意一个点,如果我们想要点亮它,必须先读出此点的状态,然后再修改该点,最后送出去,即读----修改----写。按照这个步骤,然后再运用C语言中的位操作运算符可以很方便的完成画点的函数。由于画点函数涉及到读ST7920内部RAM的操作,因此,我们必须先要完成这个读数据的函数具体实现过程如下:unsignedcharu8_Lcd12864ReadByte_f(void){unsignedcharbyReturnValue;v_Lcd12864CheckBusy_f();io_LCD12864_DATAPORT=0xff;SET_DATASET_READCLR_ENSET_ENbyReturnValue=io_LCD12864_DATAPORT;CLR_ENreturnbyReturnValue;}然后是画点的函数,其实现过程如下:voidv_Lcd12864DrawPoint_f(unsignedcharX,unsignedcharY,unsignedcharColor){unsignedcharRow,Tier,Tier_bit;unsignedcharReadOldH,ReadOldL;v_Lcd12864SendCmd_f(0x34);v_Lcd12864SendCmd_f(0x36);Tier=X4;Tier_bit=X&0x0f;if(Y32){Row=Y;}else{Row=Y-32;Tier+=8;}v_Lcd12864SendCmd_f(Row+0x80);v_Lcd12864SendCmd_f(Tier+0x80);u8_Lcd12864ReadByte_f();ReadOldH=u8_Lcd12864ReadByte_f();ReadOldL=u8_Lcd12864ReadByte_f();v_Lcd12864SendCmd_f(Row+0x80);v_Lcd12864SendCmd_f(Tier+0x80);if(Tier_bit8){switch(Color){case0:ReadOldH&=(~(0x01(7-Tier_bit)));break;case1:ReadOldH|=(0x01(7-Tier_bit));break;case2:ReadOldH^=(0x01(7-Tier_bit));break;default:break;}v_Lcd12864SendData_f(ReadOldH);v_Lcd12864SendData_f(ReadOldL);}else{switch(Color){case0:ReadOldL&=(~(0x01(15-Tier_bit)));break;case1:ReadOldL|=(0x01(15-Tier_bit));break;case2:ReadOldL^=(0x01(15-Tier_bit));break;default:break;}v_Lcd12864SendData_f(ReadOldH);v_Lcd12864SendData_f(ReadOldL);}v_Lcd12864SendCmd_f(0x30);}有了画点的函数之后,一切似乎都变得简单了,因为点是一切复杂图形的最基本的组成单位。下面我们就在这个画点函数的基础上,实现画水平线和垂直线的两个函数。画水平线:voidv_Lcd12864DrawLineX_f(unsignedcharX0,unsignedcharX1,unsignedcha
本文标题:玩转12864液晶屏(ST7920)
链接地址:https://www.777doc.com/doc-2110336 .html