还剩24页未读,继续阅读
本资源只提供10页预览,全部文档请下载后查看!喜欢就下载吧,查找使用更方便
文本内容:
[16];uchar xdot,i;addr=16*ch;〃读出个字节的点阵数据readepromaddr,hzdata,16;16xdot=cursor.x*8;〃将位置送入液晶wricmdOxbO+cursor.y;y〃将位置送入液晶wricmdxdotOxOf;xwricmd0x10|xdot»4;wricmdOxeO;fori=0;i8;i++〃写上半个字符wridatahzdata[i];wricmdOxee;wricmdxb+cursor.y+1;wricmdxdotOxOf;wricmd0xl0|xdot»4;〃写下半个字符for;i16;i++wricmdOxeO;wridatahzdata[i];wricmdOxee;}要理解这段程序,必需先知道点阵表示的含义我们知道,字母和汉字是按字模位信息显示的,那如何得到汉字的字模信息呢?莫非要我们自己去做?前辈们经过艰辛的努力,将制作好的字NO DOS模放到了一个个标准的库中以免去后辈的麻烦,这就是点阵字库文件一般我们使用的点阵宋体16*16字库,所谓是每一个汉字在纵、横各点的区域内显示的前一个表示列,后一个十六表示16*16,16,16行不过后来又有了、和字库及黑体、楷体和隶书字库HZK12HZK24,HZK32HZK48这段程序是用来在当前光标位置显示一个点阵的码字符的其实标准的码字符应当6x12ASC ASC是点阵区域表示,这也就是为什么我们常说“一个汉字占据两个字符位的缘由表示的是字符8x16asc的值首先说明一点,一个字符分两部分显示,也就是说,把分为上下两个“半码字符”ASC ASC汉字同样应当如此显示当然这只是我们目前介绍的这个的特性假如你使用的是别的种类,千万不led要生搬硬套,肯定要认真阅读说明书再回头看程序首先就是一堆定义,无符号整形数表示的是点阵在中的物理位置表示addr flash,码字符”’的字符点阵占据的物理位置是为什么?你看点阵区域,一个点用表ASC0—15,16*8Ibit示「就是灭「就是亮,那么总共,是不是就是同理,字符是,以此类推所以01128bit16byte216-30比如我传递迸来的是,贝”为而这个数组是用来存储读出的数据的addr=16*ch ch4addr64hzdata表示的是横向点位置,在下面我们可以知道它的计算公式是,就是光标横坐标值乘以Xdot cursor.x*88由于之前我们将光标设置在左上角,所以为,因此此时横向点位置也为假如我们已经显示cursor.x0了一个字符,此时的就应当为,那么就应当为这应当很好理解,从点阵区域的ASC cursor.x1xdot8大小我们可以知道一个码字符从横坐标上看占用的是个点下一个码字符当然应当ASC80—7,ASC从开头拉8接下来是这个函数什么意思呢?由于它是属于此外一个文件,这里只readepromaddr,hzdata,
16.c是给出原型函数原型如下Readepromreadepromulong ad,uchar*pst,uint nunion{ulong addr_l;struct{uint a32;uint alO;}addr_i;struct{uchar a3;uinta21;uchar aO;}add r;}address;uint i;uchar xdata*fl ash;口如被占用暂停读取Pl=0xff;//PlwhilePl!=0xff;address.addr l=ad;//设置线,每块字节Pl=Pl0xc0|address.addr.a21/0x20;bank8K窗口地址范围flash=0x8000+address.addr_i.a10%0x2000;//flash0x8000—0x9ffff读个字节〃fori=0;i N*pst++=*flash++;〃假如地址跨页贝翻到下一个ifflash==OxaOOO UbankP1++;flash=0x8000;在这里我们就不单独解释了只是说说他的或许作用即读个中的字节,每次最多字,,N flash65535节入口参数的含义分别是为字符在中的物理地址,表示读出来放在内存中的ulong adflash uchar*pst指针首位置,表示读出多少个字节uint n也就是说,』后,我们已经把表示需要用的个字节传到了数组readepromaddr,hzdata6ch16hzdata中,到时候就可以直接拿来用了在接下来是送,的位置,为什么位置是呢?是一个命令指令,表示设置x yy OxbO+cursor.y OxbO刚才说了,一个是行组成,也就是说高个点,也就是说一个字符或者汉字都应当由两个page page88来供应数据刚才还说了,显示是分上下两半部分组成的,所以先设置成,然page pageOxbO+cursor.y后再设置成‘这样是不是先后选中两个嘿嘿,很顺理成章吧?由于我们这个系OxbO+cursor.y+1pa ge列默认是点宽,所以横向点的数目也就是列地址至少需要位表示才够了位只有,但led13287128是位置送的列地址是高位的个是命令标志,只有低位,明显不能表示完怎么办x xdotOxOf844呢?我们就分两步送,先送低位,再说高四位忘了这个设置列地址的指令?回头去看看函数中的4els内容吧八_八°高位怎么送这是设置高位列地址的指令低四位表示列4?wricmd0x10|xdot»4;4的高地址连续的作用是设置成读一改一写模式这个前面已经介绍过了在接下来就是送我wricmdOxeO们要送显的数据到中的过程了,这个过程很简洁,大体就是一列一列的送,送了一个字节后GDDRAM列中的列地址自动加一,数组下标也加一,然后再连续送,其实我们从函数的过程中就能GDDRAM els领悟到送完上半部分凹凸列地址重新送再重复这个过程具体指令就不介绍了,聪慧的你,,page+1,肯定能够理解呵呵〜show_hzuchar chi,uchar ch2ulong addr;uchar hzdata
[32];uchar xdot,i;〃寻址汉字在中的物理位置ifchl=OxbO flashaddr=ch1-0xb0*94+ch2-0xal;addr=addr*32+0x5a40;elseaddr=ch1-Oxa1*94+ch2-0xal;addr=addr*32+0x800;〃读出个汉字点阵数据readepromaddr,hzdata,32;32〃计算位置xdot=cursor.x*8;XwricmdOxbO+cursor.y;wricmdxdotOxOf;wricmd0x10|xdot»4;wricmdOxeO;〃显示上半个汉字fori=0;i16;i++wridatahzdata[i];wricmdOxee;wricmd OxbO+cursor.y+1;wricmdxdotOxOf;wricmd0x1|xdot»4;wricmdOxeO;〃显示下半个汉字for;i32;i++wridatahzdata[i];wricmdOxee;初始化好,才能正确地显示图文°还自带显示英文是就是图象显示数据存储器简称1815RAM,Graphic DisplayData Ram,GDRAM对于现在很多现成的屏来说,掌握芯片都带有了的,大小就和他的最大显示点数相当LCM GDRAM我估量你看到现在还是一头雾水,呵呵,没关系,当时我看的时候也是一头雾水,看到后面你就会明白他们的原理了接着是的接口问题了它支持总线就是和我们一样的总线,有,1815,8080,6800I2C8080,51CS,,然后是数据地址线;又叫摩托罗拉总线,有,,然后是地址数据线;总线,WR RD6800R/W E12c呵呵,当然就是总线咯,还用说么?12c由于这个是摩托罗拉的屏,出厂的时候已经配置为总线了,所以我们不能用正常的LCD680051总线来驱动,但实际上是可以兼容总线的,先等我介绍下这个总线吧68008080读写脚,为的时候是读,的时候是写R/W W10脚使能脚,功能犹如总线的,也是低有效的,但数据在高的时候锁E51CS D0-D7存脚,这个是数据,命令选择脚,的时候代表总线传输的是数据(不论是读还是写),的时D/C1候代表总线传输命令(不论是读还是写)理所当然的数据脚咯D0-D7:驱动原理很简洁,在为低的时候对脚输入读写信号,读就是,写就是然后选择你读写E R/W10;的是数据还是命令,脚为数据,为命令;最终就是数据脚的数据了D/C10以上原理,用单片机做是很简洁的事情,不过使用的缺点就是不能复用,铺张了很多的资源,1010所以在学习板上是使用总线驱动的之前说了,某些总线是可以用总线模拟的,而这LCD6808080个就是可以使用总线的了LCD8080总线读写掌握只需要只脚,为读为写,而总线是两只脚,,其中的68001R/W1()8080RD WR某个脚为低就对应响应功能依据这个规律关系,我们很简洁就猜想到为什么的脚可以直接接6800R/W上的了8080WR这些都是垫场的开场白拉接下来我就以丁丁编写的的使用程序,来介绍使用驱动18151815led的具体步骤为了让大家能够理解清晰,我肯定依据分段的形式,一段一段解释当然由于本菜鸟水平有限,假如解释错误还请大家不吝赐教开头的程序我会讲的很细,后面的我就讲个或许了,只要理解了这个过程就不难了这个程序的作用就是在当前光标位置显示一个汉字或者全角字符入口参数表示该汉字的16*16chi区码入口参数表示位码,ch2说到这里可能有一些伴侣不理解了下面我来讲一下前面已经介绍了汉字库的一些学问,虽然汉字库种类繁多,但都是依据区位的挨次排列的前一个字节为该汉字的区号,后一个字节为该字的位号每一个区纪录个汉字,位号则为该字在该区中的位置因此,汉字在汉字库中的具体位置计算公式为94(区号)位号减是由于数组是以为开头而区号位号是以为开头的这仅为以汉字为单94*-1+-111位该汉字在汉字库中的位置,那么,如何得到以字节为单位得到该汉字在汉字库中的位置呢?只需乘上一个汉字字模占用的字节数即可,即(区号-)位号)一个汉字字模占用字节数,而按每种(94*1+-1*汉字库的汉字大小不同又会得到不同的结果以点阵字库为例,计算公式则为(区号)16*16(94*-1(位号))汉字库文该从该位置起的字节信息即纪录了该字的字模信息+-1*3232,明白了这些,这个程序就很好理解了,其实质是和我们分析的上一个显示字符的程序是Ok ASC差不多的,首先除了定义,就是寻址汉字在中的物理位置flash由于在中文环境下,输入的是汉字的内码,我们必需将之转换成区位码,算出偏移量,从字库中找到对应的汉字,将其字模显示即可内码转换成区位码方法如下qh=c1—OxaO wh=c2—OxaO其区位码就是qw=qh*Oxff+wh该汉字在字库中离起点的位置是(()())offset=94*qh—l+wh—1*32L其它步骤和上一个函数几乎一模一样,就不多废话了/*1*KL*K1**1**1**f K|*A**A*KL*KL*K|*1KL*KL**,t*K|*1KL*KL**1**f*1*1*1**L*K|*1/*i**T^^Tw rT^rr**T**T**T*^T*^T**g**T rj*rj**T**T*void setcursorucharx,uchar yifx=LCD_MAX_X cursor.x=x;else二cursor.x LCDMAX X;ify=LCD_MAX_Y cursor.y=y;elsecursor.y=LCD_MAX_Y-1;KL*KL*KL*KI vl*KIKIKL**1*1^KI*1vf^^L*KI^/[、[、J、,卜rr^^1%、、〃、
1、〃、—、、]、,卜力、[、元、〃、、〃、[再看接下来的这个程序这个程序的作用是设置光标位置,以点阵为一个光标单位,人口参数8x8表示方向和方向光标位置和的含义和计算公式在刚开头的时候我们x y LCD_MAX_X LCD_MAX_Y就已经说过了至于这里为什么是前面已经说了一个字符或者汉字都应当由两个LCD_MAX_Y-1,page来供应数据,现在我需要在页显示东西,那么我应当是把纵坐标点设置到页吧?呵呵,其实点破7,87就很简洁了/vi7K1K17,7,*iviKL7,KJK17,K|K|7,^1*KJK1*KL7,KJ^1*KI7,7,/J*,J*J*rT*-J**1%-J*力、*T-J*-J*7^〃、void lcdstringuchar*pstwhile*pst!=0〃小于是字符if*pst0x800x80〃处理回车换行if*pst==0x0a setcursor0,cursor.y+2;else if*pst==OxOd setcursor0,cursor.y;else〃显示字符show_asc*pst;ASCcursor.x++;ifcursor.xLCD_MAX_X*pst+1!=0x0a{cursor.x=0;cursor.y=cursor.y+2;}cursor.x=0;cursor.y=cursor.y+2;〃下一个要显示的字符pst++;}〃大于是汉字else x8if cursor.x=LCD_MAX_X〃一行的尾部只有半个汉字位置的处理,加一个空格,在下一show_asc0x20;行开头显示if cursor.y LCD_MAX_Y cursor.y=;//〃显示一个汉字show_hz*pst,*pst+l;cursor.x+=2;pst+=2;if cursor.x LCD_MAX_X*pst+1!=OxOa{cursor.x=0;cursor.y=cursor.y+2;}ifcursor.yLCD_MAX_Y{cursor.x=0;cursor.y=0;return;}7,7,7,7,7,7,Kt7,7,7,//这个程序呢,也就是我们这篇文章介绍的内容的中心程序!地位重要吧那么他的作用是什么呢?就是在当前光标位置显示字符串拉入口参数就是要显示的字符串更关键的是同时也显示汉字!什么?你还是没有理解到这个东西的好处?这样说吧,只要你的程序中包含我们所介绍的这些程序,那么在应用程序中,我们假如想让显示“风”,那么我们就直接风”就行了哈哈,这么奇led lcdstring“妙的功能,实现起来其实是很简洁的拉下面我门就一起来分析分析这个函数首先是字符处理函数前面的语句中的内容都很好理解,大家看程序注释就行了‘这里我while,if要说的是这句是处理回车换行,为什么?由于在码表中if*pst==OxOa setcursor0,cursor.y+2;0x0a asc就是表示换行的,而接下来的是表示回车的,还有后来汉字显示需要用的表示呵呵,OxOd0x20space由于我当时看的时候半天没有找到码表,为了避开让大家也都去找,这里直接说出来了为什么是asc呢?信任大家已经知道答案了什么?你不知道?,请看上一页cursor.y+2ohyeah〜这里有必要再讲讲这句为什么是自增一?横坐标一个字符不是占用个点么?cursor.x++;cursor.x8千万不要忘了,横坐标的点是用表示的计算公式是什么呢?明白了吧?xdot xdot=cursor.x*8;接下来就是汉字处理部分其流程和前一部分完全一样,只不过和都是自增,缘由当cursor.x pst2然是由于汉字是由区码和位码打算的,因此占用的字节数是字符的两倍呵呵,你看看显示汉字的语句〜不是么show_hz*pst,*pst+l到这里,我们的学习历程就基本结束了整个程序的精华已经给大家介绍完了当然最终还剩两个“在当前光标以十迸制方式在液晶上显示一个字节的值”和“在当前光标显示一个字符”两个函数,ASC不过特别简洁,这里只是作为附录附在后面,有爱好的伴侣可以试试自己分析一下这只是很多种掌握器其中一种的使用方法但是不要怕,我这几天又看了看其它的驱动掌握器,led原理其实是一样的,只不过是实现功能的程序可能不同,所以最关键的还是要理解思想思想理解了,学别的类似东西也就相通了盼望看到这个文章各位都能获得一些学问和心得假如能够关心你,将是我莫大的荣幸附录://si^six//ry*〃在当前光标以十迸制方式在液晶上显示一个字节的值〃入口:要显示的值lcddigituchar chuchari
[4];i
[0]=0x30+ch/100;i[l]=0x30+ch%100/10;二i⑵0x3+ch%10;〃添加结束符号i
[3]=0;lcdstringi;〃在当前光标显示一个字符ASC〃人口:要显示的字符lcdcharuchar chuchari
[2];i[O]=ch;lcdstringi;留意哦,这个程序是来自单片机世界”,作者版主丁丁(聂小猛),未经允许,不得”51抄袭作为商业用途/^9^^9sl^K1^K1^^9^1#/^|*^r**4^1^*g^*T*#define ucharunsigned char#define uintunsigned int#define ulongunsigned long#include#include#include study.h〃液晶数据口#define LCMDXBYTE[0xAf00]〃液晶命令口#define LCMCXBYTE[0xAb0]的宽点数#define LCD_DOT_X98//led的高点数#define LCD_DOT_Y54//led//每行字符,#define LCD_MAX_X11LCD_MAX_X+1*8A〃共多少行,点#defineLCD_MAX_Y5LCD_MAX_Y+1*8假如你写过单片机程序,就会知道任何程序的初始化阶段都是这么些步骤,定义再定义,最终是某些功能的初始化函数这些就是刚开头的声明定义过程前面的几个,我就不多说了,假define include如你连这个都看不懂,只能先去补习补习语言了c两句是用来定义外部总线接口地址的#define LCMDXBYTE[OxAfOOJ^#define LCMCXBYTE[OxAbOO]用来传递数据,用来传递命令,之前说过,是传输命令还是数据主要是取决于的,OxAfOO OxAbOOA10上面两个地址对应的其实就是〉〉照电子白菜大虾的话说,地址的取A100xaf00-A10=l,0xab00-Al0=0值只要确保在之间就可以了,所以以下定义一样能正确驱动A000〜AFFF LCD:〃液晶数据口#define LCMDXBYTE[0xA400]〃液晶命令口#define LCMCXBYTE[xA0]虽然地址不同了,但对的作用依旧不变A10接下来的两句则是用来表示的宽点数,表示高点数想象坐标轴,LCD_DOT_X led LCD_DOT_Y呵呵,是不是好理解了?这就说明我们现在用的是宽高的ledLCD_DOT_X LCD_DO T_Y最终两句则是告知我们,这个可以显示行,每行个字符这些参数都是可以依据不同led511led而变化的/7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,/•卜•卜・卜•卜,丁、•卜,卜•卜q.•卜•卜rj*•卜•卜・卜,丁、q.・卜•卜•卜,卜•卜•卜struct cursortypeucharx;uchar y;;struct cursortypecursor;void wridataucharchLCMD=ch;void wricmducharchLCMC=ch;1^^XK1#s£^X K1^1^1#K1#X/,卜,j.•[、,卜7卜.
1、■.、■、■卜,卜,卜,卜,,、•[、,卜,卜,卜.卜.[、■.、■[、■卜,卜.卜,[、■.、•;、,卜,卜•卜.[、,,、•[、,卜■[、,卜.卜.[、■]、,]、,卜/这几句也都属于初始化步骤首先这个结构体是用来定义光标的,光标struct cursortype在屏幕上当然可以用和两个值表示,这样我们到时候用或者确定光标位置就便利多x ycursor.x cursor.y了和两个函数则是写数据和写命令功能认真看就是液晶数据口5Wridata wricmd,LCMD就是液晶命令口峨们对他们迸行的操作实际上就是对或地址迸行操作例如LCMC OxAfOOOxAOOO我们用也就是说我们把这个数据通过这个外部总线接口地址送到wridata0x33,0x33OxAfOO SSD181X中由于是的地址,必定为掌握器就知道此时你要传递的是数据拉怎么样很便利吧OxAfOO A101,〜void lightucharnLCMC=0x81;LCMC=n;把这个程序单独列出来是由于想讲讲程序如何传递能够作用的有效参数首先这是一个调整亮led度(其实更加严格得说是对比度)的函数我们看到他用的,说明此时我们是发送程序给,LCMC led让他知道我们要调整亮度了那么究竟传递什么东西,掌握器才能知道我们的意图呢?不用担忧,pdf上会告知你按什么格式发送指令给掌握器才有效这是上面的格式之一SSD181Xpdf为了便利我只截取其中一个功能设置来进行说明最左边的数字表示你发送的命令必需是这样的格式,中间的英文表示该格式命令所起的作用,右边的文字表示这些,也就是不确定数字的值该如XXXX何选取才能获得我们想要的效果就以这个方框为例吧,首先我们看中间这个小方框,它告知我们这条指令的作用是设置对比度寄存器,也就是说我们可以通过对该寄存器的修改来实现调整对比度得调整那么具体如何调整呢?我们再来看看最左边的方框,这个内容告知我们,我们需要用发送两个字节数据其中一个字节是固定LCMC,的就是其次个字节则是自己打算怎么打算呢?再看看第三个小方框吧嘏如你文好,100000010x81,e立刻就能看懂它的意思假如你文不好…嘿嘿,建议金山词霸!(倒,谁扔的香蕉皮!)e・・・这里的意思就是说,对比度分为个等级,这样位二进制数就可以表示完,那么我们64XXXXXX6需要用哪个等级就设置哪个数,比如现在我们需要等级的对比度,因此程序中消失了这个n LCMC=n哪里来的?(),嘿嘿,主函数传递进来的n voidlight ucharn呵呵,现在明白命令是怎么传送的了吧?一会儿还有例子,假如不明白不要惊慌void clsucharchuchar ij;forj=OxO;jwricmdOxbO+j;//set page//101Ixxxx wricmd0x10;//set columnmsb wricmdOxO;//set columnIsbwricmdOxeO;//set modify-read modefori=0;i98;i++//填满即清屏wridataOxOO;0wricmdOxee;//reset modify-read mode这里就开头迸入实质性的编程部分了这是一个清屏函数,传递的参数就表示连带一ch=9ICON起清除,隹旻如则表示不清除这里的实质上表示中的页面值ch=8ICON chGDDRAM page这里有点难以理解先看看是怎么构成的GDDRAM这是中关于地址分布图的说明我们可以从这里清晰看到的概念一个pdf GDDRAM,page page实际上是一个拥有个高点的行点高的屏幕就有个每个的宽度都是和整个宽度8,648page,page RAM是一样的从的最开头我们就可以看到的特性是,也就是说高为,换算过pdf1815132x64+1i conline64来就是个而的数据分布图与实际的数据显示图是完全全都的,实际上的显示8page GDDRAMled led的就是的映射因此我们清屏的目的就是为了清除中的值因此从语GDDRAM GDDRAMforj=x;j句中我们得知,循环次数是由打算的假如那么循环次就只能清除这个页面ch ch=8,8,8page只有才能清除最终的那一个ch=9,1icon line好,我们接着往下看进入循环之后,程序要做的事就是一个一个得清除信息首先page page翻翻找到相关信息:wricmdOxbO+j,pdf,这下知道了,这个语句的意思就是选择要进行读写操作的页面由于总共只有个页面,所以个84不确定位就够拉这也就是的参数是的缘由数只由也就是掌握wricmd OxbO+j”page j,ch接下来两句和我们同样可以通过的信息得知,作用时用来设置列wricmdOxlO wricmdOxO,pdf的低地址和列的高地址参数高四位为的表示设置高地址,的表示设置低地址默认状况下00010凹凸地址均为0X0000接下来就是设置工作模式这个语句的作用是,就是设置成wricmdOxeO°set read-modify-read mode读一改一写模式???????????最终把本次循环我们选择的填,也就达到了请零的目的需要留意的是的范围是,page0I0—97为什么?由于我们现在举例用的宽点数只有的作用是把某一led98owridataOxOO。