LCM(LCD Module)即LCD显示模组、液晶模块,是指将液晶显示器件,连接件,控制与驱动等外围电路,PCB电路板,背光源,结构件等装配在一起的组件。
1、时序
LCD一般需要三个时序信号:VSYNC、HSYNC和VCLK。VSYNC是垂直同步信号,在每进行一个帧(即一个屏)的扫描之前,该信号就有效一次,由该信号可以确定LCD的场频,即每秒屏幕刷新的次数(单位Hz)。HSYNC是水平同步信号,在每进行一行的扫描之前,该信号就有效一次,由该信号可以确定LCD的行频,即每秒屏幕从左到右扫描一行的次数(单位Hz)。VCLK是像素时钟信号。
s3c2440处理LCD的时钟源是HCLK,通过寄存器LCDCON1中的CLKVAL可以调整VCLK频率大小,它的公式为:
VCLK=HCLK÷[(CLKVAL+1)×2]
例如,HCLK的频率为100MHz,要想驱动像素时钟信号为6.4MHz的LCD屏,则通过上式计算CLKVAL值,结果CLKVAL为6.8,取整后(值为6)放入寄存器LCDCON1中相应的位置即可。由于CLKVAL进行了取整,因此我们把取整后的值代入上式,重新计算VCLK,得到VCLK=7.1MHz。
按理说,对于一个已知尺寸(即水平显示尺寸HOZVAL和垂直显示尺寸LINEVAL已知)的LCD屏,只要确定了VCLK值,行频和场频就应该知道了。但这样还不行的,因为在每一帧时钟信号中,还会有一些与屏显示无关的时钟出现,这就给确定行频和场频带来了一定的复杂性。如在HSYNC信号先后会有水平同步信号前肩(HFPD)和水平同步信号后肩(HBPD)出现,在VSYNC信号先后会有垂直同步信号前肩(VFPD)和垂直同步信号后肩(VBPD)出现,在这些信号时序内,不会有有效像素信号出现,另外HSYNC和VSYNC信号有效时,其电平要保持一定的时间,它们分别叫做水平同步信号脉宽HSPW和垂直同步信号脉宽VSPW,这段时间也不能有像素信号。因此计算行频和场频时,一定要包括这些信号。HBPD、HFPD和HSPW的单位是一个VCLK的时间,而VSPW、VFPD和VBPD的单位是扫描一行所用的时间。在s3c2440中,所有的这些信号(VSPW、VFPD、VBPD、LINEVAL、HBPD、HFPD、HSPW和HOZVAL)都是实际值减1的结果。这些值是通过寄存器LCDCON2、LCDCON3和LCDCON4来配置,只要把这些值配置成与所要驱动的LCD中相关内容的数据一致即可。例如,我们所要显示的LCD屏大小为320×240,因此HOZVAL=320-1,LINEVAL=240-1。水平同步信号的脉宽、前肩和后肩分别为30、20和38,则HSPW=30-1,HFPD=20-1,HBPD=38-1;垂直同步信号的脉宽、前肩和后肩分别为3、12和15,则VSPW=3-1,VFPD=12-1,VBPD=15-1。
下面我们就具体计算一下行频(HSF)和场频(VSF):
HSF=VCLK÷[(HSPW+1)+(HSPD+1)+(HFPD+1)+(HOZVAL+1)]
=7.1÷408=17.5kHz
VSF=HSF÷[(VSPW+1)+(VBPD+1)+(VFPD+1)+(LINEVAL+1)]
=17.5÷270=64.8Hz
在有些情况下,s3c2440的LCD时钟信号的默认极性与所控制的LCD时钟信号的极性相反,这时可以通过寄存器LCDCON5的相关位来改变某些时钟信号的极性。
2、显示缓存区
只要把所要显示的数据放入显示缓存区内,就可以在屏幕上呈现内容。该缓存区是我们自己编程时开辟的一段内存区。一般我们是通过定义一个与屏幕尺寸大小相同的二维数组来开辟该空间的,这样控制屏幕内容会方便一些,如当屏幕的尺寸为320×240时,可以定义该缓存区为LCD_BUFFER[240][320]。由于s3c2440支持16位和24位的非调色板真彩色的TFT型LCD模式,而24位颜色模式是用32位数据来表示的,所以前面定义的那个二维数据的数据类型应该是半字整型或全字整型的。例如,在24位颜色模式下,我们想要在尺寸大小为320×240屏幕的中心处设置为白色像素,则:LCD_BUFFER[120][160]=0xffffffff。
在s3c2440中,寄存器LCDSADDR1和LCDSADDR2用于设置显示缓存区,即把我们定义的那个二维数组告诉s3c2440。其中LCDBANK的9位数据指定LCD的BANK,即显示缓存区的第30位到第22位地址;LCDBASEU的21位数据指定了LCD的基址,即显示缓存区开始地址的第21位到第1位;LCDBASEL的21位数据指定了LCD的尾址,即显示缓存区结束地址的第21位到第1位。例如,我们想要在尺寸为320×240的屏幕上显示24位颜色,定义的显示缓存区数组为LCD_BUFFER[240][320],则LCDBANK等于LCD_BUFFER的第30位到第22位数据值(因为LCD_BUFFER表示的就是数组的首地址),LCDBASEU等于LCD_BUFFER的第21位到第1位数据值,由于是用32位数据表示24为颜色,因此每个像素值是4个字节,所以LCDBASEL等于(LCD_BUFFER+(240×320×4))结果的第21位到第1位的数据值。另外寄存器LCDSADDR3有两个内容:OFFSIZE和PAGEWIDTH。OFFSIZE用于虚拟屏幕的偏移长度,如果我们不使用虚拟屏幕,就把它置为0;PAGEWIDTH定义了视口的宽,单位是半字,如在上面的例子中,PAGEWIDTH应该为320×32÷16。
其实每一字符就是一幅图像,字符的大小对应于图像的大小,字符的笔画对应于图像的内容。那么如何把字符转换为图像呢?简单的方法是使用“字模提取”之类的软件,它能够把任意的字符转换为一个字节型的数组,数组元素中的每一位代表LCD上的一个像素点,当为1时,表示该位置为字符的一个笔画,需要上色,而为0时,表示不是笔画,不需要上色。例如,一个字符想要在16×16的面积上显示,即该字符的宽和高各为16个像素,因为每一个像素用一位来表示,因此用字模提取软件生成的字节型数组,一共有16×16÷8=32个字节。在字模提取的过程中,还要注意取模的顺序,顺序不同,得到的数组就不同,一般来说是从字符的左上角开始,从左向右,从上到下取模,这样程序编写上会方便一些。相同字体大小的中文字符和ASCII码字符的宽度还有所不同,一般ASCII码字符的宽度是中文字符宽度的一半,所以显示中文字符的程序和显示ASCII码字符的程序还略有不同。
当把一个字符取模变成一个数组后,只要对该数组中每个元素的每一位依次进行判断,对值为1的位和值为0的位进行不同的上色处理,即可完成一个字符的绘制。
点阵图形式液晶由M 行×N 列个显示单元组成,假设LCD 显示屏有64行,每行有128 列,每8 列对应1 个字节的8 个位,即每行由16 字节,共16×8=128个点组成,屏上64×16 个显示单元和显示RAM 区1024 个字节相对应,每一字节的内容和屏上相应位置的亮暗对应。例如屏的第一行的亮暗由RAM 区的000H~00FH 的16 个字节的内容决定,当(000)=FFH 时,则屏的左上角显示一条短亮线,长度为8 个点;当(3FFH)=FFH 时,则屏的右下角显示一短亮线;当(000H)=FFH,(001H)=00H,(002H)=FFH,(003H)=00H,…(00EH)=FFH,(00FH)=00H 时,则在屏的顶部显示一条由8 段亮线和8 条暗线组成的虚线。
汉字的显示一般采用图形方式,事先从微机中提取要显示的汉字的点阵码,每个汉字占32 字节,分左右两半部,各占16 字节,左边为1、3、5…,右边为2、4、6…, 根据在LCD 上开始显示的行列号及每行的列数可找出显示RAM 对应的地址,设立光标,送上要显示的汉字的第一个字节,光标位置加1,送第二字节,换行按列对齐,送第三字节…直到32 字节显示完就可在LCD 上得到一个完整的汉字。
如果要在程序中显示大量的中文字符,是不是要把这些字符都取模啊?回答是肯定的,但前人已经为我们完成了这一步,做成了数据库,并且进行了编码,只要按照编码规则调用该库文件,就可以检索到相要的字符。下面就来说说编码规则:每个汉字是由两个字节表示的,前一个字节表示的区号,后一个字节表示的位号,那么汉字在汉字库中的位置为:94×(区号-1)+(位号-1)。94表示的是每个区里一共有94个汉字,减1表示的是数组是从0开始,而区号和位号是从1开始的。具体到汉字在某一数据库中的位置,还需要乘以一个汉字字模所占的字节数,即[94×(区号-1)+(位号-1)]×一个汉字字模所占字节数。如一个字模大小为16×16的宋体数据库,库里每个汉字所占的字节为16×16÷8=32,则每个汉字在该宋体数据库中的位置为:[94×(区号-1)+(位号-1)]×32。ASCII码的字符调用比汉字字符要简单,只要把它乘以字模所占字节数即可找到该字符所在字库的位置,如8×16的ASCII字库,ASCII码在该字库的位置为ASCII×16。如果中文字符和ASCII码混合在一样,如何区分它们呢?其实也很简单,ASCII码的最高位是0,而中文的最高位是1,因此当读取到的一个字节的最高位是0,则该字节为ASCII码,它的下一个字节与这个字节无关;当取得到的字节的最高位是1,则表示的是中文字符,并且该字节与它的下一个字节组合在一起表示完整的一个汉字。
编码规则介绍完了,那么如何打开字库呢?我们可以利用前人已做好的字库,然后像访问一般文件一样打开它。另一种方法是把字库变换成一个超大的数组,那么我们就可以像操作数组一样读取字库了(在这里,我们使用的是这种方法)
当用LCD显示一个字符时就较复杂了,因为一个字符由6×8 或8×8 点阵组成,即要找到和屏上某几个位置对应的显示RAM区的8 个字节,并且要使每个
字节的不同的位为‘1’,其它的为‘0’,为‘1’的点亮,为‘0’的点暗,这样一来就组成某个字符。但对于内带字符发生器的控制器(如T6963C)来说,显示字符就比较简单了,
可让控制器工作在文本方式,根据在LCD 上开始显示的行列号及每行的列数找出显示RAM对应的地址,设立光标,在此送上该字符对应的代码即可。