/* file qfsm_ini.c ---------------------------------------------------------*/ #include"qep_port.h"/* the port of the QEP event processor */ #include"qassert.h"/* embedded systems-friendly assertions */ voidQFsm_init(QFsm *me, QEvent const *e) { (*me->state)(me, e); /* execute the top-most initial transition */ /* enter the target */ (void)(*me->state)(me , &QEP_reservedEvt_[Q_ENTRY_SIG]); } /* file qfsm_dis.c ---------------------------------------------------------*/ voidQFsm_dispatch(QFsm *me, QEvent const *e) { QStateHandler s = me->state; /* save the current state */ QState r = (*s)(me, e); /* call the event handler */ if (r == Q_RET_TRAN) /* transition taken? */ { (void)(*s)(me, &QEP_reservedEvt_[Q_EXIT_SIG]); /* exit the source */ (void)(*me->state)(me, &QEP_reservedEvt_[Q_ENTRY_SIG]);/*enter target*/ } } 实现上面定时器例子 #include"qep_port.h"/* the port of the QEP event processor */ #include"bsp.h"/* board support package */
enum BombSignals /* all signals for the Bomb FSM */ { UP_SIG = Q_USER_SIG, DOWN_SIG, ARM_SIG, TICK_SIG }; typedefstructTickEvtTag { QEvent super; /* derive from the QEvent structure */ uint8_t fine_time; /* the fine 1/10 s counter */ }TickEvt;
typedefstructBomb4Tag { QFsm super; /* derive from QFsm */ uint8_t timeout; /* number of seconds till explosion */ uint8_t code; /* currently entered code to disarm the bomb */ uint8_t defuse; /* secret defuse code to disarm the bomb */ } Bomb4;
voidBomb4_ctor(Bomb4 *me, uint8_t defuse); QState Bomb4_initial(Bomb4 *me, QEvent const *e); QState Bomb4_setting(Bomb4 *me, QEvent const *e); QState Bomb4_timing(Bomb4 *me, QEvent const *e); /*--------------------------------------------------------------------------*/ /* the initial value of the timeout */ #define INIT_TIMEOUT 10 /*..........................................................................*/ voidBomb4_ctor(Bomb4 *me, uint8_t defuse){ QFsm_ctor_(&me->super, (QStateHandler)&Bomb4_initial); me->defuse = defuse; /* the defuse code is assigned at instantiation */ } /*..........................................................................*/ QState Bomb4_initial(Bomb4 *me, QEvent const *e){ (void)e; me->timeout = INIT_TIMEOUT; return Q_TRAN(&Bomb4_setting); } /*..........................................................................*/ QState Bomb4_setting(Bomb4 *me, QEvent const *e){ switch (e->sig){ case UP_SIG:{ if (me->timeout < 60) { ++me->timeout; BSP_display(me->timeout); } return Q_HANDLED(); } case DOWN_SIG: { if (me->timeout > 1) { --me->timeout; BSP_display(me->timeout); } return Q_HANDLED(); } case ARM_SIG: { return Q_TRAN(&Bomb4_timing); /* transition to "timing" */ } } return Q_IGNORED(); } /*..........................................................................*/ voidBomb4_timing(Bomb4 *me, QEvent const *e){ switch (e->sig) { case Q_ENTRY_SIG: { me->code = 0; /* clear the defuse code */ return Q_HANDLED(); } case UP_SIG: { me->code <<= 1; me->code |= 1; return Q_HANDLED(); } case DOWN_SIG: { me->code <<= 1; return Q_HANDLED(); } case ARM_SIG: { if (me->code == me->defuse) { return Q_TRAN(&Bomb4_setting); } return Q_HANDLED(); } case TICK_SIG: { if (((TickEvt const *)e)->fine_time == 0) { --me->timeout; BSP_display(me->timeout); if (me->timeout == 0) { BSP_boom(); /* destroy the bomb */ } } return Q_HANDLED(); } } return Q_IGNORED(); }
voidQHsm_init(QHsm *me, QEvent const *e) { Q_ALLEGE((*me->state)(me, e) == Q_RET_TRAN); t = (QStateHandler)&QHsm_top; /* HSM starts in the top state */ do { /* drill into the target... */ QStateHandler path[QEP_MAX_NEST_DEPTH_]; int8_t ip = (int8_t)0; /* transition entry path index */ path[0] = me->state; /* 这里的状态为begin */
/*通过执行空信号,从底层状态找到顶状态的路径*/ (void)QEP_TRIG_(me->state, QEP_EMPTY_SIG_); while (me->state != t) { path[++ip] = me->state; (void)QEP_TRIG_(me->state, QEP_EMPTY_SIG_); } /*切换为begin*/ me->state = path[0]; /* restore the target of the initial tran. */ /* 钻到最底层的状态,执行路径中的所有进入事件 */ Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_); do { /* retrace the entry path in reverse (desired) order... */ QEP_ENTER_(path[ip]); /* enter path[ip] */ } while ((--ip) >= (int8_t)0);
t = path[0]; /* current state becomes the new source */ } while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN); me->state = t; }
状态切换:
/*.................................................................*/ QState result(Calc *me, QEvent const *e) { switch (e->sig) {you case ENTER_SIG:{ break; } case EXIT_SIG:{ break; } case C_SIG: { printf("clear"); return Q_HANDLED(); } case B_SIG: { return Q_TRAN(&begin); } } return Q_SUPER(&reday); } /*.ready为result和begin的超状态................................................*/ QState ready(Calc *me, QEvent const *e) { switch (e->sig) { case ENTER_SIG:{ break; } case EXIT_SIG:{ break; } case OPER_SIG: { return Q_TRAN(&opEntered); } } return Q_SUPER(&on); }
voidQHsm_dispatch(QHsm *me, QEvent const *e) { QStateHandler path[QEP_MAX_NEST_DEPTH_]; QStateHandler s; QStateHandler t; QState r; t = me->state; /* save the current state */ do { /* process the event hierarchically... */ s = me->state; r = (*s)(me, e); /* invoke state handler s */ } while (r == Q_RET_SUPER); //当前状态不能处理事件 ,直到找到能处理事件的状态
if (r == Q_RET_TRAN) { /* transition taken? */ int8_t ip = (int8_t)(-1); /* transition entry path index */ int8_t iq; /* helper transition entry path index */ path[0] = me->state; /* save the target of the transition */ path[1] = t; while (t != s) { /* exit current state to transition source s... */ if (QEP_TRIG_(t, Q_EXIT_SIG) == Q_RET_HANDLED) {/*exit handled? */ (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); /* find superstate of t */ } t = me->state; /* me->state holds the superstate */ } . . . } me->state = t; /* set new state or restore the current state */ }
t = path[0]; /* target of the transition */ if (s == t) { /* (a) check source==target (transition to self) */ QEP_EXIT_(s) /* exit the source */ ip = (int8_t)0; /* enter the target */ } else { (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); /* superstate of target */ t = me->state; if (s == t) { /* (b) check source==target->super */ ip = (int8_t)0; /* enter the target */ } else { (void)QEP_TRIG_(s, QEP_EMPTY_SIG_); /* superstate of src */ /* (c) check source->super==target->super */ if(me->state == t) { QEP_EXIT_(s) /* exit the source */ ip = (int8_t)0; /* enter the target */ } else { /* (d) check source->super==target */ if (me->state == path[0]) { QEP_EXIT_(s) /* exit the source */ } else { /* (e) check rest of source==target->super->super.. * and store the entry path along the way */ ....