在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            博客專欄

            EEPW首頁 > 博客 > 教你一招搞定,單片機(jī)開發(fā)常用的狀態(tài)機(jī)

            教你一招搞定,單片機(jī)開發(fā)常用的狀態(tài)機(jī)

            發(fā)布人:xiaomaidashu 時(shí)間:2022-06-22 來源:工程師 發(fā)布文章
            之前寫過一篇狀態(tài)機(jī)的實(shí)用文章,很多朋友說有幾個(gè)地方有點(diǎn)難度不易理解,今天給大家換種簡(jiǎn)單寫法,使用函數(shù)指針的方法實(shí)現(xiàn)狀態(tài)機(jī)。

            狀態(tài)機(jī)簡(jiǎn)介

            有限狀態(tài)機(jī)FSM是有限個(gè)狀態(tài)及在這些狀態(tài)之間的轉(zhuǎn)移和動(dòng)作等行為的數(shù)學(xué)模型,是一種邏輯單元內(nèi)部的高效編程方法,可以根據(jù)不同狀態(tài)或者消息類型進(jìn)行相應(yīng)的處理邏輯,使得程序邏輯清晰易懂。

            函數(shù)指針實(shí)現(xiàn)FSM

            使用函數(shù)指針實(shí)現(xiàn)FSM可以分為3個(gè)步驟

            1. 建立相應(yīng)的狀態(tài)表和動(dòng)作查詢表

            2. 根據(jù)狀態(tài)表、事件、動(dòng)作表定位相應(yīng)的動(dòng)作處理函數(shù)

            3. 執(zhí)行完成后再進(jìn)行狀態(tài)的切換

            代碼實(shí)現(xiàn)步驟
            1. 定義狀態(tài)數(shù)據(jù)的枚舉類型
            typedef enum {
              state_1=1,
              state_2,
              state_3,
              state_4
            }State;
            1. 定義事件的枚舉類型
            typedef enum{
              event_1=1,
              event_2,
              event_3,
              event_4,
              event_5
            }EventID;
            1. 定義狀態(tài)表的數(shù)據(jù)類型
            typedef struct
            {
                int event;   //事件
                int CurState;  //當(dāng)前狀態(tài)
                void (*eventActFun)();  //函數(shù)指針
                int NextState;  //下一個(gè)狀態(tài)
            }StateTable;
            1. 定義處理函數(shù)及建立狀態(tài)表
            void f121()
            {
                printf("this is f121n");
            }
            void f221()
            {
                printf("this is f221n");
            }
            void f321()
            {
                printf("this is f321n");
            }
            
            void f122()
            {
                printf("this is f122n");
            }
            
            StateTable fTable[] =
            {
                //{到來的事件,當(dāng)前的狀態(tài),將要要執(zhí)行的函數(shù),下一個(gè)狀態(tài)}
                { event_1,  state_1,    f121,  event_2 },
                { event_2,  state_2,    f221,  event_3 },
                { event_3,  state_3,    f321,  event_4 },
                { event_4,  state_4,    f122,  event_1 },
                //add your code here
            };
            1. 狀態(tài)機(jī)類型,及狀態(tài)機(jī)接口函數(shù)
            /*狀態(tài)機(jī)類型*/
            typedef struct {
                int curState;//當(dāng)前狀態(tài)
                StateTable * stateTable;//狀態(tài)表
                int size;//表的項(xiàng)數(shù)
            }fsmType;
            
            /*狀態(tài)機(jī)注冊(cè),給它一個(gè)狀態(tài)表*/
            void fsmRegist(fsmType* pFsm, StateTable* pTable)
            {
                pFsm->stateTable = pTable;
            }
            
            /*狀態(tài)遷移*/
            void fsmStateTransfer(fsmType* pFsm, int state)
            {
                pFsm->curState = state;
            }
            
            /*事件處理*/
            void fsmEventHandle(fsmType* pFsm, int event)
            {
                StateTable* pActTable = pFsm->stateTable;
                void (*eventActFun)() = NULL;  //函數(shù)指針初始化為空
                int NextState;
                int CurState = pFsm->curState;
                int maxNum = pFsm->size;
                int flag = 0; //標(biāo)識(shí)是否滿足條件
            
                /*獲取當(dāng)前動(dòng)作函數(shù)*/
                for (int i = 0; i<maxNum; i++)
                {
                    //當(dāng)且僅當(dāng)當(dāng)前狀態(tài)下來個(gè)指定的事件,我才執(zhí)行它
                    if (event == pActTable[i].event && CurState == pActTable[i].CurState)
                    {
                        flag = 1;
                        eventActFun = pActTable[i].eventActFun;
                        NextState = pActTable[i].NextState;
                        break;
                    }
                }
            
                if (flag) //如果滿足條件了
                {
                    /*動(dòng)作執(zhí)行*/
                    if (eventActFun)
                    {
                        eventActFun();
                    }
            
                    //跳轉(zhuǎn)到下一個(gè)狀態(tài)
                    fsmStateTransfer(pFsm, NextState);
                }
                else
                {
                    printf("there is no matchn");
                }
            }
            附代碼

            代碼直接復(fù)制過去就行啦,本想打包的,太麻煩了。

            測(cè)試程序
            //編譯器:http://www.dooccn.com/cpp/
            //來源:技術(shù)讓夢(mèng)想更偉大
            //作者:李肖遙
            #include <stdio.h>
            
            typedef enum {
              state_1=1,
              state_2,
              state_3,
              state_4
            }State;
            
            typedef enum{
              event_1=1,
              event_2,
              event_3,
              event_4,
              event_5
            }EventID;
            
            typedef struct {
                int event;   //事件
                int CurState;  //當(dāng)前狀態(tài)
                void (*eventActFun)();  //函數(shù)指針
                int NextState;  //下一個(gè)狀態(tài)
            }StateTable;
            
            void f121()
            {
                printf("this is f121n");
            }
            void f221()
            {
                printf("this is f221n");
            }
            void f321()
            {
                printf("this is f321n");
            }
            
            void f122()
            {
                printf("this is f122n");
            }
            
            StateTable fTable[] =
            {
                //{到來的事件,當(dāng)前的狀態(tài),將要要執(zhí)行的函數(shù),下一個(gè)狀態(tài)}
                { event_1,  state_1,    f121,  event_2 },
                { event_2,  state_2,    f221,  event_3 },
                { event_3,  state_3,    f321,  event_4 },
                { event_4,  state_4,    f122,  event_1 },
                //add your code here
            };
            
            /*狀態(tài)機(jī)類型*/
            typedef struct {
                int curState;//當(dāng)前狀態(tài)
                StateTable * stateTable;//狀態(tài)表
                int size;//表的項(xiàng)數(shù)
            }fsmType;
            
            /*狀態(tài)機(jī)注冊(cè),給它一個(gè)狀態(tài)表*/
            void fsmRegist(fsmType* pFsm, StateTable* pTable)
            {
                pFsm->stateTable = pTable;
            }
            
            /*狀態(tài)遷移*/
            void fsmStateTransfer(fsmType* pFsm, int state)
            {
                pFsm->curState = state;
            }
            
            /*事件處理*/
            void fsmEventHandle(fsmType* pFsm, int event)
            {
                StateTable* pActTable = pFsm->stateTable;
                void (*eventActFun)() = NULL;  //函數(shù)指針初始化為空
                int NextState;
                int CurState = pFsm->curState;
                int maxNum = pFsm->size;
                int flag = 0; //標(biāo)識(shí)是否滿足條件
            
                /*獲取當(dāng)前動(dòng)作函數(shù)*/
                for (int i = 0; i<maxNum; i++)
                {
                    //當(dāng)且僅當(dāng)當(dāng)前狀態(tài)下來個(gè)指定的事件,我才執(zhí)行它
                    if (event == pActTable[i].event && CurState == pActTable[i].CurState)
                    {
                        flag = 1;
                        eventActFun = pActTable[i].eventActFun;
                        NextState = pActTable[i].NextState;
                        break;
                    }
                }
            
                if (flag) //如果滿足條件了
                {
                    /*動(dòng)作執(zhí)行*/
                    if (eventActFun)
                    {
                        eventActFun();
                    }
            
                    //跳轉(zhuǎn)到下一個(gè)狀態(tài)
                    fsmStateTransfer(pFsm, NextState);
                }
                else
                {
                    printf("there is no matchn");
                }
            }
            
            int main()
            {
                fsmType pType;
                fsmRegist(&pType,fTable);
                pType.curState = state_1;
                pType.size = sizeof(fTable)/sizeof(StateTable);
            
                printf("init state:%dnn",pType.curState);
            
                fsmEventHandle(&pType,event_1);
                printf("state:%dnn",pType.curState);
            
                fsmEventHandle(&pType,event_2);
                printf("state:%dnn",pType.curState);
            
                fsmEventHandle(&pType,event_3);
                printf("state:%dnn",pType.curState);
            
                fsmEventHandle(&pType,event_4);
                printf("state:%dnn",pType.curState);
            
                fsmEventHandle(&pType,event_2);
                printf("state:%dnn",pType.curState);
            
                return 0;
            }
            編譯結(jié)果

            圖片

            總結(jié)

            使用函數(shù)指針實(shí)現(xiàn)的FSM的過程還是比較費(fèi)時(shí)費(fèi)力的,但是這一切相對(duì)一大堆的if/else、switch/case來說都是值得的,當(dāng)你的程序規(guī)模變得越來越大的時(shí)候,基于這種表結(jié)構(gòu)的狀態(tài)機(jī),維護(hù)程序起來會(huì)清晰很多。



            *博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。



            關(guān)鍵詞: 單片機(jī)

            相關(guān)推薦

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

            關(guān)閉