sx1276 starter kit:【原创】技术系列之 状态机(二)

来源:百度文库 编辑:偶看新闻 时间:2024/05/02 19:32:07
【原创】技术系列之 状态机(二)

作者:CppExplore 网址:http://www.cppblog.com/CppExplore/
上接《系统设计之 状态机(一)》
三、状态机实现
(2)面向过程方式
2、层次状态机模块实现。

与常规状态机相比,它的FSM_STATE结构没有default_func,多了 FSM_STATE_ID parent; FSM_STATE_ID default_child;两个结构。状态机初始化的时候可以指定默认状态,为了防止指定的状态非叶结点,增加fsm_init方法。该状态机的事件处理算法简单描述如下:(1)首先在当前状态以及其祖先状态的状态事件表中搜索匹配事件,如果搜索到,保存操作以及目的状态标识;(2)在old栈中保存当前状态到根节点的路径,在new栈中保存目的状态到根节点的路径;(3)将old栈中的顶层元素依次与new栈的顶层元素匹配,如果匹配则都出栈,不匹配,停止;(4)当前的old栈中节点即为该事件导致的退出状态,从栈低扫描到栈顶,依次执行exit_func;(5)执行以前保存的操作;(6)扫描new栈,从栈顶到栈低依次执行enter_func;(7)最后检测目的状态是否是叶节点状态,否,则依次进入default_child节点,并执行enter_func。模块实现代码如下:#define SINGLE_STATE_MAX_EVENT 10
#define STATE_TREE_DEPTH 10
typedef  int FSM_EVENT_ID;
typedef struct event_param_st
{
    FSM_EVENT_ID id;
    union{
        int i;
    }data;
}FSM_EVENT;
typedef  int FSM_STATE_ID;
typedef void (*FSM_FUNC)(FSM_EVENT *);
typedef struct state_event_st
{
    FSM_FUNC func;
    FSM_EVENT_ID event;
    FSM_STATE_ID state;
}FSM_STATE_EVENT;
typedef struct state_st
{
    FSM_STATE_ID id;
    char *name;
    FSM_STATE_ID parent;
    FSM_STATE_ID default_child;
    FSM_FUNC enter_func;
    FSM_FUNC exit_func;
    FSM_STATE_EVENT event_table[SINGLE_STATE_MAX_EVENT]; 
}FSM_STATE;
typedef FSM_STATE STATE_TABLE[];
typedef FSM_STATE * PTR_STATE_TABLE;

#define END_EVENT_ID -1
#define END_STATE_ID -1
#define BEGIN_FSM_STATE_TABLE(state_stable) static STATE_TABLE state_stable={
#define BEGIN_STATE(id,name,parent,default_child,enter_func,exit_func) {id,name,parent,default_child,enter_func,exit_func,{
#define STATE_EVENT_ITEM(func,event,state) {func,event,state},
#define END_STATE(id) {NULL,END_EVENT_ID,END_STATE_ID}}},
#define END_FSM_STATE_TABLE(state_stable) {END_STATE_ID,NULL,END_STATE_ID,END_STATE_ID,NULL,NULL,NULL}};

typedef struct fsm_st
{
    FSM_STATE_ID state_id;
    FSM_FUNC default_func;
    PTR_STATE_TABLE state_tables;
}FSM;

