<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 單片機(jī)多級菜單編程實(shí)現(xiàn)

          單片機(jī)多級菜單編程實(shí)現(xiàn)

          作者: 時(shí)間:2016-11-27 來源:網(wǎng)絡(luò) 收藏
          建立一個(gè)樹狀的菜單結(jié)構(gòu),用鏈表實(shí)現(xiàn)

          鏈表中包含:

          本文引用地址:http://www.ex-cimer.com/article/201611/322426.htm

          1、指向同級左右菜單和指向父菜單、子菜單的四個(gè)菜單結(jié)構(gòu)體指針;

          2、進(jìn)入該菜單時(shí)需要執(zhí)行的初始化函數(shù)指針

          3、退出該菜單時(shí)需要執(zhí)行的結(jié)束函數(shù)指針

          4、該菜單內(nèi)的按鍵處理函數(shù)指針數(shù)組的指針操作菜單模塊需要的按鍵操作有:左、右、確

          認(rèn)、退出。

          采用這種辦法,可以方便的添加或刪減菜單。并且只需要在其頭文件中修改初始變量就可

          以實(shí)現(xiàn),完全無須修改C文件中的任何函數(shù)。

          具體結(jié)構(gòu)定義

          我的定義,做個(gè)參考:

          #defineMENU_HLP_EN//菜單幫助信息使能

          typedef struct

          {

          void (*pMenuTaskInit)(void);//指向菜單任務(wù)初始化函數(shù)的指針

          void (*pMenuTaskEnd)(void);//指向菜單任務(wù)結(jié)束函數(shù)的指針

          }MENU_TASK_TYP;

          typedef struct MenuTyp

          {

          INT8U*MenuName;//菜單名稱字符串

          WORK_MODWorkMod;//工作狀態(tài)編號(hào)

          MENU_TASK_TYP*pMenuTask;//指向菜單任務(wù)的指針

          void (**pTaskKeyDeal)(void);//指向菜單任務(wù)按鍵處理函數(shù)數(shù)組的指針

          #ifdef MENU_HLP_EN

          INT8U*MenuHlp;//菜單幫助字符串

          #endif

          struct MenuTyp*pParent;//指向上層菜單的指針

          struct MenuTyp*pChild;//指向子菜單的指針

          struct MenuTyp*pRight;//指向右菜單的指針

          struct MenuTyp*pLeft;//指向左菜單的指針

          }MENU_TYP;

          我根據(jù)網(wǎng)上的資料做的一個(gè)菜單:

          struct KeyTabStruct{

          uint8MenuIndex;//當(dāng)前狀態(tài)索引號(hào)

          uint8MaxItems;//本級菜單最大條目數(shù)

          uint8ShowLevel;//菜單顯示內(nèi)容

          uint8PressOk;//按下"回車"鍵時(shí)轉(zhuǎn)向的狀態(tài)索引號(hào)

          uint8PressEsc;//按下"返回"鍵時(shí)轉(zhuǎn)向的狀態(tài)索引號(hào)

          uint8PressDown;//按下"向下"鍵時(shí)轉(zhuǎn)向的狀態(tài)索引號(hào)

          uint8PressUp;//按下"向上"鍵時(shí)轉(zhuǎn)向的狀態(tài)索引號(hào)

          void(*CurrentOperate)();//當(dāng)前狀態(tài)應(yīng)該執(zhí)行的功能操作

          };

          uint8MenuID;//菜單ID號(hào)

          uint8MenuNextID;//下級菜單ID號(hào)

          //CurMenuID=本菜單ID

          //MaxMenuItem=同級菜單最大項(xiàng)數(shù)

          //OkMenuID=子菜單層所對應(yīng)的菜單ID,ID=999為菜單已經(jīng)到底了

          //EscMenuID=父菜單層所對應(yīng)的菜單ID,ID=999為菜單已經(jīng)到頂了

          //DownMenuID=弟菜單層所對應(yīng)的菜單ID,ID=999為菜單是獨(dú)生子

          //UpMenuID=兄菜單層所對應(yīng)的菜單ID,ID=999為菜單是獨(dú)生子

          //CurFunction=本菜單所對應(yīng)的菜單函數(shù)指針

          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_VIEW,MENU_DATA_VIEW_REPEAT,MENU_DATA_VIEW_FIRE,*MenuDataViewIn},

          {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_CHECK,

          *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 MenuDispDataMenuEditShow[][MENU_MAX] = {

          {{MENU_NO, 0, 0, "選擇:消音→退出"},//主菜單

          {MENU_DATA_VIEW, 1, 6, "⒈數(shù)據(jù)查看"},

          {MENU_SYS_EDIT, 2, 6, "⒉系統(tǒng)編程"},

          {MENU_PRINT_DATA, 3, 6, "⒊數(shù)據(jù)打印"}},

          {{MENU_NO, 0, 0, "數(shù)據(jù)查看:消音→退出"},//數(shù)據(jù)查

          {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, "系統(tǒng)編程:消音→退出"},//系統(tǒng)編程

          {MENU_SUM_SET, 1, 0, "⒈容量設(shè)置"},

          {MENU_EDIT_INSULATE, 2, 0, "⒉隔離點(diǎn)"},

          {MENU_EDIT_HZ, 3, 0, "⒊漢字描述"},

          {MENU_LD_CONTROL, 1,12, "⒋聯(lián)動(dòng)控制"},

          {MENU_LD_DELAY, 2,12, "⒌模塊延時(shí)"},

          {MENU_TIME_SET, 3,12, "⒍時(shí)鐘調(diào)整"}},

          {{MENU_NO, 0, 0, "數(shù)據(jù)打印:消音→退出"},//數(shù)據(jù)打印

          {MENU_PRINT_DATA_FIRE, 1, 0, "⒈火警數(shù)據(jù)"},

          {MENU_PRINT_DATA_TROUBLE,2, 0, "⒉故障數(shù)據(jù)"},

          {MENU_PRINTER_CHECK, 3, 0, "⒊打印機(jī)自檢"},

          {MENU_PRINT_SET, 1,12, "⒋打印設(shè)置"}},

          };

          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

          ShowString(MenuEditShow[j][i].Lin,MenuEditShow[j]

          [i].Column,MenuEditShow[j][i].Pdata,0);//初始化顯示

          oldid =

          0;

          //沒有原先選擇的項(xiàng)

          }else{

          if(WhichKey == KEY_UP)

          oldid = KeyTab[MenuNextID].PressDown;

          else

          oldid = KeyTab

          [MenuNextID].PressUp;

          //指示原先的項(xiàng)

          }

          for(i=1;i

          if(MenuEditShow[j][i].Id == oldid)

          ShowString(MenuEditShow[j][i].Lin,MenuEditShow[j]

          [i].Column,MenuEditShow[j][i].Pdata,0);//正常顯示原先的項(xiàng)

          else{

          if(MenuEditShow[j][i].Id == MenuNextID)

          ShowString(MenuEditShow[j][i].Lin,MenuEditShow

          [j][i].Column,MenuEditShow[j][i].Pdata,1);//反顯當(dāng)前選擇的項(xiàng)

          }

          }

          WhichKey = KEY_NONE;

          }

          uint32 Edit(void)

          {

          struct KeyTabStruct NowKeyTab;//指示當(dāng)前的菜單值

          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)

          ();//顯示當(dāng)前菜單

          }else

          escflag =

          TRUE;//退出編程狀態(tài)

          break;

          case KEY_OK:if(NowKeyTab.PressOk != MENU_NO)

          {

          MenuID =

          NowKeyTab.PressOk;

          NowKeyTab = KeyTab

          [MenuID];

          MenuNextID =

          NowKeyTab.PressOk;

          }

          (*NowKeyTab.CurrentOperate)

          ();//執(zhí)行當(dāng)前按鍵的操作

          break;

          case KEY_UP:if((MenuNextID != MENU_NO) &&

          (KeyTab[MenuNextID].PressUp != MENU_NO)){

          NowKeyTab.PressOk =

          KeyTab[MenuNextID].PressUp;

          MenuNextID = KeyTab

          [MenuNextID].PressUp;

          (*NowKeyTab.CurrentOperate)();//執(zhí)行當(dāng)前按鍵的操作

          }

          break;

          case KEY_DOWN:if((MenuNextID != MENU_NO) &&

          (KeyTab[MenuNextID].PressDown != MENU_NO)){

          NowKeyTab.PressOk =

          KeyTab[MenuNextID].PressDown;

          MenuNextID = KeyTab

          [MenuNextID].PressDown;

          (*NowKeyTab.CurrentOperate)();//執(zhí)行當(dāng)前按鍵的操作

          }

          break;

          case KEY_RESET: ResetFlag = TRUE;

          break;

          default: break;

          }

          }while(!ResetFlag && !EscFlag && !escflag);

          if(ChangeFlag && !EscFlag && !ResetFlag)

          EditDataChange();

          if(ResetFlag)

          returnSYS_RESET;

          else{

          return0;

          }

          }

          關(guān)于這個(gè)菜單的說明:

          1.我用的是ARM處理器,所以51的時(shí)候把const改成code,uint32改成unsigned char。

          2.在網(wǎng)上的資料中,結(jié)構(gòu)體數(shù)組是存在RAM中的,我把它放在也flash中了,然后再定義一個(gè)

          結(jié)構(gòu)體變量,就樣就可以省很多RAM,比較適合51.

          3.在網(wǎng)上資料中,因?yàn)楸4媪嗽瓉淼倪x擇,當(dāng)你離開編程狀態(tài)重新進(jìn)行后,會(huì)發(fā)現(xiàn)選擇上會(huì)

          是原來進(jìn)行的順序,我改動(dòng)之后,退出上一級菜單還是你選的那一項(xiàng),但重新進(jìn)入后就是第

          一個(gè)指定項(xiàng)。

          4.增加UP和DOWN顯示,可以反顯最新選定的選項(xiàng),正常顯示原來的選項(xiàng)。



          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();