1 引言
在本文中,1个元素指的是1个字符,或者是1个汉字(汉字在lcd上所占的显示空间是字符的2倍)。字符包括英文字母、数字、英文标点。1个位置指的是1 个字符在lcd上所占的显示空间的大小。本文中的数组content[],contentram[],contentlcd[]都定义成int8u(8位 无符号整型)里面存的都是汉字国标码和ascall码。
所用的lcd是上海晨兴电子科技有限公司的srl-0978gb液晶模块,1行可以显示21个字符,1屏可以显示5行(分别称为 row0,row1,row2,row3,row4)。这样lcd上就有105个字符位置。从0开始编号。这样1屏就可以显示105个ascall字符,但是能显示多少个汉字了?最多能显示50个汉字。在显示汉字最多的情况下,如果运气好的话还可以显示5个字符。这时候每行只有1个字符。如果你能把这段话 弄明白,那也就知道lcd显示的特点了。
2 菜单的显示
(1) 怎样显示不同的菜单?
在用户界面中,显示最多的就是菜单了。那是怎样显示不同的菜单?
首先,我给每个状态编个状态号,每个状态就对应着不同的菜单。用指向字符串的指针数组来指向不同状态下的菜单。不同状态下都用3个不同的全局变量来分别记 录当前显示屏上在row1行上显示的菜单项的序号,在最后一有效行上显示的菜单项的序号(当该菜单的菜单项的数目小于等于4时,其值为菜单项的数目;当菜单项的数目大于4时,其值为4),和当前反显的菜单项的序号(初始为1,表示反显第一个菜单项。当按下确认键时,表示选中了反显的菜单项)。row0始终 显示菜单的标题。
例如:
#define s_mainmenu 1 file://主菜单的状态号
#define mainmenu_maxlen 6
file://主菜单的菜单项的数目
static char *mainmenu[mainmenu_maxlen+1]=
{ “主菜单”;
“1.家家e”;
“2.短消息”;
“3.通话记录”;
“4.个人助理”;
“5.电话新业务”;
“6.话机设置” };
file://指向主菜单的字符串的指针数组
最开始进入该状 态,smstart=1;
file://在row1行上显示的菜单项的序号
smend=4; file://在最后一有效行上显示的菜单项的序号。
smindex=1; file://反显的菜单项的序号
调用 dispmenu(smmenu,smstart,smend,smindex,sm_maxlen) 函数就可将smmenu的菜单在lcd上顺序显示出标题和1~4号菜单项。这样就有这些菜单项组合方 式:1234,2345,3456,4561,5612,6123
(2) dispmenu函数的实现思路
a) 调用putmsg(0,0,mainmenu[0],0),在row0显示该菜单标题的“主菜单”;
b) 如果smstart>smend(就是第3种和第4种和5种菜单项组合方式),那么就调用putmsg函数从row1行开始依次显示从 smstart开始到sm_maxlen的各个菜单项,然后显示从1到smend的菜单项。每行显示一个菜单项。注意反显。
c) 如果不满足smstart>smend,那就从row1行开始依次显示从smstart到smend的菜单项。同样注意反显。
d) 调用lcddisplay()函数。
putmsg()函数分别调用puthz函数和putzf函数将待显示内容的代码转换成点阵存到disp_ram[][]中,lcddisplay()函 数将disp_ram[][]中的点阵写到lcd的缓存中,就可以显示了.具体说明见后。
3 菜单的翻转
3.1 翻转的操作
在lcd上显示菜单的情况下, 翻转的操作如下:
(1) 单击up键,菜单向上翻。
首先调用overflow(&smstart,&smend,&smindex,sm_maxlen)
对 smstart,smend,smindex进行调整,然后调用dispmenu dispmenu(smmenu,smstart,smend,smindex,sm_maxlen)。
(2) 单击down键,菜单向下翻。
首先调用underflow()对smstart,smend,smindex进行调整,然后调用dispmenu()显示菜单。
(3) 单击enter键,就进入反显的菜单项所对应的新的状态(对该状态下的3个全局变量初始化后,调用dispmenu函数就可以显示该状态的菜单了)
(4) 单击esc键就返回到进入该状态的上1个状态(调用dispmenu函数就显示该状态菜单,该状态的的3个全局变量已经记载了有关参数。)
3.2 overflow函数的实现
(1) 如果满足(smstart= =smindex&&sm_maxlen>4)的条件
a) 如果smstart= =1,则smsatrt=sm_maxlen;否则smstart减1
b) 如果smend= =1,则smend= sm_maxlen,否则smend减1
c) 将smindex改成与smstart相同的值
(2) 如果不满足(smstart= =smindex&&sm_maxlen>4)的条件
smstart和smend不变。
如 果smindex= =1,则smindex=sm_maxlen;否则smindex减1
underflow函数的实现类似于overflow 函数
4 文本的显示
如果我们要显示一段内容,该内容在1屏内显示不完。那么如何知道第1屏显示到什么元素结束,第2屏,第3屏……显示的内容该从哪个元素开始,该到哪个元素 结束了?初看起来这个问题是很简单的,其实不然。在lcd的每1行的最后1个位置上如果要显示1个汉字是不可能的,这样就需要把要显示的汉字挪到下1行显 示。也正是这个原因导致了需要确定以后的各屏该从哪个元素开始。
所用的办法如下:
4.1 要显示的内容是固定不变的
若要查看某条短消息的内容,但不对内容进行修改。
假如短消息的整个内容都保存在数组content[]中。我们现在要显示content[]的内容。
(1) 先将数组content[]中的内容拷贝到数组contentram[]中。contentram[]是1个虚拟的lcd屏,该屏的空间比实际的屏的空间 大很多。contentlcd[]是1个与实际屏一样大小的数组。注意在拷贝完后,在contentram[]末尾加个结束符。
该拷贝所做的就是调整content[]中内容的位置,让调整后的内容符合lcd显示的原则,该原则就是在lcd每行的最后1个位置上不可能显示1个汉 字。因此要用空格来补充该位置,该汉字放在下1行开始。
(2) 从content[]到contentram[]的拷贝完成后,根据j的值就可以知道短消息的内容一共要显示几屏了。一般在显示短消息内容的第一屏的时候需要在row0上显示一行标题。netpagemax是该短消息共占有的屏数。
(3) 用netpage表示要显示的是哪一屏内容,从1开始计数,一开始的时候其值为1。
按up键,netpage减1,如果netpage==0,则 netpage变为1
按down键,netpage加1,如果netpage==netpagemax+1,则netpage变为 netpagemax
a) netpage= =1时,将contentram〔i〕(i从0到83)拷贝到contentlcd[]中,如果没有拷贝到83号就提前遇到了结束符,那就不必继续拷贝 了。然后调用putmsg函数将contentlcd[]从lcd的row1行输出。row0用作显示标题。
b) netpage!=1时,将*(contentram+(netpage-2)*105+84+i),(i从0到104)拷贝到contentlcd[] 中,如果没有拷贝到103号就提前遇到了结束符,那就不必继续拷贝了。然后调用putmsg函数将contentlcd[]中的内容从row0行输出。
4.2 要显示的内容是变化的
例如要编辑条短消息,且短消息的内容就是变化的。
content[]用来存编辑的短消息的内容。convertindex用来表示反显的是几号元素(从1号开始编号),它是个实实在在的东西,用户看到反 显的元素就知道convertidex是多少了。cursorindex用来表示光标在几号位置上(从1号开始编号),它是一个虚拟的东西,并不通过什么记号显示给用户看,它是用来辅助计算convertindex的值的。这里的反显相当于电脑上的光标。删除是删除反显的元素,插入是在反显元素的前面插入。
由于convertindex和cursorindex所用的单位不一致,就存在相互的转换问题,并且需要保持两者的同步。这两个变量是相对 content[]里的内容而言的。
假如短消息的整个内容放在content[]中,且内容最多有255个字符。我们现在要显示content[]的内容。假如其中的内容是“我最近忙着做毕 业设计,你们在芒什么了?”,我现在发现写了错字,我将反显移动到“芒”上,这时,cursorindex为29,convertindex为15。
现在要将content[]中的内容显示在lcd上。
(1) 将content[]中的内容拷贝到contentram[]中。如何拷贝同上。
并且要从content[]中的cursorindex推算出contentram[]中的cursorindextemp的值。
将 cursorindex加上在拷贝content[cursorindex]之前所填补的空格数就是cursorindex的值。显示第1屏时,row0 显示标题。显示非第1屏时,row0也用来显示内容了。row4不显示内容,用来在汉字输入法下显示供选择的拼音组合和汉字组合
(2) 我们在编辑短消息的内容时,cursorindex和convertindex都在不断的变化。同时虚拟屏contentram[]中的 cursorindextemp也是在不断变化的。根据cursorindextemp可以确定应该将哪一屏内容显示在lcd上。netpage用来记录 应该显示的屏的序号(从1开始计数)。
(3) 用netpage表示要显示的是哪一屏内容,从1开始计数。它由cursorindextemp确定
a) netpage==1时,将contentram〔i〕i从0到62拷贝到contentlcd[]中,如果没有拷贝到62号就提前遇到了结束符,那就不 必继续拷贝了。然后调用putmsg函数将contentlcd[]从lcd的row1输出。row0用作显示标题。
b) netpage!=1时,将*(cont




