专注于射频工程师,天线工程师和电子硬件工程师的培养
首页 > 技术文库 > 硬件设计 > 显示技术 > 大神带你在LCD12864点阵屏上绘图程序详解

大神带你在LCD12864点阵屏上绘图程序详解

时间:2020-12-14 点击:

到目前为止,似乎如果我们要想做一个电话号码记事本之类的电子助手已经万事俱备了,但真正开始做的时候才发现,我们还没有教会AVR如何去写字。如果说,我们前面已经能在LCD上画出“壁画”的话,那么要想让别人看懂你记录的到底是什么鬼画符还需要一点点关于“甲骨文”的扫盲。事实上,大家约定俗成的固定大小的图片集或其子集就是一个被尊称为字库的神圣典籍。在这个圣经里面记录的是一种被称之为“字模码”的东西,对于我们,这种信息可能相当抽象,但是借助LCD,那么字模码就是一个我们能看懂的字符在显存中存在的模式。

不得不承认,到目前为止,似乎如果我们要想做一个电话号码记事本之类的电子助手已经万事俱备了,但真正开始做的时候才发现,我们还没有教会AVR如何去写字。如果说,我们前面已经能在LCD上画出“壁画”的话,那么要想让别人看懂你记录的到底是什么鬼画符还需要一点点关于“甲骨文”的扫盲。事实上,大家约定俗成的固定大小的图片集或其子集就是一个被尊称为字库的神圣典籍。在这个圣经里面记录的是一种被称之为“字模码”的东西,对于我们,这种信息可能相当抽象,但是借助LCD,那么字模码就是一个我们能看懂的字符在显存中存在的模式。

关于这些字模码是如何排列的,自古以来就有数不清的模式。终于有一天,一群中国人伴随着新中国站了起来,制定了一个叫做国标的标准(GB),根据这个标准,祖国大地的字模码才有了统一的目录,而查询这个目录的方法已经逐渐被人们所淡忘,吹落那源自电报码的书籍红色封皮上的沧桑,用手轻轻抚摸封皮上的的文字:“区位码”,我们发现,其实他包含了6000个汉字的一级字库其他一些由非常用字组成的多级字库。

在西方,埃尼阿克的故乡,一群依靠技术侵略世界的疯子根据自己半通不同的习惯制定了一个由128个字符组成的交换标准称之为ASCII码,由于技术大潮的冲击,世界妥协了。

这一切的一切都无法改变字库只不过是图片集和的本质。所以,敢于抵抗强权的人们在自己的领土上坚持着自己的信念——我们称之为“小字库技术”。甚至有些人坚持使用图片记事,那么自然的被视作是“无字库技术”。

世界在前进,即便后来世界技术的格局发生了怎样的变化,即便一些曾经约定的不合理的东西也会作为最底层的协议支持者新世界,就像是乌龟驼着的世界。任何触动这些底层的行为都会受到世界的背叛,所以,抛弃情感上的东西,我们来研究一下ACSII的构成原理和实现方法。

对不起大家,我写这些东西的目的就是面向初学者。事实上,如各位所说,我并非高手,所以很多地方漏出了类似“内存映射”之类的马脚。这里我只想做一点解释,只有我弄懂了的东西,我才能用通俗的方法和大家解释,我一窍不通的东西就只好原样照搬打肿脸充胖子了。呵呵。还请原谅。事实上,就拿“内存映射”这个问题来说,我使用的大段大段的文字来解释这个概念,因为即便是罗嗦,我也最多只能用“屏幕的一块区域对应内存的一块区域”这样仍然抽象的话语来解释,反而显得我骗稿费一般,所以不如先提出一个名词,把解释溶化在后面的文字中。

本来,开篇就说得很清楚,我写这些东西的目的不是等大家来喊牛,姑妄言之,姑妄听之,水平有限,没有刻意去追求什么文本格式上的东西,自然可能不对大家胃口,我以后注意就是了。但是,说回来,写这些东西的心情和大家写伯克的时候差不多,多半是吐吐心中不吐不快的东西罢了,所以,由着性子,演绎也罢,说明书也罢,文档整理稿也罢,那要看那一阵子我正在看什么书了,如果哪天我不幸开始看小说,来一个欲知后事请听下回分解也说不定。

我的专业本来就是软件工程,所以写出这些文字,非常自然。

1 ASCII字符集

ASCII(American Standard Code forInformaTIon InterChange)——美国通用信息交换编码。他是现在流行的众多编码的榜样,虽然使用仅仅7位二进制表示(通常用一个字节表示),但是却是众多编码系统的基础,比方说16位二进制为组成的Unicode编码,证据就是,只要在ASCII码前面加9个零就成完成了转换。当然,仍然有不听话的,比方说IBM老大的EBCDIC码(大型计算机系统上用的)。

大家都注意到了7位二进制表示的编码显然只能有128个字符的容量,那么,用一个字节256个字符的容量岂不是造成了浪费?于是,现在PC机上普遍通用的IBM扩展ASCII码从128~255开始扩展了128个字符——注意,这128个字符并不是通用的,即便在我们能接触的大部分场合他们都有效,但是记住他们的“非常任理事国”的身份是拥有重大意义的。

比方说,我们的显示系统只需要显示E文字母和数字还有一些标点符号,那么,干什么要这些无用的字符充数呢?要知道,一个字母存储起来需要至少8*7的点阵(7个字节)啊!事实上,由于几乎所有通用单片机内部都不带有ASCII字库(字模码),所以,我们必须把他们存储起来,并且还不能打破原有的存储模式,不然通过ASCII码作为索引我们就找不到他们了。为了完成对字模库的简化,我们需要知道他们的构成方式,然后再考虑如何去获取一个已知的标准字模库,并按照我们设计的方法去简化他……可怜的AVR,存储器又要吃紧了。

