一个轻量级的开源嵌入式状态机框架

小麦大叔 2023-12-06 18:01

前言

Zorb Framework是一个基于面向对象的思想来搭建一个轻量级的嵌入式框架。

本次分享的是Zorb Framework的状态机的实现。中小型嵌入式程序说白了就是由各种状态机组成,因此掌握了如何构建状态机,开发嵌入式应用程序可以说是手到拈来。

简单的状态机可以用Switch-Case实现,但复杂一点的状态机再继续使用Switch-Case的话,层次会变得比较乱,不方便维护。

因此我们为Zorb Framework提供了函数式状态机

项目地址:https://github.com/54zorb/Zorb-Framework

状态机的功能

我们先来看看要实现的状态机提供什么功能:初步要提供的功能如下:

  1. 可以设置初始状态;
  2. 可以进行状态转换;
  3. 可以进行信号调度;
  4. 最好可以在进入和离开状态的时候可以做一些自定义的事情;
  5. 最好可以有子状态机;

数据结构

因此,初步设计的数据结构如下:

`/* 状态机结构 */  
struct _Fsm  
{
  
    uint8_t Level;                  /* 嵌套层数,根状态机层数为1,子状态机层数自增 */  
                                    /* 注:严禁递归嵌套和环形嵌套 */  
    List *ChildList;                /* 子状态机列表 */  
    Fsm *Owner;                     /* 父状态机 */  
    IFsmState OwnerTriggerState;    /* 当父状态机为设定状态时,才触发当前状态机 */  
                                    /* 若不设定,则当执行完父状态机,立即运行子状态机 */  
    IFsmState CurrentState;         /* 当前状态 */  
    bool IsRunning;                 /* 是否正在运行(默认关) */  
  
    /* 设置初始状态 */  
    void (*SetInitialState)(Fsm * const pFsm, IFsmState initialState);  
  
    /* 运行当前状态机 */  
    bool (*Run)(Fsm * const pFsm);  
  
    /* 运行当前状态机和子状态机 */  
    bool (*RunAll)(Fsm * const pFsm);  
  
    /* 停止当前状态机 */  
    bool (*Stop)(Fsm * const pFsm);  
  
    /* 停止当前状态机和子状态机 */  
    bool (*StopAll)(Fsm * const pFsm);  
  
    /* 释放当前状态机 */  
    bool (*Dispose)(Fsm * const pFsm);  
  
    /* 释放当前状态机和子状态机 */  
    bool (*DisposeAll)(Fsm * const pFsm);  
  
    /* 添加子状态机 */  
    bool (*AddChild)(Fsm * const pFsm, Fsm * const pChildFsm);  
  
    /* 移除子状态机(不释放空间) */  
    bool (*RemoveChild)(Fsm * const pFsm, Fsm * const pChildFsm);  
  
    /* 调度状态机 */  
    bool (*Dispatch)(Fsm * const pFsm, FsmSignal const signal);  
  
    /* 状态转移 */  
    void (*Transfer)(Fsm * const pFsm, IFsmState nextState);  
  
    /* 状态转移(触发转出和转入事件) */  
    void (*TransferWithEvent)(Fsm * const pFsm, IFsmState nextState);  
};  

关于信号,Zorb Framework做了以下定义:

/* 状态机信号0-31保留,用户信号在32以后定义 */  
enum {  
    FSM_NULL_SIG = 0,  
    FSM_ENTER_SIG,  
    FSM_EXIT_SIG,  
    FSM_USER_SIG_START = 32  
    /* 用户信号请在用户文件定义,不允许在此定义 */  
};  

创建状态机

实现代码如下:

bool Fsm_create(Fsm ** ppFsm)  
{  
    Fsm *pFsm;  
      
    ZF_ASSERT(ppFsm != (Fsm **)0)  
      
    /* 分配空间 */  
    pFsm = ZF_MALLOC(sizeof(Fsm));  
    if (pFsm == NULL)  
    {  
        ZF_DEBUG(LOG_E, "malloc fsm space error\r\n");  
        return false;  
    }  
      
    /* 初始化成员 */  
    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;  
      
    return true;  
}  

调度状态机

实现代码如下:

`/******************************************************************************  
 * 描述  :调度状态机  
 * 参数  :(in)-pFsm           状态机指针  
 *         (in)-signal         调度信号  
 * 返回  :-true               成功  
 *         -false              失败  
******************************************************************************/
  
bool Fsm_dispatch(Fsm * const pFsm, FsmSignal const signal)  
{  
    /* 返回结果 */  
    bool res = false;  
      
    ZF_ASSERT(pFsm != (Fsm *)0)  
      
    if (pFsm->IsRunning)  
    {  
        if (pFsm->ChildList != NULL && pFsm->ChildList->Count > 0)  
        {  
            uint32_t i;  
            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;  
            }  
        }  
    }  
      
    return res;  
}  

