____ ______ _____ __ __
/ __ \ | ____/ ____| \/ |
| | | |_ __ ___ _ __ | |__ | (___ | \ / |
| | | | '_ \ / _ \ '_ \ | __| \___ \| |\/| |
| |__| | |_) | __/ | | | | | ____) | | | |
\____/| .__/ \___|_| |_| |_| |_____/|_| |_|
| |
|_|
作为一个开源的FSM框架的c/c++实现,Open FSM可以解决过多的条件判断跳转等问题。
1、使用难度小,开发者在使用时,只需关心:
2、支持嵌套,开发者只需额外多做一点工作就可以实现基于Open FSM 的n阶状态机。
3、跨平台,Open FSM 在设计的时候便考虑了应用程序、内核环境以及单片机中的使用。
在使用openfsm
之前,请先包含此头文件。
#include "openfsm.h"
这两个宏定义是为了提高可读性而添加的。
#define FSM_STATE(name) state_##name
#define FSM_FUNCT(name) funct_##name
FSM_STATE
:定义状态值,后续切换时会使用FSM_FUNCT
:定义状态处理函数,与状态对应。例如:
/* FSM Functions */
void* FSM_FUNCT(init)(void * this_fsm); // 初始化状态
void* FSM_FUNCT(do_something)(void * this_fsm);//计数状态
void* FSM_FUNCT(done)(void * this_fsm);// 执行完成状态
void* FSM_FUNCT(err)(void* this_fsm); // 错误状态
/* FSM States */
enum procedure_state {
FSM_STATE(init),
FSM_STATE(count),
FSM_STATE(done),
FSM_STATE(err)
};
状态机处理函数要求指定一个void *this_fsm
的参数。
this_fsm
用于状态机处理函数在执行的时候,执行对应fsm接口函数。
例如:
void* FSM_FUNCT(init) (void* this_fsm)
{
SM_DATA *pd = get_data_entry(this_fsm);
// 切换到下个状态
set_next_state(this_fsm, FSM_STATE(count));
// 数据处理
pd->cnt = 0;
return NULL;
}
Open FSM 允许 在状态执行以后,返回对应的值。
将任何需要的值,强制转换为AS_STEP_RETVAL
类型即可。
void* FSM_FUNCT(xxx) (void* this_fsm)
{
SM_DATA *pd = get_data_entry(this_fsm);
int *err_var;
// 状态处理
set_next_state(this_fsm, FSM_STATE(count));
// 返回一个值
return (AS_STEP_RETVAL)-1;
}
当调用者需要关心 状态机内部执行的状态时,可以通过下列函数得到返回值。
这个值通常是一个void*
型的指针,具体交由调用者自行处理。
void* get_step_retval(FSM* fsm);
fsm
:状态机 实例例如:
step_ret ret = (step_ret) get_step_retval(&sub_fsm);
为了跨平台的考虑,状态机的生命周期管理需要自行负责。
Open FSM不考虑动态内存申请。
例如:
// 静态申请
FSM fsm_1 = {0};
// 动态申请
FSM* p_fsm_1 = malloc(sizeof(FSM));
在Open FSM中,状态机跳转列表代表了状态机中状态对应的处理函数。
void set_procedures(FSM * fsm, Procedure *procedures);
fsm
:状态机 实例procedures
: 一个事先声明好的状态机跳转列表。例如:
/* 状态机跳转列表 */
static Procedure my_procedure_list[] = {
FSM_FUNCT(init),
FSM_FUNCT(do_something),
FSM_FUNCT(done),
FSM_FUNCT(err)
};
set_procedures(&fsm_1, my_procedure_list);
Open FSM支持为状态机添加一个私有的数据域,用于灵活处理复杂的状态。
void set_data_entry(FSM * fsm, void *data);
void* get_data_entry(FSM * fsm);
fsm
:状态机 实例
data
:任意数据入口
set_data_entry
传入的data
可通过get_data_entry
获取。
例如:
// 实际上使用到的数据
char my_data[128] = {0};
// 设置状态机数据域
set_data_entry(&fsm_1, my_data);
// 获取状态机数据域
char *pd = get_data_entry(&fsm_1);
Open FSM规定,在运行状态机之前,需要明确指定一个初始状态。
void set_default_state(FSM * fsm, state st);
fsm
:状态机 实例
st
:状态值,是FSM_STATE
定义的一个值。
例如:
set_default_state(&fsm_1, FSM_STATE(init));
尽管 Open FSM 提供了get_step_retval
用于获取状态机内部执行时的返回值。
如果对于错误处理有更高的要求,可以参考本节的内容以及对应的例程。
Open FSM 在节约内存开销的同时,也支持了一个用于错误处理的flag。
与 上述提及的 数据域 相似,Open FSM 也提供了一个错误域,调用者可自行指定任意类型的数据。
对应的接口如下:
typedef unsigned char state;
// 告知调用者在执行过程中出现了错误。
set_fsm_error_flag(FSM* fsm);
// 清除状态机错误
clr_fsm_error_flag(FSM* fsm);
// 判断状态机在执行过程中是否出现错误。
state is_fsm_error(FSM* fsm);
// 将某个容器设为状态机的错误域。
void set_err_var(FSM* fsm, void* err_var);
// 获取状态机中的错误域,此后可以通过自己设计的方法将值读出。
void* get_err_var(FSM* fsm);
例如:
void* FSM_FUNCT(xx)(void* this_fsm)// 错误状态
{
int *err_var;
// 通知 调用者 有错误发生
set_fsm_error_flag(this_fsm);
// 把 错误值 设进 容器中(如果容器存在)
err_var = get_err_var(this_fsm);
if(err_var)
*err_var = 0xff;
return NULL;
}
// ...
run_state_machine_once(&fsm_1);
// 判断是否出错
if(is_fsm_error(&fsm_1))
{
printf("Error when Stepping !\n");
got_err = get_err_var(&fsm_1);
printf("Get Error Code :0x%x\n", *got_err);
clr_fsm_error_flag(&fsm_1);
}
让 Open FSM 工作的真正接口是run_state_machine_once
,原型如下:
// 执行状态机,使其步进一次
state run_state_machine_once(FSM * fsm);
fsm
:状态机 实例执行完成以后,通过返回值可以获取到刚刚执行过的状态。
例如:
state cur_state;
cur_state = run_state_machine_once(&fsm_1);
printf("Ran :%d\n", cur_state);
可以通过下列函数获取即将执行的状态。
state get_next_state(FSM * fsm);
fsm
:状态机 实例例如:
printf("Next :%d\n", get_next_state(&fsm_1));
void init_state_machine(FSM *p);
void reset_state_machine(FSM *p);
上述的函数都会让状态机回到默认状态,但reset_state_machine
会额外将错误状态清除。
本项目提供3个常见的例程,分别用于实现一阶状态机以及二阶状态机; 以及其中的错误处理。
详细的用法示例请参考 src/example
中的具体实现 。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
1. 开源生态
2. 协作、人、软件
3. 评估模型