第6节 字符显示原理
推荐给好友
打印
加入收藏
更新于2009-04-21 15:52:12

3.6.1. 字符与字模
驱动程序当中,字符库(也就是字模的集全)的数据采用了与一般的单色点阵LCD的数据组成方式,即字模当中的一个位代表LCD显示中的一个像素点,取点方式为从左到右,自上到下的顺序。对于这点,驱动中自带的ASCII码西文字库的字模和用户可自定义的中文字库中的字模是一样的。

字模采用了以Byte为单位的位流结构,即当一行取点不为8的整数倍时,补齐数据至8位,无用位填零。
下面用几个字符取字模的例子来解释一下其对应的关系。
所有的字符都可以将其栅格化,化成一个点的阵列来表示,比如下图:


上图为取字模工具中输入字符’A’后显示的栅格情况,字体选择较小,整个字用8*12的点阵表示。其实在取这个字符的字模时,只需要取6*12的就够了;但如前面所述的,为了补齐8位的byte数据,才用了8*12的点阵规模。

至于数据位补齐的原则,与取模的方向有关,本驱动当中的字模取向为:从左到右,自上到下;是以横向为基准的,所以要在横向满足最小存储单元的位数倍数要求,才补齐字模为8*12。如果取字模的方向为:自上至下、从左到右(纵向优先),则补齐字模就会为6*16的了。

字模数据的补齐只是针对于字模将要存储在MCU的存储空间的,实际在显示字符时仍然可以根据字符最合适的尺寸来显示,比如在本驱动当中的ASCII码西文字库的字模就为6*10的,但占用的数据位数为8*10。
采用从左到右,自上至下的顺序取的字模数据如下所示:


将上面的数据配入前面的图中,其实就很简单了,图中的一行栅格点对应一个byte的数据,左边的点对应高位,右边的点对应低位,如下图所示:


再取一个点阵大一点的汉字字模,如下图:


从图中,可以看出,这次取的汉字“中”字的横向点数依然不为8的整倍,所以也是需要进行对齐调整的;取出的字模数据如下:


每一行的点利用3个byte的数据表示,最后不足8整倍数的,在后面补齐0;所以上面的“中”字的字模数据所占用的存储单元(byte)数为3*20,共和60个byte。

我们再取一个小一点字号的“中”字字模,如下图:


利用工具所取得的数据为:


3.6.2. 字模与字库
字库就是字模数据的集合,比如ASCII码西文字库就是根据ASCII码的编码顺序将127个ASCII码字符的字模数据组成一个数组;当然字库与字模一样也是要有规定每个字模的尺寸大小的,同一字库当中的字模都是一样的点阵大小的,这样才能在字库当中方便的检索到所需要的字符的字模数据。

比如,在MzL02的MCS51版通用LCD驱动程序当中,集成在驱动程序里面的ASCII码西文字库统一为6*10的点阵,而针对byte进行对齐后,每个字模占用的点阵位数为8*10;此外,为了节省空间的占用,这里并没有把全部的127个ASCII码字符的字模都用上,而是把前32个编号的字符去掉了,只取后面的。该字库定义如下:



字库定义为一个unsigned char的数组,数组的名称Asii0610即为该字库的首地址;所以当要检索字库中的某一个字符的字模数据时,可以利用它来找到具体的地址。

如要检索字符’A’的字模数据,则该字符的字模数据首地址等于如下代码计算的结果:
‘A’字符的首地址= Asii0610-(10*32)+’A’*10
减去10*32是因为该字库删减掉了前32个字符的字模,而每个字符的字模所占用的byte数为10个;’A’的ASCII码值为0x41。

驱动程序中自带的ASCII码西文字库用户不需要改动,此外驱动程序中还为用户定义了一个汉字字库的数组,放置在文件GB_Table当中,用户需要显示中文字符或自提取的图像字模时可以将数据放置在这处,或者另起一个字库数组。

与ASCII码西文字库一样,放置在同一个中文字库中的字模也是需要尺寸是相同的才可;而需要索引这些字模时,用户需要知道自己在定义这个字库时每个汉字(或者图像)字模在数组中的偏移位置。

如下面的定义,即为驱动程序当中所提供的几个汉字字模:


在该字库中,每个汉字的字模数据为3*16个byte,所以这四个汉字我们可以为它们定下一个查旬的序号就可以检索到它们的字模数据的首地址了;分别是:铭——0,正——1,同——2,创——3。

当然,这里所说的中文字库与GB的二级汉字库之类的不是一个概念的,二级汉字库有换算的算法,可以根据汉字的GB码值以及该字库的字符尺寸大小来检索到汉字的字模数据。这里就不多作解释。

在驱动程序当中有一个函数与定义的字库是息息相关的,就是FontSet函数,用户如果要定义新的字库的话,就需要在该函数修改相关的代码,同时在LCD_Dis.c当中对自定义的字库数组进行外部声明。下面来看看一些相关的定义:
在LCD_Dis.c文件当中有如下的定义和声明:


在前面的三个外部声明,就是分别在LCD_ASCII.c和GB_Table.c中定义好的字库;如果用户自己又额外定义了别的字库的话,同样也需要在这里加上它的外部声明。

而接下来的两个变量的定义:X_Witch和Y_Witch,分别是存放当前设置的字符类型的宽和高的点数大小,而Font_Wrod保存的是当前设置的字符的每个字模所占用的存储单元数量,指针Char_TAB则保存当前设置的字库数组的首地址。
BMP_Color和Char_Color这两个变量分别保存当前设置的绘图前景色和字符色,其实对于黑白的单色LCD屏也就是零和非零的区别。
而Font_type变量用于区分是ASCII码字库还是自定义的汉字字库,这将影响在字符显示时,提取字库中对应字符的字模。
Font_Cover和Char_BackColor这两个变量是字符覆盖显示模式的变量。

