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;i< pFsm->ChildList->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

    浏览量

    620845
  • 嵌入式
    +关注

    关注

    4982

    文章

    18281

    浏览量

    288464
  • Switch
    +关注

    关注

    1

    文章

    514

    浏览量

    57540
  • 状态机
    +关注

    关注

    2

    文章

    486

    浏览量

    27168

原文标题:单片机最好用的程序框架,莫过于状态机了

文章出处:【微信号:玩转嵌入式,微信公众号:玩转嵌入式】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    嵌入式状态机的几种大牛才懂的操作

    状态机嵌入式软件中随处可见,可能你会说状态机有什么难的,不就是 switch 吗? switch仅仅是最基础的一个点,关于状态机的更多操作,或许你都没有见过,下面分享几种
    发表于 11-17 10:41 1124次阅读
    <b class='flag-5'>嵌入式</b><b class='flag-5'>状态机</b>的几种大牛才懂的操作

    嵌入式软件开发中常用的状态机编程实现

    嵌入式软件开发中,状态机编程是一个十分重要的编程思想,它也是嵌入式开发中一个常用的编程框架。掌握了状态机编程思想,可以更加逻辑清晰的
    发表于 09-06 10:25 1408次阅读

    嵌入式框架Zorb Framework搭建方案

    Zorb Framework是一个基于面向对象的思想来搭建一个轻量级的嵌入式框架
    的头像 发表于 11-05 17:08 1026次阅读
    <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 2513次阅读

    关于嵌入式应用框架(EAF)的分析

    EAF是Embedded Application Framework 的缩写,即嵌入式应用框架嵌入式应用框架是 Application
    发表于 01-01 09:50 1171次阅读

    嵌入式状态机的设置

    状态机嵌入式软件中随处可见,可能你会说状态机有什么难的,不就是 switch 吗?
    的头像 发表于 11-02 09:04 852次阅读

    嵌入式状态机的设计与实现

    嵌入式状态机是一种常用的软件设计模式,它能够提高代码的可读性和可维护性。状态机是一个抽象的概念,它描述了一个系统或者组件的不同状态以及在不同状态
    的头像 发表于 04-14 11:55 1125次阅读