篇幅有限,其它接口实现可阅读:

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

状态机测试

/**  
  *****************************************************************************  
  * @file    app_fsm.c  
  * @author  Zorb  
  * @version V1.0.0  
  * @date    2018-06-28  
  * @brief   状态机测试的实现  
  *****************************************************************************  
  * @history  
  *  
  * 1. Date:2018-06-28  
  *    Author:Zorb  
  *    Modification:建立文件  
  *  
  *****************************************************************************  
  */
  
  
#include "app_fsm.h"  
#include "zf_includes.h"  
  
/* 定义用户信号 */  
enum Signal  
{  
    SAY_HELLO = FSM_USER_SIG_START  
};  
  
Fsm *pFsm;        /* 父状态机 */  
Fsm *pFsmSon;     /* 子状态机 */  
  
/* 父状态机状态1 */  
static void State1(Fsm * const pFsm, FsmSignal const fsmSignal);  
/* 父状态机状态2 */  
static void State2(Fsm * const pFsm, FsmSignal const fsmSignal);  
  
/******************************************************************************  
 * 描述  :父状态机状态1  
 * 参数  :-pFsm       当前状态机  
 *         -fsmSignal  当前调度信号  
 * 返回  :无  
******************************************************************************/
  
static void State1(Fsm * const pFsm, FsmSignal const fsmSignal)  
{  
    switch(fsmSignal)  
    {  
        case FSM_ENTER_SIG:  
            ZF_DEBUG(LOG_D, "enter state1\r\n");  
            break;  
  
        case FSM_EXIT_SIG:  
            ZF_DEBUG(LOG_D, "exit state1\r\n\r\n");  
            break;  
  
        case SAY_HELLO:  
            ZF_DEBUG(LOG_D, "state1 say hello, and want to be state2\r\n");  
            /* 切换到状态2 */  
            pFsm->TransferWithEvent(pFsm, State2);  
            break;  
    }  
}  
  
/******************************************************************************  
 * 描述  :父状态机状态2  
 * 参数  :-pFsm       当前状态机  
 *         -fsmSignal  当前调度信号  
 * 返回  :无  
******************************************************************************/
  
static void State2(Fsm * const pFsm, FsmSignal const fsmSignal)  
{  
    switch(fsmSignal)  
    {  
        case FSM_ENTER_SIG:  
            ZF_DEBUG(LOG_D, "enter state2\r\n");  
            break;  
  
        case FSM_EXIT_SIG:  
            ZF_DEBUG(LOG_D, "exit state2\r\n\r\n");  
            break;  
  
        case SAY_HELLO:  
            ZF_DEBUG(LOG_D, "state2 say hello, and want to be state1\r\n");  
            /* 切换到状态1 */  
            pFsm->TransferWithEvent(pFsm, State1);  
            break;  
    }  
}  
  
/******************************************************************************  
 * 描述  :子状态机状态  
 * 参数  :-pFsm       当前状态机  
 *         -fsmSignal  当前调度信号  
 * 返回  :无  
******************************************************************************/
  
static void SonState(Fsm * const pFsm, FsmSignal const fsmSignal)  
{  
    switch(fsmSignal)  
    {  
        case SAY_HELLO:  
            ZF_DEBUG(LOG_D, "son say hello only in state2\r\n");  
            break;  
    }  
}  
  
/******************************************************************************  
 * 描述  :任务初始化  
 * 参数  :无  
 * 返回  :无  
******************************************************************************/
  
void App_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);  
}  
  
/******************************************************************************  
 * 描述  :任务程序  
 * 参数  :无  
 * 返回  :无  
******************************************************************************/
  
void App_Fsm_process(void)  
{  
    ZF_DELAY_MS(1000);  
    /* 每1000ms调度状态机,发送SAY_HELLO信号 */  
    pFsm->Dispatch(pFsm, SAY_HELLO);  
}  
  
/******************************** END OF FILE ********************************/  

测试结果

测试结果

本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。

-END-



往期推荐:点击链接即可跳转阅读
实时和非实时操作系统有什么区别?
一招提高单片机代码质量!小改动,大收获
嵌入式开发的一个骚操作!你用过吗?
↓↓↓点击关注↓↓↓

