原创 一个简单却实用的菜单程序

2008-5-13 11:10 3026 5 6 分类: 测试测量
如果编写简单的程序的话这个菜单函数就可以不用看了,但是当你编写到复杂的程序的时候就可能就会为
人机界面和各个函数直接的连接而烦恼了,这个菜单函数就是用来解决这个问题,虽然没有UCGUI厉害,但是我觉得代码在2000行一下的话用起来还是不错
的选择的.虽说简单但是用到了结构体大部分的知识了,希望c语言不太好的朋友自己补习一下好了.

主要程序:
CODE:
#define Null 0


/***********************
* 函数声明 *
***********************/
void ShowMenu(void);
void Menu_Change(unsigned char KeyNum);

/***********************
* 按键功能键宏定义 *
***********************/
#define UP     '3'
#define Down '7'
#define Esc   'B'
#define Enter 'F'
#define Reset '0'


/**********************
* 目录结构体定义 *
**********************/
struct MenuItem
{
unsigned char MenuCount;   //当前层节点数
unsigned char *DisplayString; //菜单标题
void (*Subs)();     //节点函数
struct MenuItem *ChildrenMenus; //子节点
struct MenuItem *ParentMenus; //父节点
};

/***********************
* 调用子函数区 *
***********************/
void NullSubs(void)
{
}
//----------------------以下为例子,请根据实际情况修改---------------------------

void TimeSet(void)
{
put_s("TimeSet");
}

void DateSet(void)
{
put_s("DateSet");
}

void AlertSet (void)
{
put_s("AlertSet");
}
//------------------------------------------------------------------------------


/***********************
* 结构体区 *
***********************/
//----------------------以下为例子,请根据实际情况修改---------------------------
struct MenuItem TimeMenu[4];
struct MenuItem FlashMenu[5];
struct MenuItem VoiceMenu[5];
struct MenuItem RobotMenu[5];
struct MenuItem MainMenu[5];

struct MenuItem TimeMenu[4]=
{ //MenuCount   DisplayString   Subs   ChildrenMenus ParentMenus
{4,   "1.Time Set",   TimeSet,   Null,   MainMenu},
{4,   "2.Date Set",   DateSet,   Null,   MainMenu},
{4,   "3.AlertSet",   AlertSet,   Null,   MainMenu},
{4,     "4.Back",     NullSubs,   MainMenu,   MainMenu},
};

struct MenuItem FlashMenu[5]=
{ //MenuCount   DisplayString   Subs   ChildrenMenus ParentMenus
{5,   "1.Flash Record",   NullSubs,   Null,   MainMenu},
{5,   "2.Play",     NullSubs,   Null,   MainMenu},
{5,   "3.Pause",     NullSubs,   Null,   MainMenu},
{5,     "4.Flash Delete",   NullSubs,   Null,   MainMenu},
{5,   "5.Back",   NullSubs,   MainMenu,   MainMenu},
};

struct MenuItem VoiceMenu[5]=
{ //MenuCount   DisplayString   Subs   ChildrenMenus ParentMenus
{5,   "1.Voice Record" , NullSubs,   Null,   MainMenu},
{5,   "2.Play",     NullSubs,   Null,   MainMenu},
{5,   "3.Pause",       NullSubs,   Null,   MainMenu},
{5,     "4.Voice Delete",   NullSubs,   Null,   MainMenu},
  {5,   "5.Back",   NullSubs,   MainMenu,   MainMenu},
};

struct MenuItem RobotMenu[5]=
{ //MenuCount   DisplayString   Subs   ChildrenMenus ParentMenus
{5,   "1.Turn Left",   NullSubs,   Null,   MainMenu},
{5,   "2.Turn Right",   NullSubs,   Null,   MainMenu},
{5,   "3.Go Ahead",   NullSubs,   Null,   MainMenu},
{5,     "4.Go Back",   NullSubs,   Null,   MainMenu},
{5,   "5.Back",   NullSubs,   MainMenu,   MainMenu},
};


struct MenuItem MainMenu[5]=
{ //MenuCount   DisplayString   Subs   ChildrenMenus ParentMenus
{5,   "1.Time Set" ,   NullSubs,   TimeMenu,   Null},
{5,   "2.Voice Center",   NullSubs,   VoiceMenu,   Null},
{5,   "3.Robot Control",   NullSubs,   RobotMenu,   Null},
{5,     "4.Flash Option",   NullSubs,   FlashMenu,   Null},
  {5,   "5.Back",   NullSubs,   MainMenu,   MainMenu},
};
//------------------------------------------------------------------------------


