王清珍,董健,杨宇
(郑州科技学院信息工程学院,河南郑州450064)
摘要:为了在无线办公门禁系统中实现通过LCD12864显示屏分屏显示多项内容,采用单片机C语言程序设计了多级菜单,应用结构体数组成员的定义,借助按键来改变菜单项的索引号,进行内容的分屏显示及菜单项之间的切换。在多项显示时,同一屏上显示项处于同一级,涉及的变量少,索引号级数少,系统开支就小。设计简化,按键实时性好,界面简单,操作方便。
关键字:LCD12864;多级菜单;结构体数组成员;切换机制
中图分类号:TN911-34;TP368.2 文献标识码:A 文章编号:1004-373X(2015)12-0055-03
收稿日期:2014-10-13
基金项目:国家自然科学基金项目(61272392);河南省教育厅科技攻关基金资助项目(12B510032)
0 引言
在门禁系统中采用的显示设备是LCD12864,此设备在系统中仅显示少量的提示信息,能够满足系统显示需求,但是受显屏显示区域的限制,要显示多项内容,需要分屏显示,在显示的内容之间有上下级和平行级关系,这就需要在显示屏上显示多级操作菜单,每一级菜单都有一些菜单项和对应的按键操作,以及响应各种操作而执行的后续处理程序。需要采用多级菜单来显示与按键进行显示内容的切换。本文根据门禁系统的显示需求,旨在提供一个轻量级的单片机多级菜单实现方法,以较少的系统资源消耗和简单方便的方法完成菜单设计。考虑到菜单程序需要具备3个基本要素:
(1)每个显示界面显示的内容;
(2)显示界面内菜单项之间切换和显示界面之间的切换机制;
(3) 每个显示界面及菜单项对应的按键定义与响应。
本文首先介绍多级菜单的设计思想,进而采用C语言实现结构体的定义和结构体数组成员的定义,接着介绍菜单项之间的切换机制,最后进行了键盘处理模块的设计。
1 多级菜单的设计
多级菜单的基本思想是把多级菜单分层结构,通过索引号贯穿,把全部菜单项拉成一条链,每一个菜单项即为一个结构,而整个菜单即为一结构数组,访问每一个菜单项时,只须获得菜单的索引号,通过索引号找到结构数组中和该菜单项相关的项目,由此可以查询到当前菜单项的数据和所要执行的功能函数[1]。
借鉴李敏通教授提出的一种用一维线性数组实现树形拓扑结构多级菜单的方法,并用C51语言编程验证了这种方法的可行性。该方法对存储资源的利用效率高,逻辑关系清晰,且菜单的建立和修改方便,适合在单片机应用系统中使用[2]。
菜单设计的常用方法是树形拓扑结构法。菜单的树形拓扑结构是多叉树,对于多叉树结构的菜单,为了表示菜单之间的相互关系,必须表示其所有的下级菜单节点。在此控制系统中的菜单项比较少,只分为2级,即上一级(称为父项)和下一级(称为子项),其菜单树如图1所示。再由于每个菜单的下级菜单个数不同,难以用统一的数据结构来描述这种相互关系,在此借助硬件4个按键(确认、上翻和下翻按键、返回按键)进行切换。
树形拓扑结构的实现一般采用链表法[3],这时每个节点中除了要存储有用的信息(即要实现的功能)以外,还要有孩子指针、父亲指针,而这些指针只是为了维持树形结构,其数据结构如下:
//目录结构体定义
struct MenuItem //结构体名称
{ unsigned char MenuCount;
//当前层节点数、每层菜单能显示的条目数
unsigned char *DisplayString; //指向菜单标题的字符串
unsigned char (*Subs)();
//指向当前状态应该执行的功能函数
struct MenuItem *ChildrenMenus;//指向当前菜单的下级菜单
struct MenuItem *ParentMenus;//指向当前菜单的上级菜单
}
在结构体中并没有设置兄弟指针,其中兄弟关系是
通过结构体数组元素个数来实现。例如:
struct MenuItem code MainMenu[5] = //结构体主菜单
{
{5," 找人",&find_person,&Find,&Null},
{5,"调整时间",&time_change,&Null,&Null},
{5,"调整日期",&date_change,&Null,&Null},
{5,"串口传图",&Uart_Camera,&Null,&Null},
{5,"无线传图",&Nrf24L01_Camera,&Null,&Null},
};
struct MenuItem code Find[7] =
{
{7,"王清珍",&person_ui,&Null,&MainMenu},
{7,"杨宇",&person_ui,&Null,&MainMenu},
{7,"王小高",&person_ui,&Null,&MainMenu},
{7,"杨运森",&person_ui,&Null,&MainMenu},
{7,"潭涛",&person_ui,&Null,&MainMenu},
{7,"黄子帆",&person_ui,&Null,&MainMenu},
{7,"王鹏",&person_ui,&Null,&MainMenu},
};
2 界面内容显示
在本系统中此菜单的操作主要包括光标的上下移动、由上级到下一级、由下级返回上一级等。其中由上级到下一级,亦即由父项进入子项,此时只要以当前光标所指的菜单选项的菜单值为菜单数组单元的索引号,找到结构体数组中*ChildrenMenus 所指单元中存的数值,从而实现由上级到下级的操作。同样由下级到上一级,亦即由子项进入父项,此时只要以当前光标所指的菜单选项的菜单值为菜单数组单元的索引号,找到结构体数组中*ParentMenus所指单元中存的数值,从而实现由下级到上级的操作。
按键操作实现包括界面内容显示和多级菜单项的切换,其中关于LCD12864 的程序设计,用到一些显示函数在此略写。源代码设置如下变量:
struct MenuItem(*MenuPoint)= MainMenu;
signed char DisplayStart=0; //显示菜单的开始位置
signed char UserChoose=0; //用户的选择
signed char DisplayStart_Old=0; //保存菜单的开始位置
signed char UserChoose_Old=0; //保存用户的菜单编号
signed char MaxItems=0; //菜单的数量
#define LCD_MAX_DISP_LINES 4 //屏幕最多显示条目数
界面显示如图2 所示,由显示屏和4 个按键组成。
界面显示流程控制如图3所示。
3 多级菜单项的切换机制
门禁系统的菜单操作是以按键形式完成的,分别对应4个功能键:确定键、上翻键、下翻键和返回键。在操作时还要考虑按键的复用,也就是说,同一位置的按键在不同的窗口显示时会有不同的功能定义,因此,要在程序中对按键进行采集、解析键值[4],以便正确响应操作。其代码如下:
//--------------------------------------------------
// [按键说明] *
// [K1] KEY_ENTER(确定)*
// [K2] KEY_DOWN(向上) *
// [K3] KEY_UP(向下) *
// [K4] KEY_ESC(返回) *
//---------------------------------------------------/
void Key_Menu(unsigned char KeyNum)
{i
f(KeyNum != 0)
{
MaxItems = MenuPoint[0].MenuCount; //获取当前菜单的条目数
switch(KeyNum)
{
case K2:
UserChoose --;
if(UserChoose < 0)
{
UserChoose = MaxItems-1;
}
break;
case K4:
if(MenuPoint[0].ParentMenus != &Null)
{
MenuPoint = MenuPoint[0].ParentMenus;
//恢复到之前的选择菜单
UserChoose = UserChoose_Old;
DisplayStart = DisplayStart_Old;
}
break;
case K3:
UserChoose ++;
if(UserChoose >= MaxItems)
{
UserChoose = 0;
}
break;
case K1:
if(MenuPoint[UserChoose].Subs != NullSubs)
//如果操作函数不为空,运行操作函数
{ (*MenuPoint[UserChoose].Subs)();
}i
f(MenuPoint[UserChoose].ChildrenMenus != &Null)
//如果操作函数不为空并且子菜单不为空,则进行菜单切换
{
MenuPoint = MenuPoint[UserChoose].ChildrenMenus;
DisplayStart_Old = DisplayStart;
UserChoose_Old = UserChoose;
UserChoose = 0;
DisplayStart = 0;
}break;
default:break;
}i
f((UserChoose >(DisplayStart+(LCD_MAX_DISP_LINES-1))))
{//菜单翻页
DisplayStart = UserChoose;
}i
f((( UserChoose + MaxItems - DisplayStart)>
(LCD_MAX_DISP_LINES-1))&&(DisplayStart > UserChoose))
{//菜单翻页
DisplayStart = UserChoose;
}
ShowMenu();
}}
4 结语
本文介绍了在门禁系统中多级菜单的设计与切换的实现。采用多级菜单设计大大提高了LCD12864 的显示功能,提供了多功能的操作显示提示,以方便系统的使用。系统开销小,仅靠几个结构体和几个变量即可维护各显示界面及界面内同级菜单项、上下级菜单项之间切换实现。
教育期刊网 http://www.jyqkw.com
参考文献
[1] 宋晓晖,叶桦.基于单片机的多级菜单实现方法改进[J].东南大学学报,2007,37(9):66-70.
[2] 李敏通,张战国.一种建立单片机应用系统菜单的新方法[J].计算机工程,2006,32(16):259-261.
[3] 谭浩强.C语言程序设计[M].2版.北京:清华大学出版社,2011.
[4] 何立民.MCS-51系列单片机应系统[M].北京:北京航空航天大学出版社,2004.
[5] 刘运清.基于单片机的门禁系统的设计与实现[J].中国科技信息,2013(18):80-81.
[6] 黄健,吴永弘,刘乔俊.基于RFID技术的门禁系统的研究[J].数字技术与应用,2014(4):116-118.