液晶显示在嵌入式系统中的应用_显示光电论文
关键词:嵌入式系统;液晶显示;环形结构算法;汉字显示
1 引言
在嵌入系统中,一个良好的人机界面必须提供友善的菜单,同时应能实现汉字和图形显示,并应提供、数字输入和汉字输入功能。笔者采用香港精电公司的128×64点阵显示模块在以MPC860作为主CPU并以Nuclus PLUS为嵌入式操作系统的系统中进行液晶显示熑〉昧私衔满意的效果。图1所示为其结构框图。
香港精电公司的128×64点阵模块内部自带液晶图形显示控制芯片T6963,其中C/D脚用于控制字与数据,RD和WR分别为读、写使能端。当WR为低时,C/D为高为写命令,C/D为低为写数据;而当RD为低时,C/D为高为读状态牐茫D为低为读数据。另外,CE为器件使能引脚,D0~D7为数据和地址复用总线引脚。
2 应用编程
利用MPC860嵌入式系统的快速性,可将显示应用程序分为两层,其中底层为硬件接口层,上层为应用层。硬件接口层主要是显示液晶模块自带的ASCII函数和显示汉字代码函数。由于硬件各不相同,在此不作具体介绍。而上层应用层的主要功能是提供友善的菜单,同时实现汉字和图形显示,并提供、数字输入和汉字输入功能。由于硬件接口层的隔离作用,不同的系统具有一定的通用性,以下重点介绍应用层编程中的汉字代码编码方法和显示编程的实现这两部分。
2.1 汉字代码编码
一般西文为8×8点阵,因而显示一个西文字需要8个字节煻每个汉字占4个西文字体,因此显示一个汉字需要32个字节。汉字字库表为一张数据表 每个汉字在数据表中,通常由32个字节组成一个点阵图形。由于ASCII码编码是由0X00-0X7F表示,因此熋扛龊鹤挚捎闪礁鲎纸冢埃兀x和0Xyy来表示,每个字节为0X80~0XFF(区别于ASCII代码)。第一汉字定义为0X80 0X80,依此类推直至0X80 0XFF ,0X81 0X80,……,……,0XFF 0XFF ,总计可以定义128×128=16384个汉字。
一个汉字代码表可简单表示为:
hz code table煟桑危预牐渐
//汉字“数”的32字节的点阵图形代码为
0x08煟埃49煟埃2A煟埃08煟埃FF煟埃19煟埃2C煟埃4A
0x10煟埃FE煟埃22煟埃22煟埃14煟埃18煟埃25煟埃42
0x40煟埃40煟埃40煟埃84煟埃FE煟埃08煟埃88煟埃88
0x88煟埃90煟埃50煟埃20煟埃50煟埃88煟埃0E煟埃04
//汉字“据”的32字节的点阵图形代码为
0x10煟埃13煟埃12煟埃12煟埃FF煟埃12煟埃16煟埃1B
0x32煟埃D2煟埃13煟埃15煟埃15煟埃15煟埃59煟埃21
0x04煟埃FE煟埃04煟埃04煟埃FC煟埃20煟埃24煟埃FE
0x20煟埃24煟埃FE煟埃04煟埃04煟埃04煟埃FC煟埃04,
…
}
2.2 显示编程
在系统显示中,主要的显示方式有页处理和行处理两种。系统可以根据按键来显示某一页。实际上,页也是由相应行来显示的。页中的行可由按键来改变。一个页能显示8行ASCII码或4行汉字代码,带有汉字的行一般要占有2个只有ASCII码的行,而页可以由任意多行组成。显示时,通过按键可控制能显示行,并可在行中输入汉字或ASCII码。
在设计中,所有的页可组成一个环形队列结构,页中的行也可组成一个环形队列结构,其关系如图2所示。图3所示是该系统的显示流程。
下面给出一个行结构:
typedef struct lcdLine
{
struct lcdLine *previous //前一行
struct lcdLine *next //后一行
unsigned short lineId //行特征字
unsigned char showflag //是否显示汉字
unsigned char start //显示行号 ,汉字一
定是奇数行如 1,3,5,7
unsigned char lcdseg煟保钉牔
//显示的代码如是ASCII码,0X10显示0,
0X3C显示\ 熀鹤治0X80 0X81 显示汉字“据”
void 煟flcdLine牐煟螅簦颍酰悖 lcdLine * plcdLine牔
//处理行函数
};
由于页是由行组成的,所以页结构的定义如下:
typedef struct lcdPage
{
struct lcdLine *firstLine //该页中的第一行
struct lcdPage *previous //前一页
struct lcdPage *next //后一页
unsigned short pageId //页特征字
} lcdPage
下面给出的是一个环行队列函数的程序代码:
VOID CSC Place On List煟茫 NODE **head CS NODE *new node
{
/* Determine if the list in non-empty. */
if 煟head
{
/* The list is not empty. Add the new
node to the end of the list. */
new node->cs previous=煟head
->cs previous
(new node ->cs previous)->cs
next=new node
new node-> cs next =煟head牔
(new node->cs next)->cs previous
=new node;
}
else
{
/* The list is empty setup the head and
the new node. */
煟head = new node
new node -> cs previous = new node
new node -> cs next = new node
}
}
在建立了上述结构后,便可以得出行队列和页队列的组成方法:
lcdLine lcdLine煟常挨牔
lcdPage lcdPage煟保挨牐 //初始化列
lcdLine煟挨牐.lcdseg煟挨牐剑埃80
lcdLine煟挨牐.lcdseg煟堡牐剑埃80
lcdLine煟挨牐.lcdseg煟菠牐剑埃80
lcdLine煟挨牐.lcdseg煟长牐剑埃BC
lcdLine煟挨牐.lcdseg煟搐牐剑埃80
lcdLine煟挨牐.lcdseg煟丹牐剑埃97
lcdLine煟挨牐.lcdseg煟钉牐剑埃80
lcdLine煟挨牐.lcdseg煟筏牐剑埃98
lcdLine煟挨牐.lcdseg煟袱牐剑埃80
lcdLine煟挨牐.lcdseg煟工牐剑埃99
lcdLine煟挨牐.lcdseg煟保挨牐剑埃00
lcdLine煟挨牐.lcdseg煟保堡牐剑埃00
lcdLine煟挨牐.lcdseg煟保菠牐剑埃00
lcdLine煟挨牐.lcdseg煟保长牐剑埃00
lcdLine煟挨牐.lcdseg煟保搐牐剑埃00
lcdLine煟挨牐.lcdseg煟保丹牐剑埃00
lcdLine煟挨牐.start =1 //第二行起
lcdLine煟挨牐.showflag =1 //汉字
lcdLine煟挨牐lineId =1001; //行标识
煟妫椋颍螅簦欤悖洌蹋椋睿 1牐剑危眨蹋苔
CSC Place On List 煟Γ妫椋颍螅簦欤悖洌蹋椋睿 1 &lcdLine煟挨牐牔 //第一页中的第一行
CSC Place On List煟Γ妫椋颍螅簦欤悖洌蹋椋睿 1煟Γ欤悖洌蹋椋睿澶煟堡牐牔
CSC Place On List 煟Γ妫椋颍螅簦欤悖洌蹋椋睿 1 &lcdLine煟菠牐牔
CSC Place On List 煟Γ妫椋颍螅簦欤悖洌蹋椋睿 1 &lcdLine煟长牐牔犛捎谒男屑纯勺槌梢桓鲅环队列,其中lcdLine煟挨犞付ㄎ第一页的第一个入口行,FirstlcdLine 1与lcdLine为同一行,lcdPage煟挨犚车娜肟谛形firstlcd-Line;lcdPage煟挨牐firstLine=firstlcdLine 1牐欤悖洌校幔纾澶煟挨牐pageID =1001,这样,依据该方法便可以生成任意多的页。具体方法如下:
lcdpage 1=NULL
lcdPage Place On List煟Γ欤悖洌穑幔纾 1 &lcdpage煟挨牐牔
lcdPage Place On List煟Γ欤悖洌穑幔纾 1 &lcdpage煟堡牐牔
lcdPage Place On List煟Γ欤悖洌穑幔纾 1 &lcdpage煟菠牐牔
lcdPage Place On List煟Γ欤悖洌穑幔纾 1 &lcdpage煟长牐牔
lcdPage Place On List煟Γ欤悖洌穑幔纾 1 &lcdpage煟搐牐牔
lcdPage Place On List煟Γ欤悖洌穑幔纾 1 &lcdpage煟丹牐牔
这样,用五页即可组成一个循环队列,其中lcd-page_1与lcdpage煟挨犖同一页。
对于行的显示,最基础的行显示方法如下:
void disp lcd Line煟欤悖洌停澹睿 *lcdm煟酰睿螅椋纾睿澹 char start //START为行号
{
unsigned char i煟欤铮铮穰
unsigned char zt煟t1
unsigned char sign
unsigned char offset
unsigned char offlen
unsigned char *phz
unsigned char z0
phz=煟酰睿螅椋纾睿澹 char *牐Γ瑁 code table
/汉字代码初地址
offset=start*16 //显示的位置 行号 *列号
offlen =0
loop=0
z0=0x00
sign=lcdm->showflag //是否为汉字
while煟欤铮铮穑迹保叮 //在同一行中从0列到15列
{
zt=lcdm->lcdseg煟欤铮铮黏牔 //取第一个代码
if煟t<=0x7F /小于0X80为ASCII代码
{
disp self ascii煟Γt煟雹煟铮妫妫螅澹簦牔
//在本行,显示自有的ASCII代码
if煟螅椋纾睿剑剑保
{
disp self ascii煟Γ0煟雹煟铮妫妫螅澹 16牔
//在上一行,同一列的位置,不显示任何代码
}
offset=offset +1
offlen=offlen +1
loop++
}
else
{
loop++
[1]