<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

嵌入式框架Zorb Framework狀態機的實現

玩轉嵌入式 ? 來源:github.com ? 2023-11-29 09:33 ? 次閱讀

Zorb Framework是一個基于面向對象的思想來搭建一個輕量級的嵌入式框架。

本次分享的是Zorb Framework的狀態機的實現。

中小型嵌入式程序說白了就是由各種狀態機組成,因此掌握了如何構建狀態機,開發嵌入式應用程序可以說是手到拈來。

簡單的狀態機可以用Switch-Case實現,但復雜一點的狀態機再繼續使用Switch-Case的話,層次會變得比較亂,不方便維護。因此我們為Zorb Framework提供了函數式狀態機。

狀態機的功能

我們先來看看要實現的狀態機提供什么功能:

初步要提供的功能如下:

1、可以設置初始狀態

2、可以進行狀態轉換

3、可以進行信號調度

4、最好可以在進入和離開狀態的時候可以做一些自定義的事情

5、最好可以有子狀態機

因此,初步設計的數據結構如下:

/*狀態機結構*/
struct_Fsm
{
uint8_tLevel;/*嵌套層數,根狀態機層數為1,子狀態機層數自增*/
/*注:嚴禁遞歸嵌套和環形嵌套*/
List*ChildList;/*子狀態機列表*/
Fsm*Owner;/*父狀態機*/
IFsmStateOwnerTriggerState;/*當父狀態機為設定狀態時,才觸發當前狀態機*/
/*若不設定,則當執行完父狀態機,立即運行子狀態機*/
IFsmStateCurrentState;/*當前狀態*/
boolIsRunning;/*是否正在運行(默認關)*/

/*設置初始狀態*/
void(*SetInitialState)(Fsm*constpFsm,IFsmStateinitialState);

/*運行當前狀態機*/
bool(*Run)(Fsm*constpFsm);

/*運行當前狀態機和子狀態機*/
bool(*RunAll)(Fsm*constpFsm);

/*停止當前狀態機*/
bool(*Stop)(Fsm*constpFsm);

/*停止當前狀態機和子狀態機*/
bool(*StopAll)(Fsm*constpFsm);

/*釋放當前狀態機*/
bool(*Dispose)(Fsm*constpFsm);

/*釋放當前狀態機和子狀態機*/
bool(*DisposeAll)(Fsm*constpFsm);

/*添加子狀態機*/
bool(*AddChild)(Fsm*constpFsm,Fsm*constpChildFsm);

/*移除子狀態機(不釋放空間)*/
bool(*RemoveChild)(Fsm*constpFsm,Fsm*constpChildFsm);

/*調度狀態機*/
bool(*Dispatch)(Fsm*constpFsm,FsmSignalconstsignal);

/*狀態轉移*/
void(*Transfer)(Fsm*constpFsm,IFsmStatenextState);

/*狀態轉移(觸發轉出和轉入事件)*/
void(*TransferWithEvent)(Fsm*constpFsm,IFsmStatenextState);
};

關于信號,Zorb Framework做了以下定義:

/*狀態機信號0-31保留,用戶信號在32以后定義*/
enum{
FSM_NULL_SIG=0,
FSM_ENTER_SIG,
FSM_EXIT_SIG,
FSM_USER_SIG_START=32
/*用戶信號請在用戶文件定義,不允許在此定義*/
};

創建狀態機:

