<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          C語(yǔ)言映射表在嵌入式串口解析、UI設(shè)計(jì)中的應(yīng)用

          共 11704字,需瀏覽 24分鐘

           ·

          2021-09-18 11:05

          關(guān)注、星標(biāo)公眾號(hào),直達(dá)精彩內(nèi)容

          來(lái)源:網(wǎng)絡(luò)素材

          整理:嵌入式云IOT技術(shù)圈


          一直很想寫(xiě)關(guān)于映射表在MCU開(kāi)發(fā)中的各種應(yīng)用,在工作中我也經(jīng)常用,不僅美觀,而且寫(xiě)出來(lái)的程序可拓展性極高,看到群里已經(jīng)有網(wǎng)友對(duì)映射表的應(yīng)用做了相應(yīng)的總結(jié),而且簡(jiǎn)單易懂,上來(lái)就是肝,我們來(lái)看看吧:

          一、映射表在串口數(shù)據(jù)解析中的應(yīng)用

          1、數(shù)據(jù)結(jié)構(gòu)

          typedef struct 
          {
              char CMD[CMDLen];
              unsigned char (*cmd_operate)(char *data);
          }Usart_Tab;

          2、指令、函數(shù)映射表

          static const Usart_Tab InstructionList[CMDMax]=
          {
              {"PWON",PowOn},
              {"PWOFF",PowOff},
              {"HDCP",HdcpOnOff},
              {"/V",QueryKaVersion},
              {"EDIDUpgrade",UpdataEDID},
              {"Psave",Psave},
              {"Precall",Precall},
              {"Pclear",Pclear},
          };

          3、串口解析函數(shù)實(shí)現(xiàn)

          unsigned char DataAnalysis(char *buf)
          {
            unsigned char i,Result;
            char *NEXT=NULL;
            for(i=0;i<CMDMax;i++)
            {
              NEXT=StrCmp(buf,(char*)InstructionList[i].CMD);
              if(NEXT!=NULL)
              {
                usartfuncp=InstructionList[i].cmd_operate;
                Result=(*usartfuncp)(NEXT);
              }
            }
            return Result;
          }

          二、映射表在UI設(shè)計(jì)中的應(yīng)用

          1、數(shù)據(jù)結(jié)構(gòu)

          菜單枚舉:

          typedef enum
          {
            stage1=0,
            stage2,
            stage3,
            stage4,
            stage5,
            stage6,
            stage7,
            stage8,
            stage9,
          }SCENE;

          數(shù)據(jù)結(jié)構(gòu):

          typedef struct {
            void (*current_operate)(); //當(dāng)前場(chǎng)景的處理函數(shù)
            SCENE Index;               //當(dāng)前場(chǎng)景的標(biāo)簽
            SCENE Up;                  //按下Up鍵跳轉(zhuǎn)的場(chǎng)景
            SCENE Down;                //按下Down鍵跳轉(zhuǎn)的場(chǎng)景
            SCENE Right;               //按下Left鍵跳轉(zhuǎn)的場(chǎng)景
            SCENE Left;                //按下Right鍵跳轉(zhuǎn)的場(chǎng)景
          }STAGE_TAB;

          2、函數(shù)映射表

          STAGE_TAB stage_tab[]={
            #.    operate       Index    Up     Down    Left   Right   
            {Stage1_Handler,  stage1,  stage4,  stage7,  stage3, stage2},
            {Stage2_Handler,  stage2,  stage5,  stage8,  stage1, stage3},
            {Stage3_Handler,  stage3,  stage6,  stage9,  stage2, stage1},
            {Stage4_Handler,  stage4,  stage7,  stage1,  stage6, stage5},
            {Stage5_Handler,  stage5,  stage8,  stage2, stage4,  stage6},
            {Stage6_Handler,  stage6,  stage9,  stage3, stage5,  stage4},
            {Stage7_Handler,  stage7,  stage1,  stage4, stage9,  stage8},
            {Stage8_Handler,  stage8,  stage2,  stage5, stage7,  stage9},
            {Stage9_Handler,  stage9,  stage3,  stage6, stage8,  stage7},
          };

          3、定義兩個(gè)變量保存當(dāng)前場(chǎng)景和上一個(gè)場(chǎng)景

          char current_stage=stage1;
          char prev_stage=current_stage;

          4、按下Up按鍵 跳轉(zhuǎn)到指定場(chǎng)景current_stage的值根據(jù)映射表改變

          current_stage =stage_tab[current_stage].Up;

          5、場(chǎng)景改變后 根據(jù)映射表執(zhí)行相應(yīng)的函數(shù)Handler

          if(current_stage!=prev_stage)
          {
            stage_tab[current_stage].current_operate();
            prev_stage=current_stage;

          以上文章轉(zhuǎn)載自:

          CSDN博客鏈接:https://blog.csdn.net/appleJanLinux

          三、單片機(jī)實(shí)現(xiàn)屏幕界面,多層菜單(綜合版)

          1、數(shù)據(jù)結(jié)構(gòu)

          (1)行元素結(jié)構(gòu)體

          typedef struct{
           uint16_t enterViewIndex;//按下確定鍵跳轉(zhuǎn)的界面
           char * text;            //當(dāng)前行顯示的文本
           HandlerFunc handler;    //顯示函數(shù)
          }RowListTypeDef;

          HandlerFunc是函數(shù)指針,此函數(shù)即可作為行元素的顯示函數(shù),又可作為按鍵處理函數(shù),其類(lèi)型為:

          typedef void(*HandlerFunc)(uint16_t index, char* p, uint8_t key); 

          三個(gè)形參的作用分別是:

          @param index: 指向此函數(shù)的RowListTypeDef在數(shù)組中的下標(biāo)
          @param p: 指向當(dāng)前RowListTypeDef元素的text指針指向的字符串
          @param key: 若按下按鍵的值大于等于6(KEY_ADD),則此形參會(huì)是非0值(KEY_NONE);若小于6,則傳入0(KEY_NONE)

          (2)界面結(jié)構(gòu)體

          typedef struct {
           const RowListTypeDef * const list;//指向當(dāng)前層所指向的行元素
           uint16_t lengthOfList;            //指向的行元素的長(zhǎng)度
           uint16_t parentViewIndex;         //本元素所屬層的標(biāo)號(hào)
           uint16_t startRow;                //記錄在上一層時(shí)的開(kāi)始行索引
           uint8_t currRow;                  //記錄在上一層時(shí)的行索引
          }ViewListTypeDef;

          定義ViewListTypeDef型數(shù)組是可以使用VIEW_MEMBER_FORMAT(x)幫助編寫(xiě);如:

          ViewListTypeDef menu[] = {
           VIEW_MEMBER_FORMAT(rowListHome),
           VIEW_MEMBER_FORMAT(rowListSettingRoot),
           VIEW_MEMBER_FORMAT(rowListView1),
           VIEW_MEMBER_FORMAT(rowListView2),
           VIEW_MEMBER_FORMAT(rowListView3),
          VIEW_MEMBER_FORMAT(rowListView1_1),
          };

          其中VIEW_MEMBER_FORMAT宏定義為

          #define ROW_LENGTH(x)       ((uint16_t)(sizeof(x)/sizeof(RowListTypeDef)))
          #define VIEW_MEMBER_FORMAT(x)       {x,ROW_LENGTH(x),0,0,0}

          (3)游標(biāo)結(jié)構(gòu)體

          //游標(biāo),只需要定義一個(gè)即可    ==> 8字節(jié)(byte)
          typedef struct {
           uint8_t currRow;           //當(dāng)前指向元素
           uint8_t keyval;            //記錄按鍵
            uint16_t currViewIndex;   //當(dāng)前指向?qū)?br style="box-sizing: border-box;"> uint16_t startRow;         //屏幕第一行顯示的行元素索引
           uint16_t rowNum;           //記錄當(dāng)前層的行元素?cái)?shù)
          }CursorTypeDef;

          函數(shù)作用

          本控件函數(shù)很少,只有兩個(gè),即:

          void View_Init(ViewListTypeDef * v, CursorTypeDef * c)

          此函數(shù)的作用是初始化界面控件:將用戶(hù)定義好的ViewListTypeDef數(shù)組的地址和CursorTypeDef地址初始化到控件

          void View_Loop(void)

          此函數(shù)作用是在處理界面數(shù)據(jù)。注意:需要將此函數(shù)放入主循環(huán)中,每隔一段時(shí)間調(diào)用一次。

          間隔時(shí)間典型值是100ms。

          注意:并不是本控件消耗的時(shí)間多,而是屏幕驅(qū)動(dòng)程序消耗的時(shí)間太多,本人的屏幕驅(qū)動(dòng)是模擬的SPI時(shí)序而不是單片機(jī)硬件SPI,故屏幕驅(qū)動(dòng)消耗的時(shí)間太多??丶看涡枰坏?000個(gè)機(jī)器周期,而驅(qū)動(dòng)程序是其上百倍。

          若使用硬件外設(shè)驅(qū)動(dòng)屏幕,則可以將間隔時(shí)間適當(dāng)調(diào)小一點(diǎn),同時(shí)注意不要低于屏幕刷新周期。

          設(shè)計(jì)界面時(shí)只需要定義幾個(gè)數(shù)組即可。

          首先定義RowListTypeDef類(lèi)型數(shù)組,根據(jù)界面數(shù)定義數(shù)組個(gè)數(shù),根據(jù)每個(gè)界面包含的行元素?cái)?shù)定義每個(gè)數(shù)組的長(zhǎng)度。

          然后定義ViewListTypeDef類(lèi)型數(shù)組,定義一個(gè)即可,數(shù)組長(zhǎng)度是界面數(shù)決定的。

          例如,定義一個(gè)實(shí)現(xiàn)界面的大數(shù)組:

          const RowListTypeDef rowListHome[] = {  
           //{.enterViewIndex  |  .x  |  .text  |  .handler},
             {1,"home",NULL},
          };

          const RowListTypeDef rowListSRoot[] = {  
           //{.enterViewIndex  |  .x  |  .text  |  .handler},
           {2,"Row 1",NULL},
           {3,"Row 2",NULL},
           {4,"Row 3",NULL},
          };

          const RowListTypeDef rowListView1[] = {  
           //{.enterViewIndex  |  .x  |  .text  |  .handler},
           {5,"Row 1-1",NULL}, 
           {VIEW_NONE,"Row 1-2",NULL},
           {VIEW_NONE,"Row 1-3",NULL},
           {VIEW_NONE,"Row 1-4",NULL},
           {VIEW_NONE,"Row 1-5",NULL},
           {VIEW_NONE,"Row 1-6",NULL},
           {VIEW_NONE,"Row 1-7",NULL},
           {VIEW_NONE,"Row 1-8",NULL},
           {VIEW_NONE,"Row 1-9",NULL},
          };

          const RowListTypeDef rowListView2[] = {  
           //{.enterViewIndex  |  .x  |  .text  |  .handler},
           {VIEW_NONE,"Row 2-1",NULL},
           {VIEW_NONE,"Row 2-2",NULL},
           {VIEW_NONE,"Row 2-3",NULL},
           {VIEW_NONE,"Row 2-4",NULL},
           {VIEW_NONE,"Row 2-5",NULL},
           {VIEW_NONE,"Row 2-6",NULL},
           {VIEW_NONE,"Row 2-7",NULL},
           {VIEW_NONE,"Row 2-8",NULL},
          };

          const RowListTypeDef rowListView3[] = {  
           //{.enterViewIndex  |  .x  |  .text  |  .handler},
           {VIEW_NONE,"Row 3-1",NULL},
           {VIEW_NONE,"Row 3-2",NULL},
           {VIEW_NONE,"Row 3-3",NULL},
           {VIEW_NONE,"Row 3-4",NULL},
           {VIEW_NONE,"Row 3-5",NULL},
           {VIEW_NONE,"Row 3-6",NULL},
           {VIEW_NONE,"Row 3-7",NULL},
           {VIEW_NONE,"Row 3-8",NULL},
           {VIEW_NONE,"Row 3-9",NULL},
           {VIEW_NONE,"Row 3-10",NULL},
           {VIEW_NONE,"Row 3-11",NULL},
           {VIEW_NONE,"Row 3-12",NULL},
           {VIEW_NONE,"Row 3-13",NULL},
           {VIEW_NONE,"Row 3-14",NULL},
           {VIEW_NONE,"Row 3-15",NULL},
          };

          const RowListTypeDef rowListView1_1[] = {  
           //{.enterViewIndex  |  .x  |  .text  |  .handler},
           {VIEW_NONE,"Row 1-1-1",NULL}, 
           {VIEW_NONE,"Row 1-1-2",NULL},
           {VIEW_NONE,"Row 1-1-3",NULL},
           {VIEW_NONE,"Row 1-1-4",NULL},
           {VIEW_NONE,"Row 1-1-5",NULL},
           {VIEW_NONE,"Row 1-1-6",NULL},
           {VIEW_NONE,"Row 1-1-7",NULL},
           {VIEW_NONE,"Row 1-1-8",NULL},
          };

          ViewListTypeDef menu[] = {
           //.currIndex | .parentViewIndex | .list | .lengthOfList | .display
           VIEW_MEMBER_FORMAT(rowListHome),
           VIEW_MEMBER_FORMAT(rowListSRoot),
           VIEW_MEMBER_FORMAT(rowListView1),
           VIEW_MEMBER_FORMAT(rowListView2),
           VIEW_MEMBER_FORMAT(rowListView3),
           VIEW_MEMBER_FORMAT(rowListView1_1),
          };

          程序格式

          程序需要定義一個(gè)全局變量游標(biāo)CursorTypeDef,如:

          CursorTypeDef cursor;

          然后在main函數(shù)中調(diào)用控件初始化程序View_Init

          View_Init(menu,&cursor);

          在程序主循環(huán)中每隔一段時(shí)間調(diào)用程序View_Loop.例如每隔100ms調(diào)用一次

          當(dāng)有按鍵按下時(shí),只需要根據(jù)按鍵的不同給cursor.keyval變量賦不同的值即可.例如:

          rotaryval = ReadRotaryEncoder();
          if(rotaryval == ROTARY_LEFT)
          {
              cursor.keyval = KEY_UP;
          }else if(rotaryval == ROTARY_RIGHT)
          {
              cursor.keyval = KEY_DOWN;
          }

          其中按鍵值有以下:

          #define KEY_NONE    0      //沒(méi)有按下按鍵
          #define KEY_ENTER   1      //按下<確定>鍵
          #define KEY_RETURN  2     //按下<返回>鍵(返回上一層)
          #define KEY_HOME    3      //按下<首頁(yè)>鍵
          #define KEY_DOWN    4      //按下<下>鍵
          #define KEY_UP      5      //按下<上>鍵
          #define KEY_ADD     6      //按下<加>鍵
          #define KEY_SUB     7      //按下<減>鍵

          代碼文件

          gitee:https://gitee.com/figght/zBitsView.git
          GitHub:https://github.com/figght/zBitsView.git

          來(lái)源整理于網(wǎng)絡(luò)素材,版權(quán)歸原作者所有,如有侵權(quán),請(qǐng)聯(lián)系刪除,謝謝。

          ????????????????  END  ????????????????

          關(guān)注我的微信公眾號(hào),回復(fù)“加群”按規(guī)則加入技術(shù)交流群。

          歡迎關(guān)注我的視頻號(hào):


          點(diǎn)擊“閱讀原文”查看更多分享,歡迎點(diǎn)分享、收藏、點(diǎn)贊、在看。

          瀏覽 71
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久91电影 | 欧美少妇一区二区 | 123操逼电影网 | 天天玩天天操天天插天天日天插射 | 91久久夜色精品国产九色 |