嵌入式有限状态机软件设计及应用

一、状态机介绍

状态机,也称为有限状态机(Finite State Machine,FSM),是一种数学模型,用于描述系统的行为模式和状态转移关系。状态机常用概念介绍:

  1. 状态:状态机的组成部分,一个状态机由多个状态组成,假设洗衣机洗衣服的过程用状态机表示,这个状态机则包含:放水、浸洗、漂洗、脱水等多个状态。
  2. 起点:状态机从这里开始启动,是一个伪状态,指向的状态是当前状态机的第一个状态
  3. 终点:状态机从这里结束,也是一个伪状态
  4. 转换活动:从一个状态转换到另一个状态的动作,通常流程为:
    • 转换条件触发转换状态的退出动作转换过程中的动作被转换状态的入口动作
  1. 入口动作:一个状态刚进来时需要做的事,在洗衣服的状态机中的放水状态的入口动作是,打开水龙头。
  2. 出口动作:一个状态退出时需要做的事,放水状态的出口动作是关闭水龙头
  3. 保持动作:状态需要保持做的事情,比如放水状态需要保持放水,并且一直判断水位

二、项目背景

公司最近有个简单的项目,但是由于没有专业的产品经理,给到软件这边的产品需求实在是一言难尽。经过多次反复与领导的沟通,才大概明白一些需求是干什么的,理解了需求后使用状态机做软件设计。

看下软件拿到的需求😵

三、最终效果

3.1 状态机实现:

typedef struct FsmType_t FsmType;
typedef struct FsmNode_t
{
    // 进入处理
    void (*entry_func)(FsmType *);
    // 轮询处理
    void (*do_func)(FsmType *);
    // 退出处理
    void (*exit_func)(FsmType *);
}FsmNode;
typedef struct FsmType_t
{
    // 当前活动节点
    uint8_t state;
    // 节点列表
    const FsmNode** nodeTable;
}FsmType;
/**
 * @brief 状态机初始化
 * @param fsm 状态机对象
 * @param nodeTable 状态表
 * @param param 状态参数
*/
void fsm_init(FsmType* fsm,uint8_t state,FsmNode** nodeTable);
/**
 * @brief 状态转换
 * @param fsm 状态机对象
 * @param state 目标状态
*/
void fsm_trans(FsmType* fsm,uint8_t state);
/**
 * @brief 状态机执行
 * @param fsm 状态机对象
*/
void fsm_do(FsmType* fsm);

3.2 实际应用

下面是软件设计中的状态图部分(涉及到公司隐私,不展示部分细节):

// 配置状态
static const FsmNode configState = {configEntryFunc, configDoFunc, NULL};
// 自检
static const FsmNode checkState = {NULL, checkDoFunc, NULL};
// 空闲
static const FsmNode idleState = {idleEntryFunc, idleDoFunc, NULL};
// R300
static const FsmNode r300State = {r300EntryFunc, r300DoFunc, r300DoExit};
// R50
static const FsmNode r50State = {r50EntryFunc, r50DoFunc, r50DoExit};
// 错误
static const FsmNode faultState = {faultEntryFunc, NULL, NULL};
// 关机状态
static const FsmNode shutDownState = {shutDownEntryFunc, NULL, NULL};
static const FsmNode *topNodeTable[TOP_NUMS] =
    {
        &configState,
        &checkState,
        &idleState,
        &r300State,
        &r50State,
        &faultState,
        &shutDownState,
};
void topFsmInit(void)
{
    fsm_init(&topFsmObj,READY_CONFIG,topNodeTable);
}
void topFsmDo(void)
{
    switch(topFsmObj.state)
    {
    case READY_CONFIG:
    case READY_CHECK:
        app_sample_loop();
        break; 
    case WORK_IDLE:
    case WORK_300R:
    case WORK_50R:
    case WORK_FAULT:
        app_sample_loop();
        app_fault_loop();
        break; 
    case TOP_SHUTDOWN:
        break; // 关机状态
    default:
        break;
    }
    fsm_do(&topFsmObj);
}
posted @ 2024-12-12 10:14  HuDaXia  阅读(29)  评论(0编辑  收藏  举报