下面来看看FontSet函数中的设置:



FontSet函数的两个参数分别是表示要选择的字符类型、设置字符色;字符类型的选择实际上就看代码当中的switch分支怎么分配了,如上代码,设置为1时表示选择ASCII西文字符,为2时则为GB_Table中定义的自定义汉字库;当然如果用户还要另外上自定义的字库的话,可以多增加几个case选项。

在上面的代码中的case 1分支项里面,对选择的字库进行了参数的设置,跟前面我们分析过的ASCII码西文字库中的一样,每个字模所占用的存储单元数量为10个byte,所以Font_Wrod设置为10,X_Witch和Y_Witch分别设置字符的实际宽度和高度,即6*10;而设置Char_TAB值时,这里对驱动中删减掉的前32个ASCII字符进行了补齐,以便于在后面的字符显示程序中计算字模地址利用。
而从上面的代码中,可以看到Font_type的赋值,当选择ASCII字符时,该变量为1。

FontMode函数的代码如下:


3.6.3. 用绘点来绘制字符
如前面所言,本版驱动程序的字符显示程序将以绘点函数为基础,简化字符显示程序的结构,使之更容易被读懂,同时也将为彩色的LCD模块驱动相兼容打下基础。

以绘点来显示字符,实际上就是将一个字符的字模数据的每个位都进行判断;当Font_Cover为0时,如果查询到哪个位上的值非零则对该位所对应的点的位置进行绘点操作,而为零的位对应的点不进行任何操作,这样就产生了字符显示叠加在原背景的效果;而当Font_Cover为1时,则程序中除了对字模中非零的位以当前设置的字符色进行绘点外,还会对为零的位所对应的点以FontMode函数设置的Char_BackColor进行绘点。可以看看以下代码:



函数的一开始便利用前面介绍的Char_TAB(保存有当前选择的字库的首地址)、Font_Wrod(每个字符的字模数据长度)以及传递进来的参数a计算出要显示的字符的字模数据首地址,并保存于指针当中。

随后while((j ++) < Y_Witch)的循环意思就很明了了,也就是指明了要一行一行的显示,Y_Witch在前面已经介绍过了。在循环里面每次都会判断是否超出了Y轴的最大值,如超出则跳出循环。

while(i < X_Witch)的小循环里则是对一行的点进行扫描,即对字模当中的一行的数据位进行扫描判断;循环里面if((i&0x07)==0)则是调整指向字模数据的指针,每个数据位数为8位表示8个点,也就是每8个点的扫描后要使指针指向下一个数据,而Index变量中保存的是针对于当前字符字模数据的偏移量。

接下来的对字模数据从高位开始进行判断,假设Font_Cover=0,如果非零则进行绘点的操作(这时字符的显示会与之前在该位置上的已经显示了的图形进行重叠的)。调用的绘点函数为:Writ_ Dot (x+i,y,Char_Color),参数x和y是传递进来的要显示字符的位置,即左上角的坐标值,当然y值在每一行的扫描显示结束后会自加1,i的变量为当前点在当前行中的列偏移。

如下图所示,即为字符覆盖模式设置为0和1时的效果(覆盖色为0):


字符的显示控制程序其实原理非常简单,无非就是将字模数据对应的位图点矩阵从左上角开始扫描,一行一行的扫描,直到结束,其间如要绘点的地方则绘制点就可以。

在字符显示程序的基础之上,又设计了一个字符串显示的子程序,很简单,代码如下:


3.6.4. Mz的驱动中提供的字符显示
要在MzL02的通用版驱动程序的基础上显示字符,操作非常简单,只需要在显示字符之前设置好选择的字符类型(即选择字库),然后再调用单个字符显示程序(PutChar)或者字符串显示程序(PutString)即可。

要显示驱动当中自带的ASCII码西文字符的话,则要去了解驱动当中定义ASCII码西文字库的类型序号(要给FontSet函数的参数);如果显示用户自行提取的其它字符的字库,则要按上前面所介绍的规则去提取字模并将字模数据加入程序当中形成正确的字库,并作好相关的代码修改,然后调用的方法与ASCII码西文字符的显示是差不多的。

如在MzL02的通用版LCD驱动程序当中就定义ASCII码西文字符库的序号为1,而定义四个汉字“铭正同创”的自定义汉字库序号为2,显控的示意代码如下:


注:以上代码当中,汉字“铭正同创”的字模数据在该字库中的序号分别为0~3。

如果用户需要到的话,可以自行提取要显示的其它字符的字模,并制成字库存放在MCU当中(本驱动仅针对于字库存放在MCU内部的存储器当中,当然如果字库存放在外存的话,也是可以在一定程度上参考的,其实也就是读取字模数据的地方作一下修改即可),然后定义好相关的变量修改相关的设置代码,就可以跟驱动当中自带的字库一样去调用显示了。具体的操作方法这里就不多介绍了,希望读者在前面的介绍的基础之上,去理解显示字符的原理,这样的话是无需教条主义式的按照一条一条一例一例的跟随做法去做;在理解的基础之上做实践操作,这才是目的所在。

 

上一节                    下一节

相关链接


 
关于我们 | 诚邀加盟 | 客户服务 | 相关法律 | 网站地图 | 友情链接 | 服务信箱:service@eefocus.com
© 2006 与非门科技信息咨询(北京)有限公司 All Rights Reserved.