基于真值表的有限状态机实现

在ECU的处理逻辑中往往摆脱不了状态机,为了使状态编程清晰可靠,可以将状态跳转条件组成真值表,将状态跳转用模型实现,一方面减少逻辑的复杂度,另一方面可以将代码变得更清晰减少出错。以下是我的思路,希望能给大家提供一些帮助,具体实现如下:

static volatile Uint32 fsm_tmr[STATE_CNT+1] = {0};

void fsm_timer_init(void)
{
    MemSet((Uint16 *)fsm_tmr, 0, sizeof(fsm_tmr));
}

void fsm_set_timer(Uint16 index, Uint32 tout)
{
    fsm_tmr[index] = tout;
}

Uint32 fsm_get_timer(Uint16 index)
{
    return fsm_tmr[index];
}


Uint16 fsm_chk_timer(Uint16 index)
{
    return (!fsm_tmr[index]);
}

void fsm_1ms_irq(void)
{
    Uint16 j;

    for(j = 0; j < STATE_CNT+1; j++)
	{
        if(fsm_tmr[j])
        {
            fsm_tmr[j]--;
        }
	}
}

typedef enum
{
    STARTUP,
    INIT,
    STANDBY,
    CHARG,
    SHUTDOWN,
    STATE_CNT
}FSM_STATE;

Uint16 jump_matrix[STARTUP][INIT];
Uint16 fsm_state_min_time[FSM_STATE] = {200, 200, 200, 200, 200};

#define MATRIX_INIT(cond,dly) (((!!(cond))<<15) | (dly))

void update_matrix(void)
{
    jump_matrix[STARTUP][INIT] = MATRIX_INIT(1,0);
    jump_matrix[INIT][STANDBY] = MATRIX_INIT(1,0);
    jump_matrix[INIT][SHUTDOWN] = MATRIX_INIT(1,0);
}

typedef struct
{
    (void)(*entry_ev)(void);
    (void)(*during_ev)(void);
    (void)(*exit_ev)(void);
    
}FSM_EV;

FSM_EV ev_list[STATE_CNT] = 
{
    .[INIT] = {},
    .[STANDBY] = {}
};

typedef struct
{
    FSM_STATE state;
    Uint16 (*matrix)[STATE_CNT][STATE_CNT];
    FSM_EV *event;
    (void)(*state_change_notification)(FSM_STATE, FSM_STATE);
}FSM_INS;

FSM_INS fsm;

void fsm_state_change_notification(FSM_STATE prev_state, FSM_STATE curr_state)
{
}

void fsm_init(void)
{
    fsm.state = STARTUP;
    fsm.matrix = jump_matrix;
    fsm.event = ev_list;
    fsm.state_change_notification = fsm_state_change_notification;
}

void fsm_run(void)
{
    Uint16 i;

    update_matrix();
    
    (fsm.event[fsm.state]->state_ev)();
    
    for(i = 0; i < STATE_CNT; i++)
    {
        //lookup table
        if(fsm.matrx[fsm.state][i] & 0x8000)
        {
            if(fsm_chk_timer(i) && fsm_chk_timer(STATE_CNT))
            {
                //(fsm.event[fsm.state]->exit_ev)();
                (fsm.event[fsm.state]->state_change_notification)(fsm.state, i);
                fsm.state = i;
                
                fsm_timer_init();

                fsm_set_timer(STATE_CNT, fsm_state_min_time[fsm.state]*MS_T);
                
                //(fsm.event_list[fsm.state]->entry_ev)();

                //(fsm.event_list[fsm.state]->during_ev)();
                break;
            }
        }
        else
        {
            fsm_set_timer(i, fsm.matrx[fsm.state][i]&0x7FFF);
        }
    } 
}

 

发布了114 篇原创文章 · 获赞 76 · 访问量 36万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览