分享

点阵式液晶屏的显示原理与驱动设计(二)

 朱子俊 2020-10-19

第一部分介绍了控制器是如何将CGRAM中的存储数据显示到LCD面板上的。下面继续,介绍下单片机或者电脑如何将一个汉字的信息发送到控制器,也就是驱动代码的编写。

这部分驱动代码是针对单片机来说的,但是即使是对于Linux操作系统来说,它的显示驱动部分,如果不考虑操作系统接口相关部分的处理,核心部分的代码跟单片机的驱动代码还是非常类似的。

LCD驱动设计,首先要解决的就是汉字的点阵化问题。因为从上一节的介绍,已经可以知道,LCD面板显示的图形或者汉字,实际上就是存储在GCRAM里面的数据,而我们的汉字,是一种图形化的文字工具,所以汉字或者图形想要在LCD面板上显示出来,就首先要点阵化,或者说数字化,如图 1所示。

点阵式液晶屏的显示原理与驱动设计(二)

图 1 点阵化的汉字

我国早期的计算机工作者们,就是这么解决汉字的问题的。最早可以追溯到DOS时代,80年代的时候就推出了汉字点阵的字库标准GB2312,例如早期的12号宋体汉字字库HZK16,现在还在广泛使用。

那么字库里面存储的是什么内容呢,实际上就是点阵化的汉字字体。还拿HZK16为例,在这个字库里面,所有汉字都标准化成了16x16点阵的汉字。如果LCD显示还是以8像素为单位的话,那么一个汉字就变成了32个字节的数据。这样的话,计算机就可以进行处理了。

汉字放在了字库里面,那么如何提取出来呢?相对于西文字符,中文字符就比较麻烦。因为拿英文来说,只有26个英文字母,存进去就可以了,然后使用ASCII码,连同各种标点符号和控制符号在内,总共才128个字节,输入一个单字节16进制数就能表示某个字符。但是汉字不行,有几千个汉字呢。

前辈们有办法,提出了区位码的概念。用一个16位的数,高8位代表区码,有256个区,低8位代表位码,每个区有256个位。这样256x256就可以表示65536个汉字呢,足够了。这也是我们现在用的汉字输入法的基础。无论哪种输入法,拼音也好,五笔也好,键盘输入对应汉字表示后,输入法软件会通过查询区位码,列出来该表示的所有候选字组合,用户再选择后,就从字库里面选择对应汉字的点阵数据,如果是HZK16字库的话,就是32个字节数据,然后数据发送到屏幕上,我们就能看到汉字了。

早期字库提供的字号比较少,如HZK12、HZK16、HZK24等字库本身只提供10号、12号等少数几个字号字体,提供字体也比较少,只有宋体、仿宋等几种。如果文字处理软件想要其他字号,就需要用软件的方法,插值算出来其他数据,然后送LCD显示,不可避免的字体放大后有毛刺、锯齿的问题,所以后来出现了矢量字体。所谓矢量字体,其实就是存储的128x128点阵的字体,只要字体原始数据够大,放大以后就能保证足够清晰。

上面说的都是PC机里面的汉字的处理,很多驱动的工作都由操作系统完成了,用户只是使用就行了。但是单片机不行,由于没有操作系统支持,所以很多处理就需要自己做。下面说说单片机如何显示汉字。

首先是汉字存储。由于大多数单片机存储比较小,所以很难存储下整个字库文件,所以在使用的汉字较少的时候,都是使用字库提取软件,如图 2,将需要的汉字从字库里提取出来,存放到ROM中去。

点阵式液晶屏的显示原理与驱动设计(二)

图 2 字库提取软件

很多LCD供货商会研发一个类似字模提取软件,可以免费使用。由于LCD面板在显示的时候,可以横向8个像素对应一个字节,也可以竖向8个像素对应一个字节,所以很多字库软件也提供了对应的选项,可以横向取模或者纵向取模。有些软件甚至还可以选择取模的顺序。比如在横向取模模式下,选择按照1、2、3、4、5。。。的顺序取模还是按照1、3、5、7.。。2、4、6、8的顺序,如图 3所示。不同的取模方式,不同的顺序,提取出来的数据肯定就不一样了。那么做驱动的时候,就要把提取时候的顺序跟在屏幕上的显示位置一一对应起来,这样才能把一个汉字在屏幕上还原出来。

点阵式液晶屏的显示原理与驱动设计(二)

图 3 取模顺序

然后是字库数据的使用,字库提取出来以后,一般是以ROM数组的方式存放在FLASH中,使用的时候根据汉字存放次序,将单个汉字的点阵数据读出来,发送到CGRAM中,供CGRAM显示。这部分功能也是LCD显示驱动主要做的工作。

点阵式液晶屏的显示原理与驱动设计(二)

图4 nokia 7110 LCD

以SED1565控制器的NOKIA7110手机黑白LCD屏为例,屏幕的分辨率为95x65,它的16x16汉字显示的驱动代码如下:

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

**函数名称:LCD_HZ()

**函数功能:显示一个汉字16*16点阵

**函数入口:x,y 汉字的坐标; *s 字库入口

**函数出口:

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

void lcd_HZ(char x,char y,char *s)

{

char i;

y=y*16;

for(i=0;i<16;i++)

{

lcdpixel(x,y+i,s[i]);

}

for(i=16;i<32;i++)

{

lcdpixel(x+1,y+i-16,s[i]);

}

}

其中x,y参数,是汉字在屏幕的显示位置(注意x坐标是8个像素为单位计算的),s是存储汉字数据的数组名字,是个二位数组。很明显两个16次的for循环,是发送了32个字节的数据到CGRAM,正好是一个汉字的数据。这是一个横向取模的16x16点阵汉字的点阵数据,所以看到x、y坐标的变换情况,第一个循环发送汉字的左半边,x不变,y不停在加一;第二个循环发送汉字的右半边。所以第二次循环的时候,x坐标要加一,代表右边的8个像素,然后y从0开始数,因为发送左半边的时候,y已经到了汉字的最底下。

这样使用的时候,通过输入汉字的坐标,以及存储的汉字的次序,就可以在屏幕上打印汉字了。

lcd_HZ(0,i,HZ1[i]);

其中HZ1[1]就是汉字的存储数组。

unsigned char code HZ1[][32]=

{/*-- 文字: 你 --*/

/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/

0x00,0x80,0x60,0xF8,0x07,0x40,0x20,0x18,0x0F,0x08,0xC8,0x08,0x08,0x28,0x18,0x00,

0x01,0x00,0x00,0xFF,0x00,0x10,0x0C,0x03,0x40,0x80,0x7F,0x00,0x01,0x06,0x18,0x00,

/*-- 文字: 好 --*/

/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/

0x10,0x10,0xF0,0x1F,0x10,0xF0,0x00,0x80,0x82,0x82,0xE2,0x92,0x8A,0x86,0x80,0x00,

0x40,0x22,0x15,0x08,0x16,0x61,0x00,0x00,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,

这样就完成了一个汉字的显示。由于汉字是一种简单的图形,所以图形在LCD的显示方式跟汉字还是非常相似的,只要可以把点阵提取出来,就能显示。特别是对于bmp图形的显示,由于bmp图像没有压缩,本身文件内容就是每个像素点的坐标位置跟颜色信息,所以bmp图像是可以直接读取然后显示在彩色LCD屏幕上的。至于其他的图形文件由于经过了压缩,所以需要特殊处理,获取图形的点阵信息后才能显示。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多