小麦大叔 一位热衷技术的攻城狮,懂点技术,会讲故事,交个朋友?
评论 (0)
  • 一、智能语音播报技术演进与市场需求随着人工智能技术的快速发展,TTS(Text-to-Speech)技术在商业场景中的应用呈现爆发式增长。在零售领域,智能收款机的语音播报功能已成为提升服务效率和用户体验的关键模块。WT3000T8作为新一代高性能语音合成芯片,凭借其优异的处理能力和灵活的功能配置,正在为收款机智能化升级提供核心技术支持。二、WT3000T8芯片技术特性解析硬件架构优势采用32位高性能处理器(主频240MHz),支持实时语音合成与多任务处理QFN32封装(4x4mm)实现小型化设计
    广州唯创电子 2025-04-15 08:53 98浏览
  • 时源芯微 专业EMC解决方案提供商  为EMC创造可能(适用于高频时钟电路,提升EMC性能与信号稳定性)一、设计目标抑制电源噪声:阻断高频干扰(如DC-DC开关噪声)传入晶振电源。降低时钟抖动:确保晶振输出信号纯净,减少相位噪声。通过EMC测试:减少晶振谐波辐射(如30MHz~1GHz频段)。二、滤波电路架构典型拓扑:电源输入 → 磁珠(FB) → 大电容(C1) + 高频电容(C2) → 晶振VDD1. 磁珠(Ferrite Bead)选型阻抗特性:在目标频段(如100MHz~1GH
    时源芯微 2025-04-14 14:53 97浏览
  • 一、磁场发生设备‌电磁铁‌:由铁芯和线圈组成,通过调节电流大小可产生3T以下的磁场,广泛应用于工业及实验室场景(如电磁起重机)。‌亥姆霍兹线圈‌:由一对平行共轴线圈组成,可在线圈间产生均匀磁场(几高斯至几百高斯),适用于物理实验中的磁场效应研究。‌螺线管‌:通过螺旋线圈产生长圆柱形均匀磁场,电流与磁场呈线性关系,常用于磁性材料研究及电子束聚焦。‌超导磁体‌:采用超导材料线圈,在低温下可产生3-20T的强磁场,用于核磁共振研究等高精度科研领域。‌多极电磁铁‌:支持四极、六极、八极等多极磁场,适用于
    锦正茂科技 2025-04-14 13:29 74浏览
  • 你知道精益管理中的“看板”真正的意思吗?在很多人眼中,它不过是车间墙上的一块卡片、一张单子,甚至只是个用来控制物料的工具。但如果你读过大野耐一的《丰田生产方式》,你就会发现,看板的意义远不止于此。它其实是丰田精益思想的核心之一,是让工厂动起来的“神经系统”。这篇文章,我们就带你一起从这本书出发,重新认识“看板”的深层含义。一、使“看板”和台车结合使用  所谓“看板”就是指纸卡片。“看板”的重要作用之一,就是连接生产现场上道工序和下道工序的信息工具。  “看板”是“准时化”生产的重要手段,它总是要
    优思学院 2025-04-14 15:02 118浏览
  • 四、芯片封测技术及应用场景1、封装技术的发展历程 (1)DIP封装:早期分立元件封装,体积大、引脚少; (2)QFP封装:引脚密度提升,适用于早期集成电路。 (3)BGA封装:高密度互连,散热与信号传输优化; (4)3D封装:通过TSV(硅通孔)实现垂直堆叠,提升集成度(如HBM内存堆叠); (5)Chiplet封装:异质集成,将不同工艺节点的模块组合(如AMD的Zen3+架构)。 (6)SiP封装:集成多种功能芯片(如iPhone的A系列SoC整合CPU、GPU、射频模块)。2、芯片测试 (1
    碧海长空 2025-04-15 11:45 185浏览
  • 在当今汽车电子化和智能化快速发展的时代,车规级电子元器件的质量直接关系到汽车安全性能。三星作为全球领先的电子元器件制造商,其车规电容备受青睐。然而,选择一个靠谱的三星车规电容代理商至关重要。本文以行业领军企业北京贞光科技有限公司为例,深入剖析如何选择优质代理商。选择靠谱代理商的关键标准1. 授权资质与行业地位选择三星车规电容代理商首先要验证其授权资质及行业地位。北京贞光科技作为中国电子元器件行业的领军者,长期走在行业前沿,拥有完备的授权资质。公司专注于市场分销和整体布局,在电子元器件领域建立了卓
    贞光科技 2025-04-14 16:18 147浏览
  • 三、芯片的制造1、制造核心流程 (1)晶圆制备:以高纯度硅为基底,通过拉晶、切片、抛光制成晶圆。 (2)光刻:光刻、离子注入、薄膜沉积、化学机械抛光。 (3)刻蚀与沉积:使用干法刻蚀(等离子体)精准切割图形,避免侧壁损伤。 (4)掺杂:注入离子形成PN结特性,实现晶体管开关功能。2、材料与工艺创新 (1)新材料应用: 高迁移率材料(FinFET中的应变硅、GaN在射频芯片中的应用); 新型封装技术(3D IC、TSV硅通孔)提升集成度。 (2)工艺创新: 制程从7nm到3nm,设计架构由F
    碧海长空 2025-04-15 11:33 190浏览
  • 一、智能门锁市场痛点与技术革新随着智能家居的快速发展,电子门锁正从“密码解锁”向“无感交互”进化。然而,传统人体感应技术普遍面临三大挑战:功耗高导致续航短、静态人体检测能力弱、环境适应性差。WTL580微波雷达解决方案,以5.8GHz高精度雷达感知技术为核心,突破行业瓶颈,为智能门锁带来“精准感知-高效触发-超低功耗”的全新交互范式。二、WTL580方案核心技术优势1. 5.8GHz毫米波雷达:精准感知的革命全状态人体检测:支持运动、微动(如呼吸)、静态(坐卧)多模态感知,检测灵敏度达0.1m/
    广州唯创电子 2025-04-15 09:20 84浏览
  • 展会名称:2025成都国际工业博览会(简称:成都工博会)展会日期:4月23 -25日展会地址:西部国际博览城展位号:15H-E010科士威传动将展示智能制造较新技术及全套解决方案。 2025年4月23-25日,中国西部国际博览城将迎来一场工业领域的年度盛会——2025成都国际工业博览会。这场以“创链新工业,共碳新未来”为主题的展会上,来自全球的600+ 家参展企业将齐聚一堂,共同展示智能制造产业链中的关键产品及解决方案,助力制造业向数字化、网络化、智能化转型。科士威传动将受邀参展。&n
    科士威传动 2025-04-14 17:55 87浏览
  •   无人装备作战协同仿真系统软件:科技的关键支撑   无人装备作战协同仿真系统软件,作为一款综合性仿真平台,主要用于模拟无人机、无人车、无人艇等无人装备在复杂作战环境中的协同作战能力、任务规划、指挥控制以及性能评估。该系统通过搭建虚拟战场环境,支持多种无人装备协同作战仿真,为作战指挥、装备研发、战术训练和作战效能评估,提供科学依据。   应用案例   系统软件供应可以来这里,这个首肌开始是幺伍扒,中间是幺幺叁叁,最后一个是泗柒泗泗,按照数字顺序组合就可以找到。   核心功能   虚拟战
    华盛恒辉l58ll334744 2025-04-14 17:24 89浏览
  • 一、芯片的发展历程总结:1、晶体管的诞生(1)电子管时代 20世纪40年代,电子管体积庞大、功耗高、可靠性差,无法满足计算机小型化需求。(2)晶体管时代 1947年,贝尔实验室的肖克利、巴丁和布拉顿发明点接触晶体管,实现电子信号放大与开关功能,标志着固态电子时代的开端。 1956年,肖克利发明晶体管。(3)硅基晶体管时代 早期晶体管采用锗材料,但硅更耐高温、成本低,成为主流材料。2、集成电路的诞生与发展 1958年,德州仪器工程师基尔比用锗材料制成世界上第一块含多个晶体管的集成电路,同年仙童半导
    碧海长空 2025-04-15 09:30 113浏览
  • 二、芯片的设计1、芯片设计的基本流程 (1)需求定义: 明确芯片功能(如处理器、存储、通信)、性能指标(速度、功耗、面积)及目标应用场景(消费电子、汽车、工业)。 (2)架构设计: 确定芯片整体框架,包括核心模块(如CPU、GPU、存储单元)的协同方式和数据流路径。 (3)逻辑设计: 通过硬件描述语言(如Verilog、VHDL)将架构转化为电路逻辑,生成RTL(寄存器传输级)代码。 (4)物理设计: 将逻辑代码映射到物理布局,涉及布局布线、时序优化、功耗分析等,需借助EDA工具(如Ca
    碧海长空 2025-04-15 11:30 153浏览
  •   高空 SAR 目标智能成像系统软件:多领域应用的前沿利器   高空 SAR(合成孔径雷达)目标智能成像系统软件,专门针对卫星、无人机等高空平台搭载的 SAR传感器数据,融合人工智能与图像处理技术,打造出的高效目标检测、识别及成像系统。此软件借助智能算法,显著提升 SAR图像分辨率、目标特征提取能力以及实时处理效率,为军事侦察、灾害监测、资源勘探等领域,提供关键技术支撑。   应用案例系统软件供应可以来这里,这个首肌开始是幺伍扒,中间是幺幺叁叁,最后一个是泗柒泗泗,按照数字顺序组合
    华盛恒辉l58ll334744 2025-04-14 16:09 149浏览
我要评论
0
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