/***********************
* 全局变量声明区 *
***********************/
struct MenuItem (*MenuPoint) = MainMenu; //结构体指针,指向结构体后由内部函数指针指向功能函数
unsigned char DisplayStart = 0; //显示时的第一个菜单项
unsigned char UserChoose = 0;   //用户所选菜单项
unsigned char DisplayPoint = 0; //显示指针
unsigned MaxItems;       //同级最大菜单数
unsigned char ShowCount=2; //同屏显示菜单数


/***********************
*显示函数区 *
***********************/
void ShowMenu(void)
{
  unsigned char n;
MaxItems = MenuPoint[0].MenuCount;//定义最大同级菜单
DisplayPoint = DisplayStart;
for(n=0;DisplayPoint<MaxItems&&n<ShowCount;n++)
  {if(DisplayPoint==UserChoose)
  LCD_write_string(0,n,"->");
  LCD_write_string(2,n,MenuPoint[DisplayPoint++].DisplayString);
 
  }

}

void Menu_Change(unsigned char KeyNum)
{
if(KeyNum)
{
  switch(KeyNum)
  {    
      case UP:
    UserChoose --;
    if (UserChoose ==255)
    {
      UserChoose = 0;//上翻截至,如果要回滚赋值MaxItems-1
    }
    break;
    case Esc:
    if (MenuPoint[UserChoose].ParentMenus != Null)
    {
      MenuPoint = MenuPoint[UserChoose].ParentMenus;
    UserChoose = 0;
    DisplayStart = 0;
    }
    break;
    case Down:
    UserChoose ++;
    if (UserChoose == MaxItems)
    {
      UserChoose = MaxItems-1;//下翻截至,如要回滚赋值为0
    }
    break;
    case Enter:
    if (MenuPoint[UserChoose].Subs != NullSubs)
    {
      (*MenuPoint[UserChoose].Subs)();
    }
    else if (MenuPoint[UserChoose].ChildrenMenus != Null)
    {
      MenuPoint = MenuPoint[UserChoose].ChildrenMenus;
      UserChoose = 0;
      DisplayStart = 0;
    }
    break;
    case Reset:
      MenuPoint = MainMenu;
    UserChoose = 0;
    DisplayStart = 0;
    break;
    default:break;
  }
  if (UserChoose%ShowCount==0)       //一屏只能显示ShowCount行
  DisplayStart = UserChoose;
  else if(UserChoose==1||UserChoose== 3)
    DisplayStart = UserChoose-1;   //实现滚屏的关键  
  LCD_write_command(0x01);     //液晶清屏,根据不同液晶函数自行修改
  delay_nms(5);       //液晶为慢速器件
  ShowMenu();
}
}

转自AVR与虚拟仪器论坛

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户1239567 2008-5-17 09:55

学习!
相关推荐阅读
用户128507 2009-09-08 16:04
ceshi
...
用户128507 2009-08-07 15:47
测试
测试...
用户128507 2009-02-02 11:29
解读脉动式血氧计概念及设计提示(一)
脉动式血氧计由放在病人耳垂、脚趾或手指的传感器组成,该传感器与数据采集系统连接,计算和显示氧水平、心率和血流量。对于设计工程师而言,该系统的主要实现挑战是什么?对于器件选择都有哪些要求?本文将为你解读...
用户128507 2009-02-02 11:28
一种嵌入式智能寻迹机器人设计
1 引言   在信息技术的飞速发展,计算机,通讯、消费电子三种技术合一的后PC的时代,虽然计算机和网络已经全面渗透到日常生活的每一个角落,但各种各样的新型嵌入式接入设备已经成为当前的主流产品。任何一个...
用户128507 2009-02-02 11:25
中国MCU市场增长平缓 新兴应用成追逐热点
受集成电路产业周期进入低增长阶段的影响,2008年全球MCU市场增长缓慢,尤其是欧美市场表现不尽人意。一直引领全球增长的中国MCU市场,虽然仍旧表现为明显高于全球平均水平的增长态势,但受中国电子产品制...
用户128507 2009-02-02 11:24
欧姆龙(大连)电子血压计被曝不合格
北京市药监局曝光了本市24批次不合格医疗器械,这些不合格器械将被查处。  市药监局发布,去年下半年,本市共抽验292批次医疗器械,其中24批次不合格。这24批次不合格医疗器械包括:北京绿之佳科技发展有...
我要评论
1
5
关闭 站长推荐上一条 /3 下一条