一乐电子

一乐电子百科

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

搜索
查看: 2140|回复: 0
收起左侧

[操作系统]QEP之init()和dispatch()流程图

[复制链接]
发表于 2018-4-19 10:51 | 显示全部楼层 |阅读模式
本帖最后由 kenson 于 2018-4-19 11:15 编辑
7 a& T8 }! y, Y
9 b7 V- a; v/ j4 i/ e& \; K( gQEP之init()和dispatch()流程图
( l/ O- ^5 w, A, R& x& {* B% u
抽象状态机类QFsm或QHsm有一个函数指针,用于在继承的具体状态机类中指向具体的状态函数,其有两个对外的接口函数init()和dispatch(),其工作原理是理解状态机处理事件过程的关键。
具体状态机类继承自QFsm或QHsm,同时继承了这个函数指针,用于动态指向具体状态机类中的私有状态函数。
具体事件继承于根事件QEvent,并可以自己增加附加的属性。事件是外部与状态机唯一通信的实体,通过dispatch(),把事件送到状态机。状态机对外不可见,具体属性和具体状态函数都是私有的。

" g5 \# G- S9 s3 o# {0 G7 f     图1.QEP总体类结构1.预备知识
(1)声明一个函数指针
具体状态机类继承自QFsm或QHsm,则具体状态机具有了一个指针state,state可以指向任何状态函数,并调用状态函数执行。dispatch()函数可以用空事件探测状态机的结构、可以执行进入和退出动作、可以执行具体的事件处理动作,也可以进行状态转移。
2 b. a0 r& w# @: f6 X2 I; N8 z
typedef uint8_t QState;                           
8 T* i4 R% n$ h2 M
typedef QState (*QStateHandler)(void *me, QEvent const *e);/*函数指针*/
: ~; X9 s3 B2 M3 b8 B! W8 P: x* v2 t: K6 m
(2)声明一个状态机中的函数指针变量
typedef struct QFsmTag {   
4 Q  g/ k$ O' V
QStateHandler state; /*变量(函数指针),指向状态机当前状态(函数)*/. z" @8 l  v6 K5 x# F7 I
} QFsm;( v5 i' o' P. F

; `+ T& G6 x3 @
typedef struct QFsmTag QHsm;
! e& J; e, ~* {+ A0 T, r# ^! `9 Y+ `
(3)状态函数处理后的返回结果
每个状态函数中,根据不同的事件处理,处理完后要返回上边的结果之一,供dispatch()了解状态函数对某事件是否忽略、是否处理完、是否转换、是否不能处理而要让父状态函数来处理。
QSUPP(super)中的参数决定了层次状态机的层次结构。
/* 忽略事件 */
, X+ F3 I9 A: j2 m: A9 X7 [8 G
#define Q_IGNORED()         (Q_RET_IGNORED)
6 ?' Y: C: X4 X" f. R2 j/* 已处理事件 */
! O( n' V8 p* u) p5 A% N5 }; f#define Q_HANDLED()         (Q_RET_HANDLED)
' b/ U. L* m- n8 u/* 状态转移 */
. t! x9 R* h% u7 o: b# |, i#define Q_TRAN(target_)      (((QFsm *)me)->state = (QStateHandler)(target_), Q_RET_TRAN)/ {* F$ q: m0 h. t$ ]9 v+ B* [; M
/* 到超状态 */# z. f9 U; |3 G0 e2 ]2 L1 K+ z
#define Q_SUPER(super_)      (((QHsm *)me)->state = (QStateHandler)(super_),  Q_RET_SUPER)
' x1 z" R3 Q8 z) n7 u8 l: v3 A$ l/ \8 l
& n9 A; a* i, E8 t! ~
(4)触发动作
dispatch()用于主动去触发具体状态机,以探知状态机的结构、执行进入和退出动作。用QEP_EMPTY_SIG 触发空动作,总是会执行到状态函数的最后一行 QSUPPER(super_),通过触发后的返回结果,可以探知状态机的层次结构。
/* 以sig_信号触发状态机 */
' Q9 T; @3 l6 P6 ^5 A* f: C# P
#define QEP_TRIG_(state_, sig_)     ((*(state_))(me, &QEP_reservedEvt_[sig_]))4 D6 |3 g+ y6 \* |
/* 触发退出动作,在层次状态机HSM */1 D0 g0 U% T& ~( K7 h$ J6 K
#define QEP_EXIT_(state_)     
. U% ~3 n6 j0 [5 S! p: A6 ^: pif (QEP_TRIG_(state_, Q_EXIT_SIG) == Q_RET_HANDLED)
, Z# E: k3 E) [1 j{
" _0 H$ Z4 O; ~& o! ~0 T+ P8 E         ...QS     
" l) h  S0 L  V}
5 N. U7 O& g* s
/ ]; ^% U7 @1 l9 d! O* ]6 t
  u) M  ^' W" e3 C$ v: v/ f+ K& u
/* 触发进入动作,在层次状态机HSM */
6 ~+ i, [, F' p+ n9 J; I3 M5 c#define QEP_ENTER_(state_)     & F# p: \: B# i  x8 A" b$ ?3 c
if (QEP_TRIG_(state_, Q_ENTRY_SIG) == Q_RET_HANDLED) ) z! S8 ^- H- z, S& v3 {5 B% d2 Y
{
7 ~/ e0 w, i" E8 ]) Q- ^2 b( p3 N. \         ...QS     5 B+ E! O: Y. [) v
}
. d- v" H) r0 w; P, K+ l; s
# z  ]/ u8 e1 Y, t* q

9 F) {/ v, z1 m# F: b+ X; x8 I/* 触发空动作,在层次状态机HSM (自加)*/) p- |' v; A6 Y6 j9 E/ g- Z
#define QEP_EMPTY_(state_)     QEP_TRIG_(state_, QEP_EMPTY_SIG_)  
4 c# Y+ x2 |( _, u
# a3 j4 q; c" |/ f2.Fsm状态机init()和dispatch()流程

(1)QFsm_init()流程+ }) W5 I: c; q  {8 X
815490-20151227210907906-1888535234.png 

   图2.QFsm_init()流程

(2)QFsm_dispatch()流程
5 w0 T9 J' H/ o& _: x% b 815490-20151227210907999-1694829155.png 

   图3.QFsm_dispatch()流程3.Hsm状态机init()和dispatch()流程

从顶级状态的初始伪状态开始,到本初始伪状态转换的终状态(子状态),执行进入动作。在终状态(子状态)继续检查有没有子初始伪状态,如果有的话,继续进入,执行进入动作,直到最终状态。

(1)QHsm_init()流程
" z2 F- S/ N& N& T6 L" w 815490-20151227210908374-1012628730.png 

   图4.QHsm_init()流程图与层次状态机

(2)QHsm_dispatch()流程
2 b9 F7 [6 B' f% B2 m" s* M 815490-20151227210910999-1369603859.png 

   图5.QHsm_dispatch()流程图
815490-20151227210908343-159821549.png
815490-20151227210907906-1888535234.png
815490-20151227210907999-1694829155.png
815490-20151227210908374-1012628730.png
815490-20151227210910999-1369603859.png

本版积分规则

QQ|一淘宝店|手机版|商店|电子DIY套件|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2024-5-5 01:20 , Processed in 0.062928 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表