微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 多级菜单设计

多级菜单设计

时间:10-02 整理:3721RD 点击:

菜单设计是嵌入式中不可或缺的一部分,有的简单粗暴的,有的细致复杂。

关于菜单设计的方案也很多,专业问题大家可以参考下相关文献,这里我选择了一种结构鲜明、易于维护,实现简单的方法。

一般来说,多级菜单的逻辑结构都是多叉树的拓扑结构:

像这种:






在编程中,与之对应的可以用链表来组织。

首先确定一个菜单项需要具备的属性:本页菜单数量、显示内容、执行函数、上级菜单、下级菜单。


  1. struct        MenuItem                                                        //
  2. {        unsigned char         MenuCount;                         //
  3.         const char         *DisplayString;                            //
  4.         unsigned char         (*Subs)();                        //
  5.         struct MenuItem         *ChildrenMenus;                //
  6.         struct MenuItem         *ParentMenus;                  //
  7. };

复制代码



例如一页菜单中有5项,可以这样组织:


  1. struct MenuItem MainMenu[5] =      //
  2. {
  3.         {5,"1.SysTem Set    ",&fun1,SysTemSet,NULL},
  4.         {5,"2.EquipmenT ID  ",NULL, EquipmenT, NULL},
  5.         {5,"3.BaudRatE      ",NULL, BaudRatE, NULL},
  6.         {5,"4.System Infor  ",NULL, NULL, NULL},
  7.         {5,"5.System Haha  ",NULL, NULL, NULL},
  8. };

复制代码

下级菜单同理:


  1. struct MenuItem SysTemSet[5] =           //
  2. {
  3.         {5,"1.DatA  Set     ",NULL,NULL,MainMenu},
  4.         {5,"2.TimE  Set     ",NULL,NULL,MainMenu},
  5.         {5,"3.AlarM Set     ",NULL,NULL,MainMenu},
  6.         {5,"4.BacKLed  Set  ",NULL,NULL,MainMenu},
  7.         {5,"5.Password Set  ",NULL,NULL,   NULL},
  8. };

  9. struct MenuItem BaudRatE[7] =           //
  10. {
  11.         {7,"1.2400          ",NULL,NULL,MainMenu},
  12.         {7,"2.4800          ",NULL,NULL,MainMenu},
  13.         {7,"3.9600          ",NULL,NULL,MainMenu},
  14.         {7,"4.19200         ",NULL,NULL,MainMenu},
  15.         {7,"5.38400         ",NULL,NULL,MainMenu},
  16.         {7,"6.57600         ",NULL,NULL,MainMenu},
  17.         {7,"7.115200        ",NULL,NULL,MainMenu},
  18. };

  19. struct MenuItem EquipmenT[4] =           //
  20. {
  21.         {4,"1.No.01         ",NULL,NULL,MainMenu},
  22.         {4,"2.No.02         ",NULL,NULL,MainMenu},
  23.         {4,"3.NO.03         ",NULL,NULL,MainMenu},
  24.         {4,"4.No.04         ",NULL,NULL,MainMenu},
  25. };

复制代码

接下根据输入操作来改变指针指向的菜单结构体就可以了。

我这里只有2个按键,定义功能为:点击0键:上,点击1键:下,

                                                                           短按0键:后退,短按1键:进入,

每次改变光标位置后后,由show_cursor()函数刷新光标位置。

翻页或切换新菜单后,由show_current_menu()函数刷新显示菜单。


  1. struct MenuItem* ptrMenu = MainMenu;
  2. u8 select_num = 0;
  3. u8 page = 0;

  4.         show_current_menu(ptrMenu, select_num/LCD_MAX_DISP_LINES);

  5.         while(1)
  6.         {
  7.             static u8 key_num = 0;

  8.             while(key_num == 0)
  9.             {
  10.                 key_num = get_key_value();
  11.             }
  12.             if(key1_cilck == key_num)//plus
  13.             {
  14.                 select_num = (select_num + 1)%ptrMenu->MenuCount;
  15.                 show_cursor(select_num%LCD_MAX_DISP_LINES);
  16.                 if(select_num/LCD_MAX_DISP_LINES != page)
  17.                 {
  18.                     show_current_menu(ptrMenu, select_num/LCD_MAX_DISP_LINES);
  19.                     page = select_num/LCD_MAX_DISP_LINES;
  20.                 }
  21.             }
  22.             if(key0_cilck == key_num)//minus
  23.             {
  24.                 if(select_num > 0)select_num--;
  25.                 show_cursor(select_num%LCD_MAX_DISP_LINES);
  26.                 if(select_num/LCD_MAX_DISP_LINES != page)
  27.                 {
  28.                     show_current_menu(ptrMenu, select_num/LCD_MAX_DISP_LINES);
  29.                     page = select_num/LCD_MAX_DISP_LINES;
  30.                 }            
  31.             }
  32.             if(key1_short == key_num)//enter
  33.             {
  34.                 if((ptrMenu+select_num)->ChildrenMenus!=NULL)
  35.                     ptrMenu = (ptrMenu+select_num)->ChildrenMenus;
  36.                 show_current_menu(ptrMenu, select_num/LCD_MAX_DISP_LINES);
  37.                 select_num = 0;
  38.                 show_cursor(select_num%LCD_MAX_DISP_LINES);
  39.             }
  40.             if(key0_short == key_num)//esc
  41.             {
  42.                 if((ptrMenu+select_num)->ParentMenus!=NULL)
  43.                     ptrMenu = (ptrMenu+select_num)->ParentMenus;
  44.                 show_current_menu(ptrMenu, select_num/LCD_MAX_DISP_LINES);
  45.                 select_num = 0;
  46.                 show_cursor(select_num%LCD_MAX_DISP_LINES);
  47.             }
  48.             key_num = 0;
  49.        }

复制代码



Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top