从古老的教科书上,很容易获得一张ASCII编码表。因为大家都是搞Embedded System开发的(为了显示大家工作的高深程度,请允许我掉书袋),所以,这里我更多的要讲述一下ASCII编码一些不太被人注意的特性,一些只有从二进制角度才容易看出的特性。

1)ASCII码由7位二进制组成;

[6][5][4][3][2][1][0]

2)[6:5]为用来表示ASCII编码的组分类

控制字符组(显示不需要显示的东西)

数字字符和标点符号组

大写字符和特殊字符

小写字符和特殊字符

3)只要把大写字母的第6位也就是[5]置位就是现了到小写字母的转换,反之亦然;

4)数字的ASCII码[3:0]位的值与它要表示的数值相同;

例如:

“0” 0x30

“1”0x31

依照上面的编码规则,ASCII码的字模码文件存储的方式为:

char c;

……

fAddress = c* 8 * 16;//超级简单哈,这是计算机系统上标准8*16的ASCII字符集

fAddress = c* 8 * 8; //这是计算机系统使用的8*8小字符集

聪明的大家已经知道如何在存储器中获得字模码了吧?

就是访问存储的“基地址+fAddress”就可以了。

为了便于后面大家实现汉字显示时候的代码移植(回避全角和半角问题),我们使用8*16的大字符集,至于你想使用小字符集,那么就看你的爱好了。

2 How toget them?

这里我们来顺手说说字模码获得的问题。

不可否认,现在网上很多兄弟写的字模制作软件水平之高,已经到了令人叹为观止的地步,只可惜当时我学习字库问题的时候,尚且没有解决温饱,更不用说上网了。而且,这些字模软件无不在客观上支持了字模的“无政府主义”,小字库和无字库技术在一些不恰当的场合也被大量滥用,严重影响了接着写你代码同志的心情……鬼知道原来跳槽的家伙如何定义那该死的字库的,所以,提倡在何时的场合使用标准的字模库还是非常有必要的。

首先说说一种简单的获取字模的方法。

不知道还有多少人记得UCDOS,中国汉字操作系统的“希望”。金山WPS,CCED……TX.com,这些东西让人难忘啊。我们的字模库很容易从这样具有我国独立知识产权的系统中获得。所有的东西都放在

UCDOS

目录下面。我们选取这次需要的文件“ASC16”。顺手说下,汉字库也可以从里面获得“HZK16”。其他的字模库在

UCDOSFNT

目录下面。

还有一种BT的方法可以获得8*8的字库。大家记得BIOS吧……呵呵,利用TC写一个中断程序,直接读出来……哈哈。后面有机会我会附上代码,如果我能记得地址的话。

3 字库减肥

查看一下Mega8的Datasheet,上面赫然写着8K Flash,再看看ASC16的大小4K,我不知道有多少人不会打寒颤。更不用说260多K的汉字库了,看来要么外扩存储器,要么只能选择西文显示,并且对ASC16库进行减肥。

其实,减肥并不是一个可以称之为技术的行为,总原则就是丢弃无用的部分,同时修改索引方式以保证外界使用减肥前方文字魔窟文件的索引方式不至于出错就可以了。就拿ASC16的减肥工作来说吧,很显然,我们并不需要扩展字符128~255的那个部分,可以减小大小为16*128 = 2K的大小,再加上基本字符基的四个区中,控制字符区显然也是可以舍弃的,所以,还可以减少16*32 = 512B的大小,也就是说,剩下的文件只有1.5K大小了,哈哈,总算可以接受了。当然如果你选择了8*8的字模,就更小了。

以上完成的只是第一步,借助类似UltraEdit这样的编辑工具都可以做到,然后我们再把字模库写成数组的形式,比方说:

const charASC_Lib[][16] = {

……

{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},

……

}

包含入头文件,就可以了。

下面我们需要一个访问函数,用来安全的有效的访问到我们需要的字模库:

char*getASCLIB(char ASC)

{

if ((ASC <32 )|| (ASC > 127))

{

returnASC_Lib[CharStringNULL]; //需要一个空字符串作为安全返回

}

returnASC_Lib[ASC];

}

配合12864头文件中公版中都有的那个显示图片的函数,就可以显示字符了。例如:

voidDispBITMap(const char *String,char StringLength,char X,char Y,char DispModel);

我们还可以再对这个函数包装一下,实现16 * 4的文本模式。使用CLocate(x,y)来定位字符,用Print("")来显示字符串,用PrintN()来显示数字……哈哈。这一部分就留给大家自己来做了,不过是几个函数加宏定义罢了,相信自己简单的。

至于如何实现任意位置显示字符,还有一些字符特效的实现,在下一节里面具体说明。

这是我写的函数

/********************************************************

* 函数说明:读取显示数据指令              *

* 输出:  显示数据                  *

********************************************************/

chargetLCD12864Data(void)

{

char TempData= 0;

char a = 0;

LCD12864_SetModel_Data;

LCD12864_SetModel_Read;

LCD12864_SetEnable;

LCD12864_SetDisable;

LCD12864_SetEnable;

asm("nop");

TempData =ReadDataPORT;

CopyRight © 2009-2021,易迪拓培训 All Rights Reserved,沪ICP备05048810-2号 版权所有

网站地图

Top