boolFsm_create(Fsm**ppFsm)
{
Fsm*pFsm;

ZF_ASSERT(ppFsm!=(Fsm**)0)

/*分配空間*/
pFsm=ZF_MALLOC(sizeof(Fsm));
if(pFsm==NULL)
{
ZF_DEBUG(LOG_E,"mallocfsmspaceerror
");
returnfalse;
}

/*初始化成員*/
pFsm->Level=1;
pFsm->ChildList=NULL;
pFsm->Owner=NULL;
pFsm->OwnerTriggerState=NULL;
pFsm->CurrentState=NULL;
pFsm->IsRunning=false;

/*初始化方法*/
pFsm->SetInitialState=Fsm_setInitialState;
pFsm->Run=Fsm_run;
pFsm->RunAll=Fsm_runAll;
pFsm->Stop=Fsm_stop;
pFsm->StopAll=Fsm_stopAll;
pFsm->Dispose=Fsm_dispose;
pFsm->DisposeAll=Fsm_disposeAll;
pFsm->AddChild=Fsm_addChild;
pFsm->RemoveChild=Fsm_removeChild;
pFsm->Dispatch=Fsm_dispatch;
pFsm->Transfer=Fsm_transfer;
pFsm->TransferWithEvent=Fsm_transferWithEvent;

/*輸出*/
*ppFsm=pFsm;

returntrue;
}

調度狀態機:

/******************************************************************************
*描述:調度狀態機
*參數:(in)-pFsm 狀態機指針
*(in)-signal調度信號
*返回:-true 成功
*-false失敗
******************************************************************************/
boolFsm_dispatch(Fsm*constpFsm,FsmSignalconstsignal)
{
/*返回結果*/
boolres=false;

ZF_ASSERT(pFsm!=(Fsm*)0)

if(pFsm->IsRunning)
{
if(pFsm->ChildList!=NULL&&pFsm->ChildList->Count>0)
{
uint32_ti;
Fsm*pChildFsm;

for(i=0;iChildList->Count;i++)
{
pChildFsm=(Fsm*)pFsm->ChildList
->GetElementDataAt(pFsm->ChildList,i);

if(pChildFsm!=NULL)
{
Fsm_dispatch(pChildFsm,signal);
}
}
}

if(pFsm->CurrentState!=NULL)
{
/*1:根狀態機時調度
2:沒設置觸發狀態時調度
3:正在觸發狀態時調度
*/
if(pFsm->Owner==NULL||pFsm->OwnerTriggerState==NULL
||pFsm->OwnerTriggerState==pFsm->Owner->CurrentState)
{
pFsm->CurrentState(pFsm,signal);

res=true;
}
}
}

returnres;
}

篇幅有限,其它接口實現可閱讀:

https://github.com/54zorb/Zorb-Framework

狀態機測試

/**
*****************************************************************************
*@fileapp_fsm.c
*@authorZorb
*@versionV1.0.0
*@date2018-06-28
*@brief狀態機測試的實現
*****************************************************************************
*@history
*
*1.Date:2018-06-28
*Author:Zorb
*Modification:建立文件
*
*****************************************************************************
*/

#include"app_fsm.h"
#include"zf_includes.h"

/*定義用戶信號*/
enumSignal
{
SAY_HELLO=FSM_USER_SIG_START
};

Fsm*pFsm;/*父狀態機*/
Fsm*pFsmSon;/*子狀態機*/

/*父狀態機狀態1*/
staticvoidState1(Fsm*constpFsm,FsmSignalconstfsmSignal);
/*父狀態機狀態2*/
staticvoidState2(Fsm*constpFsm,FsmSignalconstfsmSignal);

/******************************************************************************
*描述:父狀態機狀態1
*參數:-pFsm 當前狀態機
*-fsmSignal當前調度信號
*返回:無
******************************************************************************/
staticvoidState1(Fsm*constpFsm,FsmSignalconstfsmSignal)
{
switch(fsmSignal)
{
caseFSM_ENTER_SIG:
ZF_DEBUG(LOG_D,"enterstate1
");
break;

caseFSM_EXIT_SIG:
ZF_DEBUG(LOG_D,"exitstate1

");
break;

caseSAY_HELLO:
ZF_DEBUG(LOG_D,"state1sayhello,andwanttobestate2
");
/*切換到狀態2*/
pFsm->TransferWithEvent(pFsm,State2);
break;
}
}

/******************************************************************************
*描述:父狀態機狀態2
*參數:-pFsm 當前狀態機
*-fsmSignal當前調度信號
*返回:無
******************************************************************************/
staticvoidState2(Fsm*constpFsm,FsmSignalconstfsmSignal)
{
switch(fsmSignal)
{
caseFSM_ENTER_SIG:
ZF_DEBUG(LOG_D,"enterstate2
");
break;

caseFSM_EXIT_SIG:
ZF_DEBUG(LOG_D,"exitstate2

");
break;

caseSAY_HELLO:
ZF_DEBUG(LOG_D,"state2sayhello,andwanttobestate1
");
/*切換到狀態1*/
pFsm->TransferWithEvent(pFsm,State1);
break;
}
}

/******************************************************************************
*描述:子狀態機狀態
*參數:-pFsm 當前狀態機
*-fsmSignal當前調度信號
*返回:無
******************************************************************************/
staticvoidSonState(Fsm*constpFsm,FsmSignalconstfsmSignal)
{
switch(fsmSignal)
{
caseSAY_HELLO:
ZF_DEBUG(LOG_D,"sonsayhelloonlyinstate2
");
break;
}
}

/******************************************************************************
*描述:任務初始化
*參數:無
*返回:無
******************************************************************************/
voidApp_Fsm_init(void)
{
/*創建父狀態機,并設初始狀態*/
Fsm_create(&pFsm);
pFsm->SetInitialState(pFsm,State1);

/*創建子狀態機,并設初始狀態*/
Fsm_create(&pFsmSon);
pFsmSon->SetInitialState(pFsmSon,SonState);

/*設置子狀態機僅在父狀態State2觸發*/
pFsmSon->OwnerTriggerState=State2;

/*把子狀態機添加到父狀態機*/
pFsm->AddChild(pFsm,pFsmSon);

/*運行狀態機*/
pFsm->RunAll(pFsm);
}

/******************************************************************************
*描述:任務程序
*參數:無
*返回:無
******************************************************************************/
voidApp_Fsm_process(void)
{
ZF_DELAY_MS(1000);
/*每1000ms調度狀態機,發送SAY_HELLO信號*/
pFsm->Dispatch(pFsm,SAY_HELLO);
}

/********************************ENDOFFILE********************************/

結果:

6f904bd2-8e45-11ee-939d-92fbcf53809c.png

審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 單片機
    +關注

    關注

    6001

    文章

    43973

    瀏覽量

    620831
  • 嵌入式
    +關注

    關注

    4982

    文章

    18281

    瀏覽量

    288432
  • Switch
    +關注

    關注

    1

    文章

    514

    瀏覽量

    57539
  • 狀態機
    +關注

    關注

    2

    文章

    486

    瀏覽量

    27165

原文標題:單片機最好用的程序框架,莫過于狀態機了

文章出處:【微信號:玩轉嵌入式,微信公眾號:玩轉嵌入式】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    嵌入式狀態機的幾種大牛才懂的操作

    狀態機嵌入式軟件中隨處可見,可能你會說狀態機有什么難的,不就是 switch 嗎? switch僅僅是最基礎的一個點,關于狀態機的更多操作,或許你都沒有見過,下面分享幾種
    發表于 11-17 10:41 ?1123次閱讀
    <b class='flag-5'>嵌入式</b><b class='flag-5'>狀態機</b>的幾種大牛才懂的操作

    嵌入式軟件開發中常用的狀態機編程實現

    嵌入式軟件開發中,狀態機編程是一個十分重要的編程思想,它也是嵌入式開發中一個常用的編程框架。掌握了狀態機編程思想,可以更加邏輯清晰的
    發表于 09-06 10:25 ?1408次閱讀

    嵌入式框架Zorb Framework搭建方案

    Zorb Framework是一個基于面向對象的思想來搭建一個輕量級的嵌入式框架。
    的頭像 發表于 11-05 17:08 ?1024次閱讀
    <b class='flag-5'>嵌入式</b><b class='flag-5'>框架</b><b class='flag-5'>Zorb</b> <b class='flag-5'>Framework</b>搭建方案

    基于狀態機嵌入式系統開發

    給大家分享下,基于狀態機嵌入式系統開發,慢慢看吧
    發表于 12-22 19:44

    嵌入式狀態機編程的概念是什么

    干貨 | 嵌入式狀態機編程干貨篇文章描述了基本的狀態機編程概念,感覺還可以。如果在搭上事件驅動框架,就可以寫一個簡單的RTOS了,這個OS可以作為一種不可剝奪型內核。...
    發表于 12-22 06:25

    LSM6DSOX嵌入式有限狀態機的使用和配置的信息

    本文檔旨在提供有關 ST 的 LSM6DSOX 嵌入式有限狀態機的使用和配置的信息。LSM6DSOX 可配置為由用戶定義的運動模式激活中斷信號生成。為此,最多可以為運動檢測獨立編程 16 組嵌入式有限
    發表于 09-06 06:36

    ISM330DHCX嵌入式有限狀態機的使用和配置信息

    本文檔旨在提供有關 ST 的 ISM330DHCX嵌入式有限狀態機的使用和配置的信息。ISM330DHCX 可配置為由用戶定義的運動模式激活中斷信號生成。為此,最多可以為運動檢測獨立編程 16 組嵌入式有限
    發表于 09-08 08:00

    LSM6DSOX嵌入式有限狀態機的使用和配置的信息

    本文檔旨在提供有關 ST 的 LSM6DSOX 嵌入式有限狀態機的使用和配置的信息。LSM6DSOX 可配置為由用戶定義的運動模式激活中斷信號生成。為此,最多可以為運動檢測獨立編程 16 組嵌入式有限
    發表于 09-13 07:33

    嵌入式軟件中狀態機的抽象與實現

    文中提出了 在嵌入式軟件中把狀態機作為一個獨立模塊從控制模塊中抽象出來的思想 , 描述了 抽象出來的狀態機模塊 。 并介紹了 如何將這種狀態機抽象模塊應用到實際項目中 。
    發表于 03-22 15:47 ?1次下載

    有限狀態機嵌入式系統中的實現及應用

    如何使嵌入式軟件代碼更加可靠 增強程序的可維護性 一直以來都是嵌入式程序員追 求的目標。論述了有限狀態機的原理和其實現方法;采用狀態機方法編
    發表于 03-22 15:40 ?1次下載

    有限狀態機嵌入式軟件中的應用

    有限狀態機嵌入式軟件中的應用,感興趣的小伙伴們可以看看。
    發表于 07-26 10:43 ?27次下載

    嵌入式應用框架EAF詳解

    EAF是Embedded Application Framework 的縮寫,即嵌入式應用框架。嵌入式應用框架是 Application
    發表于 12-02 11:30 ?2512次閱讀

    關于嵌入式應用框架(EAF)的分析

    EAF是Embedded Application Framework 的縮寫,即嵌入式應用框架。嵌入式應用框架是 Application
    發表于 01-01 09:50 ?1171次閱讀

    嵌入式狀態機的設置

    狀態機嵌入式軟件中隨處可見,可能你會說狀態機有什么難的,不就是 switch 嗎?
    的頭像 發表于 11-02 09:04 ?852次閱讀

    嵌入式狀態機的設計與實現

    嵌入式狀態機是一種常用的軟件設計模式,它能夠提高代碼的可讀性和可維護性。狀態機是一個抽象的概念,它描述了一個系統或者組件的不同狀態以及在不同狀態
    的頭像 發表于 04-14 11:55 ?1124次閱讀
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>