嵌入式有限状态机软件设计及应用
一、状态机介绍
状态机,也称为有限状态机(Finite State Machine,FSM),是一种数学模型,用于描述系统的行为模式和状态转移关系。状态机常用概念介绍:
- 状态:状态机的组成部分,一个状态机由多个状态组成,假设洗衣机洗衣服的过程用状态机表示,这个状态机则包含:放水、浸洗、漂洗、脱水等多个状态。
- 起点:状态机从这里开始启动,是一个伪状态,指向的状态是当前状态机的第一个状态
- 终点:状态机从这里结束,也是一个伪状态
- 转换活动:从一个状态转换到另一个状态的动作,通常流程为:
- 转换条件触发➡转换状态的退出动作➡转换过程中的动作➡被转换状态的入口动作
- 入口动作:一个状态刚进来时需要做的事,在洗衣服的状态机中的放水状态的入口动作是,打开水龙头。
- 出口动作:一个状态退出时需要做的事,放水状态的出口动作是关闭水龙头
- 保持动作:状态需要保持做的事情,比如放水状态需要保持放水,并且一直判断水位
二、项目背景
公司最近有个简单的项目,但是由于没有专业的产品经理,给到软件这边的产品需求实在是一言难尽。经过多次反复与领导的沟通,才大概明白一些需求是干什么的,理解了需求后使用状态机做软件设计。
看下软件拿到的需求😵:
三、最终效果
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);
}
0.0点关注不迷路QAQ