基于单片机的VRAM型彩色液晶显示模块设计(二)
扫描二维码
随时随地手机看文章
4 软件系统设计及实现
4. 1 操作YD2502 的程序设计
YD2502 的指令码格式如下:
其中: CA1 ,CA0 组合功能为内部寄存器通道的选择,功能如下:
DISP :显示控制位。
当DISP 设置为“1”时,液晶显示模块为开显示状态。
当DISP 设置为“0”时,液晶显示模块为关显示状态。
X:表示未用位,可设为“0”。
ATmega128 访问外部存储器的软件设计步骤是:先用extern 声明一个外部变量,再用map2ping_init 函数(外部存储地址分配函数) 分配给此变量一个外部存储地址(因A Tmega128 内部有4 kB 的SRAM 所以外部存储地址范围为1000H~0FFFFH) ,那么对该变量的操作就实现了CPU 对相应地址的外部存储空间的访问。
根据此步骤,对YD2502 写指令和写数据的具体函数如下:
extern unsigned char LCD_DA TA ;
void mapping_init (void) {
asm(“。 area memory (abs) n”
“。 org 0x4000n ” / / 分配给LCD_DA TA 的地址为4000H
“ _LCD_DA TA : : . blkb 1\ n”/ / 存储空间为1
“。 text/ n”) ;}
写指令函数如下:
void LCD_writeinstr (unsigned char data) {
PORTD & = 0xFC ; / / 置/ CS 为低电平,并且置RS 为低电平,处于写指令状态
LCD_DA TA = data ; / / 送数据
PORTD | = 0x03 ;} / / 置/ CS 和RS为高电平
写数据函数如下:
void LCD_writedata (unsigned char data) {
PORTD & = 0xFE ; / / 置/ CS 为低,并且置RS 为高电平,处于写数据状态
LCD_DA TA = data ; / / 送数据
PORTD | = 0x01 ;} / / 置/ CS 为高电平除了上面两个基本的函数外,对YD2502 最基本的操作是往VRAM 里写数据,根据上面给出的指令码,具体函数如下:
# define HREG 0x09 / / 显示地址高8 位寄存器指令
# define L REG 0x08 / / 显示地址低8 位寄存器指令
# define DA TARW 0x0A / / 显示数据读写通道指令
void LCD_filldata ( unsigned int address ,
unsigned char data) {
unsigned char addrh ,addrl ;
addrh = (char) (address > > 8) ; / / 取内存地址的高8 位数据
addrl = (char) (address &0xFF) ; / / 取内存地址的低8 位数据
LCD_writeinst r ( HREG) ; / / 送显示地址高8 位寄存器指令
LCD_writedata (addrh) ; / / 送内存地址的高8 位数据
LCD_writeinst r (L REG) ; / / 送显示地址低8 位寄存器指令
LCD_writedata (addrl) ; / / 送内存地址的低8 位数据
LCD_writeinst r (DA TARW) ; / / 送显示数据读写通道指令
LCD_writedata (data) ;} / / 送数据
4. 2 画点函数的实现
要在液晶上实现显示字符和画图等功能,在屏幕上显示一个点是实现这些功能的基础。画点函数实现的步骤是:首先确定该点对应的VRAM中的内存位置,找到该点具体对应的数据位,填充显示颜色的数据,该点就按对应的颜色显示出来了。
4. 2. 1 显示内存与屏幕点阵的对应关系
YD2502 屏幕点阵为320 ×240 ,每一个点对应3 个像素(RGB) ,屏幕上8 个点对应内存3 个字节,一行对应320/ 8 ×3 = 120 个字节,其对应关系如下:
其中R ,G,B 表示红、绿、蓝三原色,D7~D0 表示对应的数据位。
对于屏幕上坐标为( X , Y) 的点,其对应内存地址的计算方法为:
当Y = 0 时 SRAM = 0EFH ×100H +[ IN T( X/ 8) ] ×3
当Y > 0 时 SRAM = ( Y - 1) ×100H +[ IN T( X/ 8) ] ×3
通过( X/ 8) 的余数得出具体的内存位置:
当余数为0 则 RAM = SRAM [ 1110 ,0000 ]
当余数为1 则 RAM = SRAM [ 0001 ,1100 ]
当余数为2 则 RAM1 = SRAM [ 0000 ,0011 ]
RAM2 = SRAM + 1[1000 ,0000 ]
当余数为3 则 RAM = SRAM + 1[0111 ,0000 ]
当余数为4 则 RAM = SRAM + 1[0000 ,1110 ]
当余数为5 则 RAM1 = SRAM + 1[0000 ,0001 ]
RAM2 = SRAM + 2[1100 ,0000 ]
当余数为6 则 RAM = SRAM + 2[0011 ,1000 ]
当余数为7 则 RAM = SRAM + 2[0000 ,0111 ]
其中[ ]内为“1”的位表示应该填充颜色的位置, SRAM 表示该点对应的基础地址, RAM、RAM1 和RAM2 表示该点对应的实际内存地址。
当数据位为“1”时,对应色点为亮;为“0”时,对应色点为暗。通过RGB 三原色组合而得到的8 种颜色代码如下:
例1 :若X 、Y 坐标为(7 ,0)
SRAM = 0EFH ×100H + 0 = 0EF00H
余数为7 ,则 RAM = 0EF00H + 2 = 0EF02H
若此点为红色,则送入0EF02H 内存单元里的数据为[ 0EF02H] &11111000B + 00000100B
例2 :若X 、Y 坐标为(15 ,5)
SRAM = (5 - 1) ×100H + 1 ×3 = 403H
余数为5 ,则 RAM1 = 403H + 1 = 404H
RAM2 = 403H + 2 = 405H
若此点为白色,则送入这两个单元的数据为
[ 404H] &11111110B + 00000001B
[ 405H] &00111111B + 11000000B[!--empirenews.page--]
4. 2. 2 画点函数的具体实现
从例1 和例2 可以看出,要只显示一个色点,就必须知道该点对应的内存中的数据,而前面提到过内存中的数据是不能读出的,所以要将写入内存中的数据先保存起来,即在向YD2502 的显示缓冲区里写数据之前, 应先将此数据写入61LV5128 。若在坐标( X , Y) 处画颜色为color 的点,其具体函数如下:
void LCD_ disppixel ( unsigned int X , unsigned int Y ,unsigned char color) {
unsigned int address ;
unsigned char data ;
address = LCD_pixeladdr ( X , Y) ;
/ / 计算该点对应的内存地址
switch ( X %8) {
case 0 : data = read _ exram ( ad2
dress) ; / / 读取相应SRAM 中的数据
data & = 0x1F; / / [1110 ,
0000]保存其他点的数据
data | = (color < < 5) ;
/ / 填充相应的颜色
write _ exram ( data , ad2
dress) ; / / 把修改好的数据写回到SRAM
LCD_filldata (address ,da2
ta) ; / / 把数据写到液晶显示缓冲区
break ;
……
case 7 : …; break ;}}
以上只给出了余数是0 的情况,其他的情况可依此类推。计算内存地址的LCD_pixeladdr 函数可根据给出的内存地址计算方法编写,读写61LV5128 的read_exram 函数和write_exram 函数可根据具体的硬件设计编写,这里不再给出。
4. 3 显示汉字和其他功能的实现
在屏幕上显示16 ×16 点阵汉字的基本步骤是:首先取得该汉字的32 个字节的点阵数据,再确定屏幕上显示的位置,利用画点函数即可显示该汉字。因本模块使用了硬件汉字库技术,所以汉字的点阵数据是从汉字库中获取的。
在计算机汉字系统中,汉字是用机内码的形式存储的,将汉字机内码减去0A0A0H 就得到该汉字的区位码,通过区位码就可以找到该汉字点阵数据在汉字库中的位置。例如:汉字“中”的机内码是十六进制的“D6D0”,其中前两位“D6”表示机内码的区码,后两位“D0”表示机内码的位码。所以“中”的区位码为0D6D0H - 0A0A0H =3630H ,将区码和位码分别转换为十进制,得汉字“中”的区位码为“5448”。即“中”的点阵位于第54区的第48 个字的位置,在文件HZK16 中的位置为第32 ×[(54 - 1)×94 + (48 - 1)] = 160928D以后的32 个字节为“中”的点阵数据,用SUPER2PRO25 编程器读入文件HZK16 后利用其编辑功能中的缓冲区编辑查找到274A0H (160928D 的十六进制表示) 开始的32 个字节: 01H , 00H ,01H , 00H , 01H , 04H , 7FH , FEH , 41H , 04H ,41H , 04H , 41H , 04H , 41H , 04H , 7FH , FCH ,41H , 04H , 01H , 00H , 01H , 00H , 01H , 00H ,01H ,00H ,01H ,00H ,01H ,00H。这些数据与其点阵图形的对应关系如图4 所示,图中黑色方格表示二进制位“1”,即对应该显示的点,白色方格表示二进制位“0”,即不该显示的点。因此要在液晶屏幕上显示16 ×16 点阵的汉字,首先应找到该汉字在硬件汉字库中的位置,取出其后的32 个字节数据。取这32 个字节数据的函数如下:
图4 汉字“中”的点阵图形
unsigned char chinese[ ] [ 2 ] = {“中”“, 国”} ;
unsigned char buffer [32 ] ;
void LCD_ readdata ( unsigned char num2
ber) {
unsigned char temp1 ,temp2 , k ;
unsigned long address , i ;
temp1 = chinese [ number ] [ 0 ] - 0xA0 ;/ / 把机内码转换成区位码
temp2 = chinese [ number ] [ 1 ] - 0xA0 ;
address = 32 3 ( ( (long) temp1 - 1) 3 94 +( (long) temp2 - 1) ) ; / / 计算该汉字在汉字库中的首地址
k = 0 ;
for ( i = address ; i < address + 32 ; i + + ) {
data = read_exrom( i) ;
buffer [ k ] = data ;
k + + ; }}
读A T29C040A 的read_exrom 函数可根据硬件设计编写,这里不再给出。
取得这32 个字节数据后,下面的程序设计就比较容易了,这里只给出程序流程(如图5 所示) ,具体函数可根据此流程编写。其中( X , Y) 是该汉字显示的起始点, color 是该汉字的显示颜色,number 是该汉字在chinese 数组中的位置。显示英文和数字的函数可根据显示汉字的函数稍加改造后即可得到,这里不再详细分析。
图5 显示一个汉字程序流程图
在本模块中也实现了在屏幕上画斜线、圆等功能,其具体实现过程就是在画点函数的基础上通过相应的算法来编写这些函数。画线和画圆算法比较多,在这里画线算法采用的是整数数字微分分析法,画圆算法采用的是贝森海姆算法。
鉴于篇幅所限,这里不再具体分析。由于YD2502是点阵式液晶显示器, 还可以通过移植嵌入式GUI(如μC/ GUI) 软件,使其显示多种曲线,各种窗口对象,如按钮、编辑框、滑动条等更加丰富灵活的图形界面。
5 结语
以上程序均在ICCAVR 编译器里调试通过,实现了在液晶屏幕上正常显示各种颜色的汉字、英文、数字及简单的图形功能。在笔者参与开发的油田探测爆炸机设备中,采用了本液晶模块,达到了显示稳定,显示色彩丰富,人机界面友好的较理想的显示效果。