(完整版)单片机多级菜单编程实现
msp430单片机12864二级菜单
#include <msp430x14x.h>#define uchar unsigned char#define uint unsigned int#define LCD_data P5DIR=0XFF //数据口输出#define LCD_CMDOUT P3DIR|=0xe0 //P3口的高三位设置为输出#define LCD_RS_LOW P3OUT &= ~BIT7 //RS=0#define LCD_RS_HIGH P3OUT |=BIT7 //RS=1#define LCD_RW_LOW P3OUT &= ~BIT6 //RW=0#define LCD_RW_HIGH P3OUT |=BIT6 //RW=1#define LCD_EN_LOW P3OUT &= ~BIT5 //EN=0#define LCD_EN_HIGH P3OUT |=BIT5 //EN=1uchar k=0,flag=0,flag1=0;uchar dis1_[] = {"系统初始化. "};uchar dis2_[] = {"系统初始化.. "};uchar dis3_[] = {"系统初始化... "};uchar dis4_[] = {" 按选择键开始! "};uchar dis1[] = {"手1:手机设定"}; //一级菜单1uchar dis2[] = {"机2:管理器"}; //一级菜单2uchar dis3[] = {"菜3:通话"}; //一级菜单3uchar dis4[] = {"单4:信息功能"}; //一级菜单5uchar dis5[] = {"手5:文件管理"}; //一级菜单7uchar dis6[] = {"机6:通讯录"}; //一级菜单8uchar dis7[] = {"菜"}; //一级菜单8uchar dis8[] = {"单"}; //一级菜单8uchar dis1_1[] = {"手1:时间和日期"}; //一级菜单1下的子菜单1 uchar dis2_1[] = {"机2:语言"}; //一级菜单1下的子菜单2 uchar dis3_1[] = {"设3:语音控制"}; //一级菜单1下的子菜单3 uchar dis4_1[] = {"定4:关闭无线电"}; //一级菜单1下的子菜单4uchar dis1_2[] = {"管1:闹铃"}; //一级菜单2下的子菜单1 uchar dis2_2[] = {"理2:视频电话"}; //一级菜单2下的子菜单2 uchar dis3_2[] = {"器3:日历"}; //一级菜单2下的子菜单3 uchar dis4_2[] = {" 4:任务"}; //一级菜单2下的子菜单4uchar dis1_3[] = {"通1:全部"}; //一级菜单3下的子菜单1 uchar dis2_3[] = {"话2:已接来电"}; //一级菜单3下的子菜单2 uchar dis3_3[] = {" 3:未接来电"}; //一级菜单3下的子菜单3 uchar dis4_3[] = {" 4:已拨电话"}; //一级菜单3下的子菜单4uchar dis1_4[] = {"信1:编写新信息"}; //一级菜单4下的子菜单1uchar dis2_4[] = {"息2:收件箱"}; //一级菜单4下的子菜单2uchar dis3_4[] = {"功3:电子邮件"}; //一级菜单4下的子菜单3uchar dis4_4[] = {"能4:草稿箱"}; //一级菜单4下的子菜单4uchar dis1_5[] = {"文1:相册"}; //一级菜单5下的子菜单1uchar dis2_5[] = {"件2:音乐"}; //一级菜单5下的子菜单2uchar dis3_5[] = {"管3:视频"}; //一级菜单5下的子菜单3uchar dis4_5[] = {"理4:图片"}; //一级菜单5下的子菜单4uchar dis1_6[] = {"通1:快速拨号"}; //一级菜单6下的子菜单1uchar dis2_6[] = {"讯2: 我的名片"}; //一级菜单6下的子菜单2uchar dis3_6[] = {"录3: 组群"}; //一级菜单6下的子菜单3uchar dis4_6[] = {" 4:特定号码"}; //一级菜单6下的子菜单4void delay_1ms(uint x){uint i,j;for(j=0;j<x;j++)for(i=0;i<113;i++);}void write_cmd(uchar cmd)//写指令数据到LCD :RS=L,RW=L,E=高脉冲,D0-D7=指令码{LCD_RS_LOW ;LCD_RW_LOW ;LCD_EN_LOW ;P5OUT = cmd;delay_1ms(1);LCD_EN_HIGH;delay_1ms(1);LCD_EN_LOW;}void write_dat(uchar dat)//写显示数据到LCD :RS=H,RW=L,E=高脉冲,D0-D7=数据。
单片机汇编语言下LCD多级菜单的一种实现方法
单片机汇编语言下LCD多级菜单的一种实现方法万方数据万方数据单片机汇编语言下LCD多级菜单的一种实现方法作者:高璇作者单位:安徽理工大学电气与信息工程学院,安徽,淮南,232001;中煤北京煤矿机械有限责任公司设备动力部,中国,北京,102400 刊名:科技信息英文刊名:SCIENCE & TECHNOLOGY INFORMATION年,卷(期):2010,(31)被引用次数:0次参考文献(3条)1.ST7920控制器系列中文字库液晶模块中文说明书 20052.STC89C51RC/RD+系列单片机器件手册 20033.蔡美琴MCS-51系列单片机系统及其应用 2005相似文献(10条)1.会议论文宋晓辉.叶桦.丁昊基于单片机的多级菜单实现方法改进2007介绍了一种在C语言环境下,基于单片机的多级菜单实现方法.该方法从菜单的功能结构发,在程序设计中做了几点改进.首先对菜单数据项和功能函数各自进行独立设计,通过在数据结构中增加按键有效标志、字符串指针、存储器地址以及与复用相关的元素,实现了两者源代码空间的有效分离,从而大大提高了程序的可维护性;其次引入菜单项复用的思想,简化了程序结构.该设计的多级菜单在自动售货机的服务模式的实际应用表明,此改进方法使菜单设计变得更为简单方便,软件通用性更高,维护更容易.2.期刊论文陆铮.罗嘉单片机C语言下LCD多级菜单的一种实现方法-工矿自动化2006(1)介绍了在C语言环境下,在LCD液晶显示屏上实现多级嵌套菜单的一种简便方法,提出了一个结构紧凑、实用的程序模型.3.期刊论文宋晓辉.叶桦.丁昊.Song Xiaohui.Ye Hua.Ding Hao基于单片机的多级菜单实现方法改进-东南大学学报(自然科学版)2007,37(z1)介绍了一种在C语言环境下,基于单片机的多级菜单实现方法.该方法从菜单的功能结构发,在程序设计中做了几点改进.首先对菜单数据项和功能函数各自进行独立设计,通过在数据结构中增加按键有效标志、字符串指针、存储器地址以及与复用相关的元素,实现了两者源代码空间的有效分离,从而大大提高了程序的可维护性;其次引入菜单项复用的思想,简化了程序结构.该设计的多级菜单在自动售货机的服务模式的实际应用表明,此改进方法使菜单设计变得更为简单方便,软件通用性更高,维护更容易.4.期刊论文唐炜.卢道华.顾金凤单片机系统中液晶显示多级菜单的软硬件设计-华东船舶工业学院学报(自然科学版)2003,17(1) 以8031单片机控制GXM-12864液晶显示器为例,通过建立小字库,结合具体实例介绍了实现多级菜单显示的方法.当菜单显示内容改变时,只需修改相应参数,而不修改程序.文中提及的硬件电路和软件设计通用性较强,具有更一般的实际意义.5.期刊论文汪高勇.宋毅恒.尚举邦.WANG Gao-yong.SONG Yi-heng.SHANG Ju-bang C51与单片机系统多级菜单的模块化设计-光电技术应用2009,24(2)介绍了一种基于单片机系统的多级菜单模块化编程方法.该方法从模块化的角度将菜单编程简单地划分为共用键盘处理和菜单模块两部分,使得菜单具有通用的模块化结构,方便了菜单的加载与卸载,增强了C51语言在单片机系统人机接口的设计,软件结构清晰,维护方便.6.期刊论文朱青.张兴敢.柏业超.ZHU Qing.ZHANG Xing-gan.BAIYe-chao一种多功能水情自动测报系统设计-现代电子技术2011,34(3) 为满足当前水情数据测报的要求,设计实现了一种多功能水情自动测报系统.该系统基于PIC16F887单片机、GSM模块,可接收多种形式的传感器信号,并存储在大容量的FLASH存储器中,同时通过GSM模块发送水情数据和报警信息.另外,该系统借助LCD液晶显示屏可显示多级中文菜单,方便控制和查询.该系统的功耗低,体积小,功能扩展性强,经过多次测试,操作方便,工作可靠,在水情自动测报领域具有很大的推广价值.7.期刊论文王运良.张建忠.程明.WANG Yun-liang.ZHANG Jian-zhong.CHENG Ming基于ATmega16L单片机的中文菜单显示技术-江苏电器2006(1)针对目前电力测量仪表广泛使用中文液晶显示器的趋势,介绍一种由ATmega16L单片机和液晶MSC-G12864组成的多级中文菜单滚动显示系统,应用结果证明该实现方法简单,系统易于扩展和维护.描述了硬件电路的结构,详细分析了多级菜单软件的实现方法,包括中英文字符的存储,菜单项的构成以及整个菜单的滚动显示,给出了部分程序清单.8.期刊论文李敏通.张战国.LI Mintong.ZHANG Zhanguo一种建立单片机应用系统菜单的新方法-计算机工程2006,32(16) 提出了一种用一维线性数组实现树形拓扑结构多级菜单的方法,并用C51语言编程验证了这种方法的可行性.该方法对存储资源的利用效率高,逻辑关系清晰,且菜单的建立和修改方便,适合在单片机应用系统中使用.9.期刊论文基于单片机实现的实用汉字液晶显示设计方法-硅谷2009(19)介绍一种在多级菜单界面设计上非常简单实用的采用C51语言实现液晶显示的方法;同时介绍自定义字库和硬件汉字库的设计方法和应用.10.期刊论文陈国鹏.Chen Guopeng基于PIC18F6622的人机界面设计-工业控制计算机2009,22(9)介绍了如何使用PIC单片机PIC18F6622和液晶模块MTG-S32240进行显示控制系统的设计,分析了其硬件平台的设计要点,给出了清晰的人机界面软件设计架构,介绍了其中最主要的多级菜单的设计方法.设计的显示控制系统在实际系统中运行稳定可靠,证明了设计方法的正确性.本文链接:/doc/887e05f29e31433239689316.html /Periodical_kjxx201031057.aspx授权使用:南华大学(nhdx),授权号:af1513e4-a30e-4369-9f7f-9f1000acb2e6下载时间:2011年6月28日。
12864并行多级菜单程序
#include "includes.h"u8 key=0,hua;extern u32 Second;extern u32 minite,hour,day,k,month,year,shan;u8 xingqi[]={"一二三四五六日"};u8 ModeFlag=0,wei=0;//液晶界面选择int main(void){u8 PasswordIndex=0;//密码数组索引u8 Password[4]={" "};//存储密码数组BSP_Init();//初始化外部资源ModeFlag=0;while(1){//////////////////////////////////////// 界面一//////////////////////////////////if(ModeFlag==0){ LCD12864_Waddr(1,3);LCD12864_WPoss(0,"WELCOME!");LCD12864_Waddr(2,2);LCD12864_WPoss(0,"--欢迎使用--");Delay_1ms(8000);LCD12864_Clear();}//////////////////////////////////////// 界面二//////////////////////////////////// ModeFlag=0; ///// 改while(ModeFlag==0) //进入登录界面{LCD12864_Waddr(1,1);LCD12864_WPoss(0,"请输入登陆密码:");LCD12864_Waddr(2,3);//LCD12864_WPoss(0," ");LCD12864_Waddr(3,1);LCD12864_WPoss(0,"密码为四位数字");LCD12864_Waddr(4,1);LCD12864_WPoss(0,"删除*");LCD12864_Waddr(4,6);LCD12864_WPoss(0,"确定#");key=Key_Scan();//键盘扫描if(key_check==1)//检测是否有按键按下{if(key<='9'&&key>='0')//密码只能是数字{Password[PasswordIndex]=key;//存储输入的密码// LCD12864_WPoss(0," ");//////////////// 改动过++PasswordIndex; //记录输入密码的次数if(PasswordIndex>4) //如果次数超过4次返回重新输入{PasswordIndex=0;//清空索引Password[0]=0;//清空数组Password[1]=0;Password[2]=0;Password[3]=0;LCD12864_Clear();LCD12864_Waddr(3,1);LCD12864_WPoss(0,"密码只能为四位");Delay_1ms(4000);//延时两秒显示LCD12864_Clear(); //延时清空break;}if(PasswordIndex<=4){LCD12864_Waddr(2,3);LCD12864_WPoss(0,Password);//显示输入的密码LCD12864_WPoss(0," ");/// 改}//ModeFlag=10;//进入while(1) 重新开始///// 改}if(key=='#') //确认密码{if(PasswordIndex<4)//密码位数少于4位则返回重新输入{PasswordIndex=0;Password[0]=0;Password[1]=0;Password[2]=0;Password[3]=0;LCD12864_Clear();LCD12864_Waddr(3,1);LCD12864_WPoss(0,"密码只能为四位");Delay_1ms(4000);LCD12864_Clear();break;}if(Password[0]=='1'&&Password[1]=='2'&&Password[2]=='3'&&Password[3]=='4'){//如果输入密码正确则进入计数界面//ModeFlag=2;LCD12864_Clear();//// LCD12864_Waddr(1,5);//// LCD12864_WPoss(0,"00:00");// LCD12864_Waddr(2,4);//// LCD12864_WPoss(0,"2013/01/01");// LCD12864_Waddr(3,4);// LCD12864_WPoss(0,"星期一");//// LCD12864_Waddr(4,6);//// LCD12864_WPoss(0,"返回*");////// Second=0;//计数器清零// minite=0;//计数器清零// hour=0;// day=1;// month=1;}else //如果密码错误重新输入{//ModeFlag=10;//进入while(1) 重新开始LCD12864_Clear();LCD12864_Waddr(3,1);LCD12864_WPoss(0,"密码错误");Delay_1ms(4000);LCD12864_Clear();PasswordIndex=0;Password[0]=0;Password[1]=0;Password[2]=0;Password[3]=0;break;}}if(key=='*')//删除按键{Password[--PasswordIndex]=' ';//删除一位密码LCD12864_Waddr(2,3);LCD12864_WPoss(0,Password);//显示输入的密码LCD12864_WPoss(0," ");if(PasswordIndex<=0){PasswordIndex=0;break;}}key_check=0;LCD12864_Waddr(2,8);LCD12864_WPoss(0," ");}}//////////////////////////////////界面三///////////////////////////////////////////////////while(ModeFlag==2){LCD12864_Waddr(1,1);LCD12864_WPoss(0,"查看时钟");LCD12864_Waddr(1,6);LCD12864_WPoss(0," B向上");LCD12864_Waddr(2,1);LCD12864_WPoss(0,"查看图片");LCD12864_Waddr(2,6);LCD12864_WPoss(0," C向下");LCD12864_Waddr(3,1);LCD12864_WPoss(0,"空文件");LCD12864_Waddr(4,1);LCD12864_WPoss(0,"返回*");LCD12864_Waddr(4,6);LCD12864_WPoss(0,"确定#");key=Key_Scan();//键盘扫描if(key_check==1){key_check=0;if(key=='B'){if(hua>0)hua--;}if(key=='C'){if(hua<2)hua++;}if(hua>2)hua=0;switch(hua){case 0:{convertChar(1,1,10);break;}case 1:{ convertChar(2,1,10);break;}case 2:{convertChar(3,1,10);break;}}if(key=='#'){if(hua==0)ModeFlag=3;if(hua==1)ModeFlag=4;if(hua==2)ModeFlag=5;LCD12864_W (LCD12864_COM,0x30);break;}if(key=='*'){LCD12864_Clear();Delay_1ms(1000);ModeFlag=0;LCD12864_Clear();}}}/////////////////////////////////////////// 界面四//////////////////////////if(ModeFlag==3)//计数界面{///////// Password[ ]=" ";// LCD12864_Waddr(1,1);// LCD12864_WPoss(0," ");LCD12864_Clear();//LCD12864_Waddr(1,5);//LCD12864_WPoss(0,"00:00");LCD12864_Waddr(2,4);//LCD12864_WPoss(0,"2013/01/01");LCD12864_Waddr(3,4);LCD12864_WPoss(0,"星期一");//LCD12864_Waddr(4,6);//LCD12864_WPoss(0,"返回*");//Second=0;//计数器清零minite=0;//计数器清零hour=0;day=1;month=1;while(ModeFlag==3){ if(shan==0) // :以秒为单位进行闪烁{LCD12864_Waddr(1,6);LCD12864_WPoss(0," ");}if(shan!=0){LCD12864_Waddr(1,6);LCD12864_WPoss(0,":");}if(minite<10){LCD12864_Wnum(0,0);LCD12864_Wnum(minite,0);LCD12864_WPoss(0," ");}else{LCD12864_Wnum(minite,0);LCD12864_WPoss(0," ");}LCD12864_Waddr(1,5);if(hour<10){LCD12864_Wnum(0,0);LCD12864_Wnum(hour,0);}if(hour>=10){LCD12864_Waddr(1,5);LCD12864_Wnum(hour,0);}LCD12864_Waddr(2,8);if(day<10){LCD12864_Wnum(0,0);LCD12864_Wnum(day,0);}if(day>=10)LCD12864_Wnum(day,0); LCD12864_Waddr(2,6);if(month<10){LCD12864_WPoss(0,"/");LCD12864_Wnum(0,0);LCD12864_Wnum(month,0);LCD12864_WPoss(0,"/");}if(month>=10){LCD12864_WPoss(0,"/");LCD12864_Wnum(month,0);LCD12864_WPoss(0,"/");}LCD12864_Waddr(3,6);LCD12864_W(LCD12864_DAT,xingqi[k]);LCD12864_W(LCD12864_DAT,xingqi[k+1]);if(day>365)year++;LCD12864_Waddr(2,4);LCD12864_Wnum(year,0);key=Key_Scan();//键盘扫描if(key_check==1){key_check=0;if(key=='A'){ wei++;if(wei==7)wei=1;}switch(wei){case 1:{if(key=='B')hour++;if(hour>0){ if(key=='C')hour--;}convertChar(1,5,2);//写入字节break;}case 2:{if(key=='B')minite++;if(minite>0){ if(key=='C')minite--;}convertChar(1,6,3);break;}case 3:{if(key=='B')year++;if(year>0){ if(key=='C')year--;}convertChar(2,4,4);break;}case 4:{if(key=='B')month++;if(month>1){ if(key=='C')month--;}convertChar(2,6,3);break;}case 5:{if(key=='B')day++;if(day>1){ if(key=='C')day--;}convertChar(2,8,2);break;}case 6:{if(key=='B')k=k+2;convertChar(3,6,2);break;}}if(key=='*'){ModeFlag=2;Delay_1ms(40);LCD12864_Clear();}}}}////////////////////////////////// 界面五////////////////////////////// while(ModeFlag==4){LCD12864_Clear();LCD12864_Waddr(2,3);LCD12864_WPoss(0,"No pictures");LCD12864_Waddr(4,1);LCD12864_WPoss(0,"返回*");key=Key_Scan();//键盘扫描if(key_check==1){key_check=0;if(key=='*'){LCD12864_Clear();Delay_1ms(1000);ModeFlag=2;LCD12864_Clear();}}}///////////////////////////////// 界面六///////////////////////////////// while(ModeFlag==5){LCD12864_Clear();LCD12864_Waddr(2,3);LCD12864_WPoss(0,"啥也没有");LCD12864_Waddr(4,1);LCD12864_WPoss(0,"返回*");key=Key_Scan();//键盘扫描if(key_check==1){key_check=0;if(key=='*'){Delay_1ms(100);ModeFlag=2;LCD12864_Clear();}}}}}。
一种易于移植的单片机液晶显示多级菜单设计
一种易于移植的单片机液晶显示多级菜单设计王勇【摘要】LCD display as a human-computer interaction is very popular in various application situations of embedded microcontroller systems. However, general LCD display menu design is a little bit complicated, and does not have the portability, therefore the complexity in development and system maintenance and the cost are increased. In this paper we introduce the window and message mechanisms of Windows Operating System, and design a multilevel menu. The core of the menu is a universal window engine which does not depend on specific hardware and the content of menu. Research and application show that the menu design has the characters of simple structure, easy to use, little resource consumption, portable and so on. In the end of the paper we present an application example running in the FYD12864 LCD module.%在单片机嵌入式系统的许多应用场合均采用液晶显示器作为人机交互的方式,然而通常的液晶显示菜单设计较为复杂,且基本不具备可移植性,从而增加了开发、维护的复杂性和成本.引入Windows系统下的窗口和消息机制,设计一个多级菜单,该菜单的核心部分是一个不依赖具体硬件和菜单内容的通用的窗口引擎.研究和应用表明,该菜单设计具有结构简单、使用方便、占用资源少以及易于移植等特点.最后给出一个在FYD12864液晶模块上使用此方法的应用案例.【期刊名称】《计算机应用与软件》【年(卷),期】2011(028)012【总页数】6页(P263-268)【关键词】单片机;液晶显示;菜单;窗口引擎【作者】王勇【作者单位】电子科技大学四川成都610054东莞电子科技大学电子信息工程研究院广东东莞523808【正文语种】中文【中图分类】TP3110 引言单片机系统,特别是8位单片机系统通常可用资源较少,速度相对较慢,一般不适合部署操作系统,更谈不上图形引擎了。
C51与单片机系统多级菜单的模块化设计_汪高勇
单片机的应用中, 除了进行数据运算和过程控 制外, 还会使用到人机接口. 人机接口处理了操作者 的指令输入, 这些操作普遍采用了菜单方式进行命 令输入, 在使用液晶显示器的场合, 菜单更是必需的 设计. 对于汇编语言而言, 菜单可以使用制表法进行 菜单编写, 但是由于汇编语言可移植性和可读性较 差, 所以对于菜单的复杂性、菜单的可移植性、可维 护性以及可扩充性方面, 汇编语言处于弱势. 使用 C 语言可以解决这方面的问题, 利用 C 语言的数据结 构, 对菜单进行数据组织, 将菜单进行模块化设计, 可解决上述问题.
第 24 卷第 2 期 2009 年 4 月
电路与控制
光 电技 术应 用
EL ECT RO - OPT IC T ECHNO LOG Y AP PLI CAT ION
Vo l. 24, No. 2 Apr 块化设计
汪高勇, 宋毅恒, 尚举邦
( 东北电子技术研究所, 辽宁 锦州 121000)
图 2 菜单模块组成
图 1 共用键盘处理程序
图 1 中, 工作程序是软件中需要在主程序轮询 执行的任务程序, 用于检查系统的各种功能标识和 消息并进行处理. 共用键盘处理程序也算作一种任 务程序, 由主程序轮询执行. 如图 1 虚框所示, 当键 标志有效时, 程序对键值进行匹配, 执行当前菜单模 块对应的按键程序. N 个菜单模块同一时刻仅有一 个模块通过按键函数指针初始化得以装载.
1 菜单模块化设计原理
1. 1 共用键盘处理
菜单的模块化设计主要分为共用键盘处理和 菜单模块两部分. 主要原理是在主程序中设置一个 共用键盘处理程序, 各菜单模块利用统一的键盘接 口函数对共用键盘处理程序中的按键函数指针进行 重定向设定, 使得共用键盘处理程序能够指向各菜 单模块. 每次按键操作完毕, 均回到主程序, 这与常 用的菜单编程方法类似.
单片机C语言下LCD多级菜单的一种实现方法
单片机C语言下LCD多级菜单的一种实现方法(转)2012-1-10 00:45阅读(1)单片机菜单程序#include#include#define SIZE_OF_KEYBD_MENU 20 //菜单长度uchar KeyFuncIndex=0;//uchar KeyFuncIndexNew=0;void (*KeyFuncPtr)(); //按键功能指针typedef struct{uchar KeyStateIndex; //当前状态索引号uchar KeyDnState; //按下"向下"键时转向的状态索引号uchar KeyUpState; //按下"向上"键时转向的状态索引号uchar KeyCrState; //按下"回车"键时转向的状态索引号void (*CurrentOperate)(); //当前状态应该执行的功能操作} KbdTabStruct;KbdTabStruct code KeyTab[SIZE_OF_KEYBD_MENU]={{ 0, 0, 0, 1,(*DummyJob)},//顶层{ 1, 2, 0, 3,(*DspUserInfo)},//第二层{ 2, 1, 1, 9,(*DspServiceInfo)}, //第二层{ 3, 0, 0, 1,(*DspVoltInfo)},//第三层>>DspUserInfo的展开{ 4, 0, 0, 1,(*DspCurrInfo)},//第三层>>DspUserInfo的展开{ 5, 0, 0, 1,(*DspFreqInfo)},//第三层>>DspUserInfo的展开{ 6, 0, 0, 1,(*DspCableInfo)},//第三层>>DspUserInfo的展开...........{ 9, 0, 0, 1,(*DspSetVoltLevel)}//第三层>>DspServiceInfo的展开..........};void GetKeyInput(void){uchar KeyValue;KeyValue=P1&0x07; //去掉高5bitdelay(50000);switch(KeyValue){case 1: //回车键,找出新的菜单状态编号{KeyFuncIndex=KeyTab[KeyFuncIndex].KeyCrState;break;}case 2: //向上键,找出新的菜单状态编号{KeyFuncIndex=KeyTab[KeyFuncIndex].KeyUpState; break;}case 4: //向下键,找出新的菜单状态编号{KeyFuncIndex=KeyTab[KeyFuncIndex].KeyDnState; break;}default: //按键错误的处理......break;}KeyFuncPtr=KeyTab[KeyFuncIndex].CurrentOperate; (*KeyFuncPtr)();//执行当前按键的操作}//其中KeyTab的设计颇费尽心机。
51单片机实现多级液晶显示中文菜单
51单片机实现多级液晶显示中文菜单【摘要】以AT89C51单片机控制使用比较普遍的YM12864液晶显示器为基础,介绍了一种采用分页原理实现多级中文菜单操作的方法。
给出了YM12864主要技术参数、显示特性和核心的程序。
设计的中文菜单具有一定的通用性,只需更改其中的菜单项即可将此设计应用到家电、仪器仪表等设备上,为操作者提供友好方便的中文操作界面。
【关键词】单片机;分页;YM12864液晶;中文菜单一、引言目前小型的显示器主要有LCD和LED,LED显示器只能显示数字和有限个英文字符,不能显示汉字,显示内容不直观,操作人员只能根据约定格式了解显示内容。
而LCD则可显示各种汉字和图形,尤其能实现中文菜单显示,为操作者提供方便友好的操作界面,并且功耗低,因此LCD得到广泛应用。
而现在市面上带中文字库的LCD比比皆是,价格适中,且大部分具有与MCU统一的标准接口,为使用LCD实现中文菜单操作提供了很大的方便。
相信更多的电子产品在提升性能的同时,设计更加人性化的中文菜单交互界面,将会使产品具有更广阔的前景。
二、YM12864液晶显示模块简介YM12864汉字图形点阵液晶显示模块,可显示汉字及图形,内置8192个中文汉字(16X16点阵)、128个字符(8X16点阵)及64X256点阵显示RAM (GDRAM)。
主要技术参数和显示特性:电源:VDD 3.3V~+5V(内置升压电路,无需负压)显示内容:128列×64行与MCU接口:8位或4位并行/3位串行多种软件功能:光标显示、画面移位、自定义字符、睡眠模式等。
其引脚功能为通用20脚LCD接口,用户指令集也为通用128*64LCD用户指令集,相关资料很容易获取。
因其内置中文字库,省去了自己造字库的工作量,而只需写入相应的汉字和字符内码即可显示所需要的汉字和字符,这在许多程序开发软件中很容易实现,如:WA VE、KEIL等。
所以使用带中文字库的LCD来实现中文菜单操会更加简便。
51单片机实现多级液晶显示中文菜单共5页word资料
51单片机实现多级液晶显示中文菜单一、引言目前小型的显示器主要有LCD和LED,LED显示器只能显示数字和有限个英文字符,不能显示汉字,显示内容不直观,操作人员只能根据约定格式了解显示内容。
而LCD则可显示各种汉字和图形,尤其能实现中文菜单显示,为操作者提供方便友好的操作界面,并且功耗低,因此LCD得到广泛应用。
而现在市面上带中文字库的LCD比比皆是,价格适中,且大部分具有与MCU统一的标准接口,为使用LCD实现中文菜单操作提供了很大的方便。
相信更多的电子产品在提升性能的同时,设计更加人性化的中文菜单交互界面,将会使产品具有更广阔的前景。
二、YM12864液晶显示模块简介YM12864汉字图形点阵液晶显示模块,可显示汉字及图形,内置8192个中文汉字(16X16点阵)、128个字符(8X16点阵)及64X256点阵显示RAM(GDRAM)。
主要技术参数和显示特性:电源:VDD 3.3V~+5V(内置升压电路,无需负压)显示内容:128列×64行与MCU接口:8位或4位并行/3位串行多种软件功能:光标显示、画面移位、自定义字符、睡眠模式等。
其引脚功能为通用20脚LCD接口,用户指令集也为通用128*64LCD 用户指令集,相关资料很容易获取。
因其内置中文字库,省去了自己造字库的工作量,而只需写入相应的汉字和字符内码即可显示所需要的汉字和字符,这在许多程序开发软件中很容易实现,如:WAVE、KEIL等。
所以使用带中文字库的LCD来实现中文菜单操会更加简便。
三、原理分析通常的人机交互界面有两种方式,选择菜单和输入参数,为了便于分析,本文使用三级树状菜单结构,如图1所示,来阐述中文菜单的显示原理。
因YM12864满屏能显示四行、每行八个汉字,故将四个选择或参数输入菜单项编为一页,不足一页的补空格。
补空格的目的是为了归一化操作,可大大简化程序。
每一个菜单、参数输入、空格都为固定的八个汉字空间。
图1中顶级菜单1、顶级菜单2、顶级参数输入3、顶级4构成一级菜单,四个菜单项为一页同时显示在液晶屏幕上;一级菜单1-1、一级菜单1-2、一级参数输入1-3、一级空格1-4构成了顶级菜单1下的二级菜单,也组成一页同时显示在液晶屏幕上,三级菜单也是如此。
12864液晶多级菜单设计
(完整版)单片机多级菜单编程实现
单片机多级菜单编程实现单片机多级菜单编程实现(ZT)建立一个树状的菜单结构,用链表实现链表中包含:1、指向同级左右菜单和指向父菜单、子菜单的四个菜单结构体指针;2、进入该菜单时需要执行的初始化函数指针3、退出该菜单时需要执行的结束函数指针4、该菜单内的按键处理函数指针数组的指针操作菜单模块需要的按键操作有:左、右、确认、退出。
采用这种办法,可以方便的添加或删减菜单。
并且只需要在其头文件中修改初始变量就可以实现,完全无须修改C文件中的任何函数。
具体结构定义我的定义,做个参考:#define MENU_HLP_EN //菜单帮助信息使能typedef struct{void (*pMenuTaskInit)(void); //指向菜单任务初始化函数的指针void (*pMenuTaskEnd)(void); //指向菜单任务结束函数的指针}MENU_TASK_TYP;typedef struct MenuTyp{INT8U *MenuName; //菜单名称字符串WORK_MOD WorkMod; //工作状态编号MENU_TASK_TYP *pMenuTask; //指向菜单任务的指针void (**pTaskKeyDeal)(void); //指向菜单任务按键处理函数数组的指针#ifdef MENU_HLP_ENINT8U *MenuHlp; //菜单帮助字符串#endifstruct MenuTyp *pParent; //指向上层菜单的指针struct MenuTyp *pChild; //指向子菜单的指针struct MenuTyp *pRight; //指向右菜单的指针struct MenuTyp *pLeft; //指向左菜单的指针}MENU_TYP;我根据网上的资料做的一个菜单:/****************菜单数据结构**********************/struct KeyTabStruct{uint8 MenuIndex; //当前状态索引号uint8 MaxItems; //本级菜单最大条目数uint8 ShowLevel; //菜单显示内容uint8 PressOk; //按下"回车"键时转向的状态索引号uint8 PressEsc; //按下"返回"键时转向的状态索引号uint8 PressDown; //按下"向下"键时转向的状态索引号uint8 PressUp; //按下"向上"键时转向的状态索引号void (*CurrentOperate)(); //当前状态应该执行的功能操作};uint8 MenuID; //菜单ID号uint8 MenuNextID; //下级菜单ID号//CurMenuID=本菜单ID//MaxMenuItem=同级菜单最大项数//OkMenuID=子菜单层所对应的菜单ID,ID=999为菜单已经到底了//EscMenuID=父菜单层所对应的菜单ID,ID=999为菜单已经到顶了//DownMenuID=弟菜单层所对应的菜单ID,ID=999为菜单是独生子//UpMenuID=兄菜单层所对应的菜单ID,ID=999为菜单是独生子//CurFunction=本菜单所对应的菜单函数指针const struct KeyTabStruct KeyTab[MAX_KEYTABSTRUCT_NUM]={//CurMenuID, axMenuItem, MenuShowLevel, OkMenuID, EscMenuID, DownMenuID, UpMenuID, CurFunction{MENU_EDIT, 0, 0, MENU_DATA_VIEW, MENU_NO, MENU_NO, MENU_NO, *MenuEdit},{MENU_DATA_VIEW, 3, 1, MENU_DATA_VIEW_FIRE, MENU_EDIT, MENU_ SYS_EDIT, MENU_PRINT_DATA,*MenuEdit},{MENU_DATA_VIEW_FIRE, 5, MENU_NO, MENU_NO, MENU_DATA_VIEW, MENU_DATA_VIEW_TROUBLE, MENU_STEP_FOLLOW, *MenuDataViewIn}, {MENU_DATA_VIEW_TROUBLE, 5, MENU_NO, MENU_NO, MENU_DATA_VI EW, MENU_DATA_VIEW_REPEAT, MENU_DATA_VIEW_FIRE, *MenuDataVie wIn},{MENU_DATA_VIEW_REPEAT, 5, MENU_NO,MENU_NO, MENU_DATA_VIEW, MENU_FACE_CHECK,MENU_DATA_VIEW_TROUBLE, *MenuDataViewIn},{MENU_FACE_CHECK, 5, MENU_NO,MENU_NO, MENU_DATA_VIEW, MENU_STEP_FOLLOW,MENU_DATA_VIEW_REPEAT, *MenuFaceCheck},{MENU_STEP_FOLLOW, 5, MENU_NO,MENU_NO, MENU_DATA_VIEW, MENU_DATA_VIEW_FIRE, MENU_FACE_CH ECK,*MenuStepFollow},{MENU_SYS_EDIT, 3,2, MENU_SUM_SET, MENU_EDIT,MENU_PRINT_DATA, MENU_DATA_VIEW, *MenuEdit},{MENU_SUM_SET, 6, MENU_NO,MENU_NO, MENU_SYS_EDIT, MENU_EDIT_INSULATE,MENU_TIME_SET, *MenuSumSet},{MENU_EDIT_INSULATE, 6, MENU_NO,MENU_NO, MENU_SYS_EDIT, MENU_EDIT_HZ, MENU_SUM_SET,*MenuEditInsulate},{MENU_EDIT_HZ, 6, MENU_NO,MENU_NO, MENU_SYS_EDIT, MENU_LD_CONTROL,MENU_EDIT_INSULATE, *MenuEditHZ},{MENU_LD_CONTROL, 6,MENU_NO, MENU_NO, MENU_SYS_EDIT, MENU_LD_DELAY,MENU_EDIT_HZ, *MenuLDControl},{MENU_LD_DELAY, 6,MENU_NO, MENU_NO, MENU_SYS_EDIT, MENU_TIME_SET,MENU_LD_CONTROL, *MenuLDDelay},{MENU_TIME_SET, 6, MENU_NO,MENU_NO, MENU_SYS_EDIT, MENU_SUM_SET, MENU_LD_DELAY,*MenuTimeSet},{MENU_PRINT_DATA, 3, 3,MENU_PRINT_DATA_FIRE, MENU_EDIT, MENU_DATA_VIEW,MENU_SYS_EDIT, *MenuEdit},{MENU_PRINT_DATA_FIRE, 4,MENU_NO, MENU_NO, MENU_PRINT_DATA,MENU_PRINT_DATA_TROUBLE, MENU_PRINT_SET, *MenuPrintDataIn}, {MENU_PRINT_DATA_TROUBLE, 4, MENU_NO,MENU_NO, MENU_PRINT_DATA, MENU_PRINTER_CHECK,MENU_PRINT_DATA_FIRE, *MenuPrintDataIn},{MENU_PRINTER_CHECK, 4, MENU_NO,MENU_NO, MENU_PRINT_DATA, MENU_PRINT_SET,MENU_PRINT_DATA_TROUBLE, *MenuPrintDataIn},{MENU_PRINT_SET, 4, MENU_NO,MENU_NO, MENU_PRINT_DATA, MENU_PRINT_DATA_FIRE,MENU_PRINTER_CHECK, *MenuPrintSet},};/**************************************编程菜单显示数据******************************/const struct MenuDispData MenuEditShow[][MENU_MAX] = {{{MENU_NO , 0, 0, "选择: 消音→退出"}, //主菜单{MENU_DATA_VIEW , 1, 6, "⒈数据查看"},{MENU_SYS_EDIT , 2, 6, "⒉系统编程"},{MENU_PRINT_DATA , 3, 6, "⒊数据打印"}},{{MENU_NO , 0, 0, "数据查看: 消音→退出"}, //数据查看{MENU_DATA_VIEW_FIRE , 1, 4, "⒈火警"},{MENU_DATA_VIEW_TROUBLE, 2, 4, "⒉故障"},{MENU_DATA_VIEW_REPEAT , 3, 4, "⒊重码"},{MENU_FACE_CHECK , 1,12, "⒋面板检测"},{MENU_STEP_FOLLOW , 2,12, "⒌单步跟踪"}},{{MENU_NO , 0, 0, "系统编程: 消音→退出"}, //系统编程{MENU_SUM_SET , 1, 0, "⒈容量设置"},{MENU_EDIT_INSULATE , 2, 0, "⒉隔离点"},{MENU_EDIT_HZ , 3, 0, "⒊汉字描述"},{MENU_LD_CONTROL , 1,12, "⒋联动控制"},{MENU_LD_DELAY , 2,12, "⒌模块延时"},{MENU_TIME_SET , 3,12, "⒍时钟调整"}},{{MENU_NO , 0, 0, "数据打印: 消音→退出"}, //数据打印{MENU_PRINT_DATA_FIRE , 1, 0, "⒈火警数据"},{MENU_PRINT_DATA_TROUBLE,2, 0, "⒉故障数据"},{MENU_PRINTER_CHECK , 3, 0, "⒊打印机自检"},{MENU_PRINT_SET , 1,12, "⒋打印设置"}},};/***********************************等待按键******************** **************/void WaitKey(void){uint32 time;time = RTCFlag;WhichKey = KEY_NONE;while(!EscFlag){if(RTCFlag - time >= EDIT_TIME)EscFlag = TRUE;if(WhichKey != KEY_NONE){KeySound(300); //按键音return;}}}/*********************************显示多级菜单**********************************/void MenuEdit(){uint32 i,j=0;uint32 oldid;j = KeyTab[MenuID].ShowLevel;if(WhichKey == KEY_ESC || WhichKey == KEY_OK){ClearScreen();for(i=0;i<KeyTab[MenuNextID].MaxItems+1;i++) ShowString(MenuEditShow[j][i].Lin,MenuEditShow[j] [i].Column,MenuEditShow[j][i].Pdata,0); //初始化显示oldid =0;//没有原先选择的项}else{if(WhichKey == KEY_UP)oldid = KeyTab[MenuNextID].PressDown;elseoldid = KeyTab[MenuNextID].PressUp;//指示原先的项}for(i=1;i<KeyTab[MenuNextID].MaxItems+1;i++){if(MenuEditShow[j][i].Id == oldid)ShowString(MenuEditShow[j][i].Lin,MenuEditShow[j][i].Column,MenuEditShow[j][i].Pdata,0); //正常显示原先的项else{if(MenuEditShow[j][i].Id == MenuNextID)ShowString(MenuEditShow[j][i].Lin,MenuEditShow[j][i].Column,MenuEditShow[j][i].Pdata,1); //反显当前选择的项}}WhichKey = KEY_NONE;}/******************************系统编程************************* ******/uint32 Edit(void){struct KeyTabStruct NowKeyTab; //指示当前的菜单值uint32 escflag = FALSE;ResetFlag = FALSE;ChangeFlag = FALSE;EscFlag = FALSE;MenuID = MENU_EDIT;NowKeyTab = KeyTab[MenuID];MenuNextID = NowKeyTab.PressOk;(*NowKeyTab.CurrentOperate)(); //显示主菜单do{if(WhichKey == KEY_NONE)WaitKey(); //等待按键switch(WhichKey){case KEY_ESC : if(NowKeyTab.PressEsc != MENU_NO) {MenuID =NowKeyTab.PressEsc;MenuNextID =NowKeyTab.MenuIndex;NowKeyTab = KeyTab[MenuID];NowKeyTab.PressOk =MenuNextID;(*NowKeyTab.CurrentOperate)(); //显示当前菜单}elseescflag =TRUE; //退出编程状态break;case KEY_OK : if(NowKeyTab.PressOk != MENU_NO) {MenuID =NowKeyTab.PressOk;NowKeyTab = KeyTab[MenuID];MenuNextID =NowKeyTab.PressOk;}(*NowKeyTab.CurrentOperate)(); //执行当前按键的操作break;case KEY_UP : if((MenuNextID != MENU_NO) && (KeyTab[MenuNextID].PressUp != MENU_NO)){NowKeyTab.PressOk =KeyTab[MenuNextID].PressUp;MenuNextID = KeyTab[MenuNextID].PressUp;(*NowKeyTab.CurrentOperate)(); //执行当前按键的操作}break;case KEY_DOWN: if((MenuNextID != MENU_NO) && (KeyTab[MenuNextID].PressDown != MENU_NO)){NowKeyTab.PressOk =KeyTab[MenuNextID].PressDown;MenuNextID = KeyTab[MenuNextID].PressDown;(*NowKeyTab.CurrentOperate)(); //执行当前按键的操作}break;case KEY_RESET: ResetFlag = TRUE;break;default : break;}}while(!ResetFlag && !EscFlag && !escflag);if(ChangeFlag && !EscFlag && !ResetFlag) EditDataChange();if(ResetFlag)return SYS_RESET;else{return 0;}}关于这个菜单的说明:1.我用的是ARM处理器,所以51的时候把const改成code,uint32改成unsign ed char。
基于STM32单片机LCD多级菜单的设计
基于STM32单片机LCD多级菜单的设计摘要本设计介绍了以ARM内核嵌入式处理器STM32为控制核心,辅以低功耗的液晶模块MFG240160-3-A,以及相应的按键控制电路,实现了LCD多级菜单的设计。
在本系统中,侧重点在于LCD的显示上,因此此系统的硬件结构很简单,侧重点在于软件架构及程序的编写上,该系统程序量大,函数封装多,关于实时时钟信息、波形存储信息都留有相应的软件接口,以便与其它模块正确的相连接。
本系统硬件电路简单,但显示信息丰富,可以移植到各种便携式的电子产品上去,为电子产品的显示界面的设计提供了一个新的思路。
关键词 STM32单片机;LCD多级菜单;低功耗;Base on STM32 Microprocessor LCD modules in the multi-level menu display systemAbstractThis design describes to STM32 embedded processor based on ARM core for control, coupled with low power consumption of LCD module MFG240160-3-A as well as the corresponding keys control circuitry, enabling multi-level menu design of LCD. In this system, the focus is on the LCD display, so this system hardware structure is very simple, the emphasis lies in software architectures and applications, the system capacity, function encapsulates the information about the real-time clock, waveform stored information will have the appropriate software interface so that correct with other modules that you are connecting to. This system is simple, but the display information-rich, portable to avariety of portable electronic products, for electronic product display interface design provides a new train of thought.Keywords: STM32; LCD multi-level menu; low-power;目录摘要(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((I Abstract(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((II 前言 ............................................................... 4 1方案设计 (5)1.1 设计方案概述 (5)1.2 电路介绍 (5)2 器件介绍 (9)2.1 STM32简介 (9)2.2 MFG240160-3-A LCD介绍 (13)3 软件设计 (16)3.1 STM32单片机的初始化 (16)3.2 液晶屏的初始化 (20)3.3 数据的传输 (20)3.4 字模的提取 (21)3.5 菜单框架的设计 (23)3.6 字模库的建立 (25)3.7 函数库的封装 (25)3.8 菜单标记 (26)3.9 时钟信息的显示 (27)3.10 波形的显示 (28)4 结论 (30)参考文献 (31)致谢 ............................................ 错误~未定义书签。
单片机C语言下LCD多级菜单的一种实现方法
第1期2006年2月工矿自动化IndustryandMineAutomationNO1文章编号:1671—251X(2006)01—0050一02单片机C语言下LCD多级菜单的一种实现方法陆铮1,罗嘉2(1.天地科技股份有限公司常州自动化分公司,江苏常州2130152.宁夏煤矿安全监察局,宁夏银川750001)摘要:介绍了在C语言环境下,在LCD液晶显示屏上实现多级嵌套菜单的一种简便方法,提出了一个结构紧凑、实用的程序模型。
关键词:液晶显示屏;多级菜单;单片机;C语言;I。
CD中图分类号:TP311.1文献标识码:B0引言由于C语言的结构性和模块化,采用c语占编写的程序容易阅读和维护,还有很好的可移植性。
本文介绍一种用C语言实现的LCD多级菜单的方法,该方法已成功应用在煤矿安全监测设备上。
1硬件环境及LCD菜单实现的功能图形点阵式液晶可显示用户自定义的任意符号和图形,并可卷动显示。
它作为单片机系统人机交互界面的重要组成部分被广泛应用于实时检测和显示的仪器仪表中,例如手机r的显示屏就是图形点收藕日期:2005—11—2阵液晶。
采用图形点阵式液晶显示较之其它显示方式主要有以下优点:(1)工作电压低、功耗极低。
工作电压仅为3~5V.工作电流≤10tuA/cm2,特别适用于低功耗的仪器仪表中。
(2)液晶显示属被动昴示,受外界光线干扰小。
(3)图形点阵式液晶可显示的信息量大、分辨率高。
(4)不产生电磁干扰。
(5)可靠性高,使用寿命长。
本文所介绍的I.CI?采用128×64点阵的液晶屏,因此可显示16×16点阵的汉字4行8列。
菜单为多级嵌套形式,最长的有13层,主要完成对某个,'…●,'l,,l●l…,',,',,●'…,●’’,,,●’’’,,,'',…,’’●’’,,,,’’’…,,’,,■'…,,'…●…,,……,',,'系统要运行可靠,对其有关设备是否能够安全运行地检测也是很重要的一环。
LCD12864 多级菜单
searchMenu.subMenus = malloc(sizeof(&searchMenu)*6); searchMenu.subMenus[0] = searchMenu.subMenus[1] = searchMenu.subMenus[2] = searchMenu.subMenus[3] = searchMenu.subMenus[4] = searchMenu.subMenus[5] = NULL; searchMenu.func = malloc(sizeof(&printf)*6); searchMenu.func[0] = searchMenu.func[2] = searchMenu.func[2] = searchMenu.func[3] = searchMenu.func[4] = searchMenu.func[5] = NULL; searchMenu.parent = &MainMenu;//上一级菜单是MainMenu.进入查询 子菜单后按返回键,将会显示这个菜单 项
Lcd_Write_Data(*s); s++; } Lcd_Write_Cmd(0x36); //返回图形模式 }
void highlight(uchar x,uchar y,uchar width,u8 mode)
//反
白,X值为0-7,Y值为0-3,width为行反白格数
{
uchar i,j,flag=0x00;
break; } case 8://向下 if(currentMenu->selected == currentMenu->itemCount-1) break; else { currentMenu->selected++; if(currentMenu->selected>currentMenu->range_to) {
一种单片机多级菜单的模块化设计方法
一种单片机多级菜单的模块化设计方法引言在单片机设计中,往往需要在显示屏上显示多级操作菜单,每级菜单都有一些菜单项和对应的按键操作,以及为响应各种操作而执行的后续处理程序。
参考文献以函数指针为结构元素,把整个菜单结构拉伸成一个结构数组,内部包含了全部菜单项。
这种方法没有将菜单项数据与功能函数分开设计,而把菜单项数据写在功能函数中,当菜单项数据需要改变时,必须修改功能函数,这在很大程度上限制了程序的通用性,不利于程序的维护。
参考文献在前者的基础上略加改进,在原结构体中增加了菜单项显示文字和按键复用标识,这使得结构体较为庞大,且菜单项的文字内容非常固定,保存在EEPROM 中,无法灵活改变显示内容和位置。
参考文献引入Windows 系统下的窗口和消息机制实现多级菜单设计,该方法需要维护堆栈、消息队列和窗口定时器等,设计过于复杂。
本文旨在提供一个轻量级的单片机多级菜单实现方法,以较少的系统资源消耗和简单方便的方法完成菜单设计。
考虑到菜单程序需要具备3 个基本要素:一是每个菜单窗口要显示的内容;二是每个窗口对应的按键定义与响应;三是窗口内菜单项之间切换和窗口之间的切换机制。
因此,将菜单分为菜单窗口模块和键盘处理模块两部分,独立进行设计。
1 菜单窗口模块设计菜单窗口模块主要功能是按照菜单窗口切换机制,实时完成窗口的显示控制。
1.1 菜单窗口切换机制菜单窗口切换机制包括两点:一是不同窗口之间切换效果的实现;二是窗口内的同级菜单项之间滚动切换效果的实现。
为实现上述功能,定义了两个结构体MenuState 和MenuItems。
MenuState 定义如下:MenuState 是一个与窗口跳转和窗口显示有关的结构体数组,用于全局调度各窗口之间的切换。
其中,CurIndex 是窗口的索引值,用来标识当前窗口。
UpIndex、DnIndex、BackIndex 用来标识当有上页、下页、返回按键操作时,。
单片机C语言中LCD菜单的方法实现
1995-2006 Tsinghua Tongfang Optical Disc Co., Ltd. All rights reserve d. 2006 年第 1 期 陆 铮等 : 单片机 C 语言下 L CD 多级菜单的一种实现方法 ,4 ,6 ,8 ,0 , ( 3 Modif yPoint) } , / 第一层 {5 / ,6 ,1 ,0 ,0 , ( 3 Cancel) } , / 第一层 {7 / … … ,0 ,0 ,0 ,0 , ( 3 Disab le) } , {54 void Get Keylnp ut (void) { ?51 ? 测点各方面的设置或查询 , 可通过 “向上” 向下” 、 “ 、 “回退” 确认 ” 个键或遥控器来实现对菜单的选 “ 、 4 择 。具体功能 : “向上” : 在本层菜 单的项目中向上移动进行 键 选择 ; “向下” : 在本层菜单的项目中向下移动进行 键 选择 ; “回退” : 取消本层的菜单设置 , 返回上层菜 键 单; “确认” : 确 认本层的菜单设置 , 进入下级菜 键 单。 可根据用户在菜单中的选择项对测点进行 某些 设置 ,或者进行某些特殊的显示 ,例如对某个测点的 实时曲线显示等 。 2 程序设计 }; KeyFuncIndex = Key Tab[ KeyFuncIndex ] . KeyCrState ; 根据需求 ,首先建立一个结构 ,并定义一个结构 变量 Kbd TabSt ruct 。结构 变量就是把多个不同类 型的变量结合在一起形成的一个组合型变量 , 构成 一个结构 的各个变量称为结构元素 。该结构中共有 6 个结构元素 ,分别是 5 个字符型和 1 个指针变量 , 5 个字符型变量分别为当前及各个按键的索引号 , State ; case 0xd0 :/ / 向上键 ,找出新的菜单状态编号 也就是操作的状态号 , 最后 1 个指针变量指向需执 行函数 。这样就可以做一 个结构数组 , 在结构数组 里为每一个菜单项编制一个单独的函数 , 并根据菜 单的 嵌套顺序排好本菜单项的索引号 ,以及本级菜 单项的上、 下卷动的索引号和上 、 下级菜单的索引号。 具体程序如下所述 : t ypedef st ruct { State ; State ; uchar KeyStateIndex ; / 当前状态索引号 / uchar KeyDnState ; / 按下 / “向下” 键时转向的状态索引号 uchar KeyUpState ; / 按下 / “向上” 键时转向的状态索引号 uchar KeyCrState ; / 按下 / “回车” 键时转向的状态索引号 uchar KeyBackState ; / 按下 / “ 退回” 键时转向的状态索引号 功能操作 void ( 3 CurrentOperate) ( ) ; / / 当前状态应该执行的 # define SIZE - O F KE YBD - M ENU 55 / 菜单总长度 / ,5 ,7 ,52 ,0 , ( 3 Set Clo seDown) } , / 第一层 {6 / ,53 ,53 ,0 ,1 , ( 3 OkSet CloseDown1) } , {52 ,52 ,52 ,0 ,1 , ( 3 OkSet CloseDo wn2) } , {53 switch ( stat us &0xf0) { … … bre ak ; … … break ; … … break ; … … break ; case 0 ; urn ; / 错误的处理 ret / break ; } case 0xe0 :/ / 回车键 ,找出新的菜单状 态编号 case 0xb0 :/ / 向下键 ,找出新的菜单状态编号 case 0x70 :/ / 回退键 ,找出新的菜单状态编号 } Kbd TabSt ruct ; } 3 结语 Kbd TabSt ruct code Key Tab[ SIZE - O F - KE YBD - MENU ] = { ,0 ,0 ,1 ,0 , ( 3 MainJob1) } , {0
msp430三级菜单菜单算法
msp430三级菜单菜单算法#include "msp430x14x.h"#include "lcd12864.h"#include "jianpan.h"#include "fun.h"#define uchar unsigned char#define uint unsigned intuchar func_index;uint i;void (*current_operation_index)();/********************主函数******************************************/ void main() { P1DIR=0Xf0;P1OUT=0X00;WDTCTL = WDTPW + WDTHOLD;lcd12864_init();init();//初始化LCD模块delay2(1);while(1){/*******************find index****************************/if(P1IN==0X0E){func_index=table[func_index].up; //向上翻while((P1IN&0x0f)!=0x0f);//松手检测write_con(0x01);//清屏}if(P1IN==0x0D){func_index=table[func_index].down; //向下翻while((P1IN&0x0f)!=0x0f);write_con(0x01);//清屏}if(P1IN==0x0B){func_index=table[func_index].enter; //确认while((P1IN&0x0f)!=0x0f);write_con(0x01);//清屏}current_operation_index=table[func_index].current_operatio n;(*current_operation_index)();//执行当前操作函数}}#include"msp430f149.h"#define uchar unsigned char#define uint unsigned int#define keyin (P1IN&0X0F)uchar keyValue;/****************延时1ms******************/void delay2(uchar time){uint i,j;for(i=0;i<time;i++)< p="">{for(j=0;j<150;j++);}}#include"msp430f149.h"/****************菜单结构体***************************/typedef struct{uchar current;uchar up;//向上翻索引号uchar down;//向下翻索引号uchar enter;//确认索引号void (*current_operation)();} key_table;/**************菜单功能显示***********************************/ void fun1(){display_hz(1,0,"【菜单1 】",12);display_hz(2,1,"菜单2",3);display_hz(3,1,"菜单3",3);display_hz(4,3,"返回",2);}void fun2(){display_hz(1,1,"菜单1",2);display_hz(2,0,"【菜单2 】",2);display_hz(3,1,"菜单3",2);display_hz(4,3,"返回",2);}void fun3(){display_hz(1,1,"菜单1",2);display_hz(2,1,"菜单2",2);display_hz(3,0,"【菜单3 】",2);display_hz(4,3,"返回",2);void fun4(){display_hz(1,1,"菜单1",2);display_hz(2,1,"菜单2",2);display_hz(3,1,"菜单3",2);display_hz(4,2,"【返回】",2);}void fun5(){display_hz(1,0,"【菜单1.1 】",2);display_hz(2,1,"菜单1.2",2);display_hz(3,1,"菜单1.3",2);display_hz(4,3,"返回",2);void fun6(){display_hz(1,1,"菜单1.1",2); display_hz(2,0,"【菜单1.2 】",2); display_hz(3,1,"菜单1.3",2); display_hz(4,3,"返回",2);}void fun7(){display_hz(1,1,"菜单 1.1",2); display_hz(2,1,"菜单 1.2",2); display_hz(3,0,"【菜单1.3 】",2); display_hz(4,3,"返回",2);}void fun8(){display_hz(1,1,"菜单 1.1",2); display_hz(2,1,"菜单 1.2",2); display_hz(3,1,"菜单1.3",2); display_hz(4,2,"【返回】",2);}void fun9()display_hz(1,0,"【菜单2.1 】",2); display_hz(2,1,"菜单2.2",2); display_hz(3,1,"菜单2.3",2); display_hz(4,3,"返回",2);}void fun10(){display_hz(1,1,"菜单2.1",2); display_hz(2,0,"【菜单2.2 】",2); display_hz(3,1,"菜单2.3",2); display_hz(4,3,"返回",2);}void fun11(){display_hz(1,1,"菜单 2.1",2); display_hz(2,1,"菜单 2.2",2); display_hz(3,0,"【菜单2.3 】",2); display_hz(4,3,"返回",2);}void fun12()display_hz(1,1,"菜单 2.1",2); display_hz(2,1,"菜单 2.2",2); display_hz(3,1,"菜单2.3",2); display_hz(4,2,"【返回】",2);}void fun13(){display_hz(1,0,"【菜单3.1 】",2); display_hz(2,1,"菜单3.2",2); display_hz(3,1,"菜单3.3",2); display_hz(4,3,"返回",2);}void fun14(){display_hz(1,1,"菜单3.1",2); display_hz(2,0,"【菜单3.2 】",2); display_hz(3,1,"菜单3.3",2); display_hz(4,3,"返回",2);}void fun15(){display_hz(3,0,"【菜单3.3 】",2); display_hz(4,3,"返回",2);}void fun16(){display_hz(1,1,"菜单 3.1",2); display_hz(2,1,"菜单 3.2",2); display_hz(3,1,"菜单3.3",2); display_hz(4,2,"【返回】",2);}void fun17(){display_hz(1,1,"菜单1.1.1",2); display_hz(2,1,"菜单1.1.2",2); display_hz(3,1,"菜单1.1.3",2); display_hz(4,2,"【返回】",2);}void fun18(){display_hz(1,1,"菜单1.2.1",3);display_hz(3,1,"菜单1.2.3",3); display_hz(4,2,"【返回】",2);}void fun19(){display_hz(1,1,"菜单1.3.1",2);display_hz(2,1,"菜单1.3.2",2);display_hz(3,1,"菜单1.3.3",2);display_hz(4,2,"【返回】",2); }void fun20(){display_hz(1,1,"菜单2.1.1",2); display_hz(2,1,"菜单2.1.2",2); display_hz(3,1,"菜单2.1.3",2); display_hz(4,2,"【返回】",2); } void fun21(){display_hz(3,1,"菜单2.2.3",2); display_hz(4,2,"【返回】",2); } void fun22(){display_hz(1,1,"菜单2.3.1",2); display_hz(2,1,"菜单2.3.2",2); display_hz(3,1,"菜单2.3.3",2); display_hz(4,2,"【返回】",2); } void fun23(){display_hz(1,1,"菜单3.1.1",2); display_hz(2,1,"菜单3.1.2",2); display_hz(3,1,"菜单3.1.3",2); display_hz(4,2,"【返回】",2); } void fun24(){display_hz(1,1,"菜单3.2.1",2); display_hz(2,1,"菜单3.2.2",2); display_hz(3,1,"菜单3.2.3",2);}void fun25(){display_hz(1,1,"菜单3.3.1",2);display_hz(2,1,"菜单3.3.2",2);display_hz(3,1,"菜单3.3.3",2);display_hz(4,2,"【返回】",2);}void fun26(){display_hz(1,0,"错",2);display_hz(2,0,"误",2);display_hz(3,0,"操",2);display_hz(4,0,"作",2);}/**************************结构体数组***************************************/ key_table table[30]= {{0,3,1,4,(*fun1)},//第一层,显示【菜单1】、菜单2、菜单3 、返回{1,0,2,8,(*fun2)},//第一层,显示菜单1、【菜单2】、菜单3 、返回{2,1,3,12,(*fun3)},//第一层,显示菜单1、菜单2、【菜单3】、返回{3,2,0,25,(*fun4)},//第一层,显示菜单1、菜单2、菜单3 、【返回】{4,7,5,16,(*fun5)},//第二层,菜单1层下显示【菜单1.1】、菜单1.2、菜单1.3、返回{5,4,6,17,(*fun6)},//第二层,菜单1层下显示菜单1.1、【菜单1.2】、菜单1.3、返回{6,5,7,18,(*fun7)}, //第二层,菜单1层下显示菜单1.1、菜单1.2、【菜单1.3】、返回{7,6,4,0,(*fun8)},//第二层,菜单1层下显示菜单 1.1、菜单 1.2、菜单 1.3、【返回】{8,11,9,19,(*fun9)},//第二层,菜单2层下显示【菜单2.1】、菜单2.2、菜单2.3、返回{9,8,10,20,(*fun10)},//第二层,菜单2层下显示菜单2.1、【菜单2.2】、菜单2.3、返回{10,9,11,21,(*fun11)}, //第二层,菜单2层下显示菜单 2.1、菜单 2.2、【菜单 2.3】、返回{11,10,8,1,(*fun12)},//第二层,菜单2层下显示菜单2.1、菜单2.2、菜单2.3、【返回】{12,15,13,22,(*fun13)},//第二层,菜单3层下显示【菜单3.1】、菜单3.2、菜单3.3、返回{13,12,14,23,(*fun14)}, //第二层,菜单3层下显示菜单3.1、【菜单3.2】、菜单3.3、返回{14,13,15,24,(*fun15)}, //第二层,菜单3层下显示菜单3.1、菜单3.2、【菜单3.3】、返回{15,14,12,2,(*fun16)}, //第二层,菜单3层下显示菜单3.1、菜单3.2、菜单3.3、【返回】{16,16,16,4,(*fun17)}, //第三层,菜单1.1层{17,17,17,5,(*fun18)}, //第三层,菜单1.2层{18,18,18,6,(*fun19)}, //第三层,菜单1.3层{19,19,19,8,(*fun20)}, //第三层,菜单2.1层{20,20,20,9,(*fun21)}, //第三层,菜单2.2层{21,21,21,10,(*fun22)}, //第三层,菜单2.3层{22,22,22,12,(*fun23)}, //第三层,菜单3.1层{23,23,23,13,(*fun24)}, //第三层,菜单3.2层{24,24,24,14,(*fun25)}, //第三层,菜单3.3层{25,25,25,0,(*fun26)}, //第0层};#include"msp430f149.h"#define uchar unsigned char#define uint unsigned int#define RS_0 (P3OUT&=~BIT0)#define RS_1 (P3OUT|=BIT0)#define RW_0 (P3OUT&=~BIT1)#define RW_1 (P3OUT|=BIT1)#define EN_0 (P3OUT&=~BIT2)#define EN_1 (P3OUT|=BIT2)/****************延时1ms******************/void delay1(uchar time){uint i,j;for(i=0;i<time;i++)< p="">{for(j=0;j<150;j++);}}/*************IO初始化*****************************/void lcd12864_init(void){P4DIR=0XFF;P6DIR|=BIT2;P6DIR |= BIT3;P3DIR|=0X07;}/**********lcdd写指令**************************/void write_con(uchar con){RS_0;RW_0;EN_0;P4OUT=con;delay1(2);EN_1;EN_0;}/****************lcd写数据********************************/ void write_data(uchar data){RS_1;RW_0;EN_0;P4OUT=data;delay1(2);EN_1;EN_0;}/***********lcd初始化****************************/void init(){P6OUT|=0X04;P6OUT |= BIT3;write_con(0x30);//基本指令集delay1(2);write_con(0x02);//地址归位delay1(2);write_con(0x0c);//显示delay1(2);write_con(0x01);//清屏delay1(2);write_con(0x06);//点设定delay1(2);}/*****************lcd写指令/数据地址****************************/void write_ardd(uchar hang,uchar lie){switch(hang){case 1 :write_con(0x80+lie);break;case 2 :write_con(0x90+lie);break;case 3 :write_con(0x88+lie);break;case 4 :write_con(0x98+lie);break;default:break;}}/*********************lcd显示数据串**************************************/ void display_shujc(ucharhang,uchar lie,uint shujc){uint i;uchar tab[4];write_ardd(hang,lie);tab[0]=shujc/1000;tab[1]=shujc%1000/100;tab[2]=shujc%100/10;tab[3]=shujc%10;for(i=0;i<4;i++){write_data(0x30+tab[i]);}}/***********************lcd显示数字******************************************/ void display_shuzi(uchar hang,uchar lie,uchar shuzi){write_ardd(hang,lie);write_data(0x30+shuzi);}/************************lcd显示汉字*****************************************************/void display_hz(uchar hang,uchar lie,uchar *data,uchar shu) {uint i;write_ardd(hang,lie);for(i=0;i<shu;i++)< p="">{while(*data!='\0'){write_data(*data); data++;}}}</shu;i++)<></time;i++)<> </time;i++)<>。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
单片机多级菜单编程实现单片机多级菜单编程实现(ZT)建立一个树状的菜单结构,用链表实现链表中包含:1、指向同级左右菜单和指向父菜单、子菜单的四个菜单结构体指针;2、进入该菜单时需要执行的初始化函数指针3、退出该菜单时需要执行的结束函数指针4、该菜单内的按键处理函数指针数组的指针操作菜单模块需要的按键操作有:左、右、确认、退出。
采用这种办法,可以方便的添加或删减菜单。
并且只需要在其头文件中修改初始变量就可以实现,完全无须修改C文件中的任何函数。
具体结构定义我的定义,做个参考:#define MENU_HLP_EN //菜单帮助信息使能typedef struct{void (*pMenuTaskInit)(void); //指向菜单任务初始化函数的指针void (*pMenuTaskEnd)(void); //指向菜单任务结束函数的指针}MENU_TASK_TYP;typedef struct MenuTyp{INT8U *MenuName; //菜单名称字符串WORK_MOD WorkMod; //工作状态编号MENU_TASK_TYP *pMenuTask; //指向菜单任务的指针void (**pTaskKeyDeal)(void); //指向菜单任务按键处理函数数组的指针#ifdef MENU_HLP_ENINT8U *MenuHlp; //菜单帮助字符串#endifstruct MenuTyp *pParent; //指向上层菜单的指针struct MenuTyp *pChild; //指向子菜单的指针struct MenuTyp *pRight; //指向右菜单的指针struct MenuTyp *pLeft; //指向左菜单的指针}MENU_TYP;我根据网上的资料做的一个菜单:/****************菜单数据结构**********************/struct KeyTabStruct{uint8 MenuIndex; //当前状态索引号uint8 MaxItems; //本级菜单最大条目数uint8 ShowLevel; //菜单显示内容uint8 PressOk; //按下"回车"键时转向的状态索引号uint8 PressEsc; //按下"返回"键时转向的状态索引号uint8 PressDown; //按下"向下"键时转向的状态索引号uint8 PressUp; //按下"向上"键时转向的状态索引号void (*CurrentOperate)(); //当前状态应该执行的功能操作};uint8 MenuID; //菜单ID号uint8 MenuNextID; //下级菜单ID号//CurMenuID=本菜单ID//MaxMenuItem=同级菜单最大项数//OkMenuID=子菜单层所对应的菜单ID,ID=999为菜单已经到底了//EscMenuID=父菜单层所对应的菜单ID,ID=999为菜单已经到顶了//DownMenuID=弟菜单层所对应的菜单ID,ID=999为菜单是独生子//UpMenuID=兄菜单层所对应的菜单ID,ID=999为菜单是独生子//CurFunction=本菜单所对应的菜单函数指针const struct KeyTabStruct KeyTab[MAX_KEYTABSTRUCT_NUM]={//CurMenuID, axMenuItem, MenuShowLevel, OkMenuID, EscMenuID, DownMenuID, UpMenuID, CurFunction{MENU_EDIT, 0, 0, MENU_DATA_VIEW, MENU_NO, MENU_NO, MENU_NO, *MenuEdit},{MENU_DATA_VIEW, 3, 1, MENU_DATA_VIEW_FIRE, MENU_EDIT, MENU_ SYS_EDIT, MENU_PRINT_DATA,*MenuEdit},{MENU_DATA_VIEW_FIRE, 5, MENU_NO, MENU_NO, MENU_DATA_VIEW, MENU_DATA_VIEW_TROUBLE, MENU_STEP_FOLLOW, *MenuDataViewIn}, {MENU_DATA_VIEW_TROUBLE, 5, MENU_NO, MENU_NO, MENU_DATA_VI EW, MENU_DATA_VIEW_REPEAT, MENU_DATA_VIEW_FIRE, *MenuDataVie wIn},{MENU_DATA_VIEW_REPEAT, 5, MENU_NO,MENU_NO, MENU_DATA_VIEW, MENU_FACE_CHECK,MENU_DATA_VIEW_TROUBLE, *MenuDataViewIn},{MENU_FACE_CHECK, 5, MENU_NO,MENU_NO, MENU_DATA_VIEW, MENU_STEP_FOLLOW,MENU_DATA_VIEW_REPEAT, *MenuFaceCheck},{MENU_STEP_FOLLOW, 5, MENU_NO,MENU_NO, MENU_DATA_VIEW, MENU_DATA_VIEW_FIRE, MENU_FACE_CH ECK,*MenuStepFollow},{MENU_SYS_EDIT, 3,2, MENU_SUM_SET, MENU_EDIT,MENU_PRINT_DATA, MENU_DATA_VIEW, *MenuEdit},{MENU_SUM_SET, 6, MENU_NO,MENU_NO, MENU_SYS_EDIT, MENU_EDIT_INSULATE,MENU_TIME_SET, *MenuSumSet},{MENU_EDIT_INSULATE, 6, MENU_NO,MENU_NO, MENU_SYS_EDIT, MENU_EDIT_HZ, MENU_SUM_SET,*MenuEditInsulate},{MENU_EDIT_HZ, 6, MENU_NO,MENU_NO, MENU_SYS_EDIT, MENU_LD_CONTROL,MENU_EDIT_INSULATE, *MenuEditHZ},{MENU_LD_CONTROL, 6,MENU_NO, MENU_NO, MENU_SYS_EDIT, MENU_LD_DELAY,MENU_EDIT_HZ, *MenuLDControl},{MENU_LD_DELAY, 6,MENU_NO, MENU_NO, MENU_SYS_EDIT, MENU_TIME_SET,MENU_LD_CONTROL, *MenuLDDelay},{MENU_TIME_SET, 6, MENU_NO,MENU_NO, MENU_SYS_EDIT, MENU_SUM_SET, MENU_LD_DELAY,*MenuTimeSet},{MENU_PRINT_DATA, 3, 3,MENU_PRINT_DATA_FIRE, MENU_EDIT, MENU_DATA_VIEW,MENU_SYS_EDIT, *MenuEdit},{MENU_PRINT_DATA_FIRE, 4,MENU_NO, MENU_NO, MENU_PRINT_DATA,MENU_PRINT_DATA_TROUBLE, MENU_PRINT_SET, *MenuPrintDataIn}, {MENU_PRINT_DATA_TROUBLE, 4, MENU_NO,MENU_NO, MENU_PRINT_DATA, MENU_PRINTER_CHECK,MENU_PRINT_DATA_FIRE, *MenuPrintDataIn},{MENU_PRINTER_CHECK, 4, MENU_NO,MENU_NO, MENU_PRINT_DATA, MENU_PRINT_SET,MENU_PRINT_DATA_TROUBLE, *MenuPrintDataIn},{MENU_PRINT_SET, 4, MENU_NO,MENU_NO, MENU_PRINT_DATA, MENU_PRINT_DATA_FIRE,MENU_PRINTER_CHECK, *MenuPrintSet},};/**************************************编程菜单显示数据******************************/const struct MenuDispData MenuEditShow[][MENU_MAX] = {{{MENU_NO , 0, 0, "选择: 消音→退出"}, //主菜单{MENU_DATA_VIEW , 1, 6, "⒈数据查看"},{MENU_SYS_EDIT , 2, 6, "⒉系统编程"},{MENU_PRINT_DATA , 3, 6, "⒊数据打印"}},{{MENU_NO , 0, 0, "数据查看: 消音→退出"}, //数据查看{MENU_DATA_VIEW_FIRE , 1, 4, "⒈火警"},{MENU_DATA_VIEW_TROUBLE, 2, 4, "⒉故障"},{MENU_DATA_VIEW_REPEAT , 3, 4, "⒊重码"},{MENU_FACE_CHECK , 1,12, "⒋面板检测"},{MENU_STEP_FOLLOW , 2,12, "⒌单步跟踪"}},{{MENU_NO , 0, 0, "系统编程: 消音→退出"}, //系统编程{MENU_SUM_SET , 1, 0, "⒈容量设置"},{MENU_EDIT_INSULATE , 2, 0, "⒉隔离点"},{MENU_EDIT_HZ , 3, 0, "⒊汉字描述"},{MENU_LD_CONTROL , 1,12, "⒋联动控制"},{MENU_LD_DELAY , 2,12, "⒌模块延时"},{MENU_TIME_SET , 3,12, "⒍时钟调整"}},{{MENU_NO , 0, 0, "数据打印: 消音→退出"}, //数据打印{MENU_PRINT_DATA_FIRE , 1, 0, "⒈火警数据"},{MENU_PRINT_DATA_TROUBLE,2, 0, "⒉故障数据"},{MENU_PRINTER_CHECK , 3, 0, "⒊打印机自检"},{MENU_PRINT_SET , 1,12, "⒋打印设置"}},};/***********************************等待按键******************** **************/void WaitKey(void){uint32 time;time = RTCFlag;WhichKey = KEY_NONE;while(!EscFlag){if(RTCFlag - time >= EDIT_TIME)EscFlag = TRUE;if(WhichKey != KEY_NONE){KeySound(300); //按键音return;}}}/*********************************显示多级菜单**********************************/void MenuEdit(){uint32 i,j=0;uint32 oldid;j = KeyTab[MenuID].ShowLevel;if(WhichKey == KEY_ESC || WhichKey == KEY_OK){ClearScreen();for(i=0;i<KeyTab[MenuNextID].MaxItems+1;i++) ShowString(MenuEditShow[j][i].Lin,MenuEditShow[j] [i].Column,MenuEditShow[j][i].Pdata,0); //初始化显示oldid =0;//没有原先选择的项}else{if(WhichKey == KEY_UP)oldid = KeyTab[MenuNextID].PressDown;elseoldid = KeyTab[MenuNextID].PressUp;//指示原先的项}for(i=1;i<KeyTab[MenuNextID].MaxItems+1;i++){if(MenuEditShow[j][i].Id == oldid)ShowString(MenuEditShow[j][i].Lin,MenuEditShow[j][i].Column,MenuEditShow[j][i].Pdata,0); //正常显示原先的项else{if(MenuEditShow[j][i].Id == MenuNextID)ShowString(MenuEditShow[j][i].Lin,MenuEditShow[j][i].Column,MenuEditShow[j][i].Pdata,1); //反显当前选择的项}}WhichKey = KEY_NONE;}/******************************系统编程************************* ******/uint32 Edit(void){struct KeyTabStruct NowKeyTab; //指示当前的菜单值uint32 escflag = FALSE;ResetFlag = FALSE;ChangeFlag = FALSE;EscFlag = FALSE;MenuID = MENU_EDIT;NowKeyTab = KeyTab[MenuID];MenuNextID = NowKeyTab.PressOk;(*NowKeyTab.CurrentOperate)(); //显示主菜单do{if(WhichKey == KEY_NONE)WaitKey(); //等待按键switch(WhichKey){case KEY_ESC : if(NowKeyTab.PressEsc != MENU_NO) {MenuID =NowKeyTab.PressEsc;MenuNextID =NowKeyTab.MenuIndex;NowKeyTab = KeyTab[MenuID];NowKeyTab.PressOk =MenuNextID;(*NowKeyTab.CurrentOperate)(); //显示当前菜单}elseescflag =TRUE; //退出编程状态break;case KEY_OK : if(NowKeyTab.PressOk != MENU_NO) {MenuID =NowKeyTab.PressOk;NowKeyTab = KeyTab[MenuID];MenuNextID =NowKeyTab.PressOk;}(*NowKeyTab.CurrentOperate)(); //执行当前按键的操作break;case KEY_UP : if((MenuNextID != MENU_NO) && (KeyTab[MenuNextID].PressUp != MENU_NO)){NowKeyTab.PressOk =KeyTab[MenuNextID].PressUp;MenuNextID = KeyTab[MenuNextID].PressUp;(*NowKeyTab.CurrentOperate)(); //执行当前按键的操作}break;case KEY_DOWN: if((MenuNextID != MENU_NO) && (KeyTab[MenuNextID].PressDown != MENU_NO)){NowKeyTab.PressOk =KeyTab[MenuNextID].PressDown;MenuNextID = KeyTab[MenuNextID].PressDown;(*NowKeyTab.CurrentOperate)(); //执行当前按键的操作}break;case KEY_RESET: ResetFlag = TRUE;break;default : break;}}while(!ResetFlag && !EscFlag && !escflag);if(ChangeFlag && !EscFlag && !ResetFlag) EditDataChange();if(ResetFlag)return SYS_RESET;else{return 0;}}关于这个菜单的说明:1.我用的是ARM处理器,所以51的时候把const改成code,uint32改成unsign ed char。