void fsm_init(FSM &fsm)
{
    FSM_STATE *state=&(fsm.state_tables[fsm.state_id]);
    while(state->default_child!=END_STATE_ID)
    {
        state=&(fsm.state_tables[state->default_child]);
        if(state->enter_func)
            state->enter_func(NULL);
    }
    fsm.state_id=state->id;
}
void fsm_do_event(FSM &fsm, FSM_EVENT &event)
{
    FSM_STATE *state;
    FSM_STATE_ID state_id,old_state_id,new_state_id;
    FSM_STATE_ID oldStack[STATE_TREE_DEPTH],newStack[STATE_TREE_DEPTH];
    int old_cur=0,new_cur=0;
    
    bool isMatch=false;
    FSM_FUNC match_func=NULL;
    int i=0;
    state_id=old_state_id=fsm.state_id;
    do
    {
        i=0;
        state=&(fsm.state_tables[state_id]);
        while(state->event_table[i].event!=END_EVENT_ID)
        {
            if(state->event_table[i].event==event.id)
            {
                isMatch=true;
                match_func=state->event_table[i].func;
                new_state_id=state->event_table[i].state;
                break;
            }
            i++;
        }
        if(isMatch==false)
            state_id=state->parent;
        else
            break;
    }while(state->parent!=END_STATE_ID);
    if(isMatch==false)
    {
        if(fsm.default_func)
            fsm.default_func(&event);
        return;
    }
    if(new_state_id==old_state_id)
    {
        if(match_func)
            match_func(&event);
        return;
    }
    state_id=old_state_id;
    do
    {
        oldStack[old_cur++]=state_id;
        state=&(fsm.state_tables[state_id]);
        state_id=state->parent;
    }while(state->parent!=END_STATE_ID);
    state_id=new_state_id;
    do
    {
        newStack[new_cur++]=state_id;
        state=&(fsm.state_tables[state_id]);
        state_id=state->parent;
    }while(state->parent!=END_STATE_ID);
    while(oldStack[old_cur-1]==newStack[new_cur-1])
    {
        old_cur--;
        new_cur--;
    }
    for(i=0;i    {
        if(fsm.state_tables[oldStack[i]].exit_func)
            fsm.state_tables[oldStack[i]].exit_func(&event);
    }
    if(match_func)
        match_func(&event);
    for(i=new_cur;i>0;i--)
    {
        if(fsm.state_tables[newStack[i-1]].enter_func)
            fsm.state_tables[newStack[i-1]].enter_func(&event);
    }
    state=&(fsm.state_tables[new_state_id]);
    while(state->default_child!=END_STATE_ID)
    {
        state=&(fsm.state_tables[state->default_child]);
        if(state->enter_func)
            state->enter_func(&event);
    }
    fsm.state_id=state->id;
}使用举例,仅仅列举一个状态表和简单的状态机初始化,状态和事件应该为enum,当前使用数字,仅为了举例,操作的实现不在写出。BEGIN_FSM_STATE_TABLE(my_state_table)
    BEGIN_STATE(0,"first",END_STATE_ID,2,enter_fsm,exit_fsm)
        STATE_EVENT_ITEM(func_fsm,1,1)
        STATE_EVENT_ITEM(func_fsm,2,2)
    END_STATE(0)
    
    BEGIN_STATE(1,"second",0,END_STATE_ID,enter_fsm,exit_fsm)
        STATE_EVENT_ITEM(func_fsm,1,3)
        STATE_EVENT_ITEM(func_fsm,2,0)
    END_STATE(1)
    
    BEGIN_STATE(2,"third",0,3,enter_fsm,exit_fsm)
        STATE_EVENT_ITEM(func_fsm,1,0)
        STATE_EVENT_ITEM(func_fsm,2,1)
    END_STATE(2)
    BEGIN_STATE(3,"third",2,END_STATE_ID,enter_fsm,exit_fsm)
        STATE_EVENT_ITEM(func_fsm,1,4)
        STATE_EVENT_ITEM(func_fsm,2,1)
    END_STATE(3)
    BEGIN_STATE(4,"third",2,END_STATE_ID,enter_fsm,exit_fsm)
        STATE_EVENT_ITEM(func_fsm,1,2)
        STATE_EVENT_ITEM(func_fsm,2,1)
    END_STATE(4)
END_FSM_STATE_TABLE(my_state_table)
FSM fsm={0,default_fsm,my_state_table};
fsm_init(fsm);
FSM_EVENT event;
event.id=1;
event.data.i=1;
fsm_do_event(fsm,event);



后续提纲:
三、状态机实现
(3)面向对象方式 常规&层次

四、状态机分析
五、状态机回路检测
六、状态机使用
另介绍boost中同步异步状态机