一乐电子

一乐电子百科

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

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

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

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

[复制链接]
发表于 2018-4-19 10:51 | 显示全部楼层 |阅读模式
本帖最后由 kenson 于 2018-4-19 11:15 编辑
, C# p% K! ?) J5 J0 o. g' x% D. p
7 c( J- i- s/ I, J2 wQEP之init()和dispatch()流程图
, ?1 r% U* @8 m* U
抽象状态机类QFsm或QHsm有一个函数指针,用于在继承的具体状态机类中指向具体的状态函数,其有两个对外的接口函数init()和dispatch(),其工作原理是理解状态机处理事件过程的关键。
具体状态机类继承自QFsm或QHsm,同时继承了这个函数指针,用于动态指向具体状态机类中的私有状态函数。
具体事件继承于根事件QEvent,并可以自己增加附加的属性。事件是外部与状态机唯一通信的实体,通过dispatch(),把事件送到状态机。状态机对外不可见,具体属性和具体状态函数都是私有的。
0 r& k! Z0 P% f& ?; B
     图1.QEP总体类结构1.预备知识
(1)声明一个函数指针
具体状态机类继承自QFsm或QHsm,则具体状态机具有了一个指针state,state可以指向任何状态函数,并调用状态函数执行。dispatch()函数可以用空事件探测状态机的结构、可以执行进入和退出动作、可以执行具体的事件处理动作,也可以进行状态转移。

% G3 Y  O7 V5 U; \9 jtypedef uint8_t QState;                           

+ l  d4 Y$ ~: R
typedef QState (*QStateHandler)(void *me, QEvent const *e);/*函数指针*/$ c2 }5 g& R( _; D

( i; p( [# E$ B  Q% o
(2)声明一个状态机中的函数指针变量
typedef struct QFsmTag {   
2 @/ Y5 B5 P& M  |/ F. ^" g
QStateHandler state; /*变量(函数指针),指向状态机当前状态(函数)*/
( z. D& |8 ~0 |* G# |7 s} QFsm;
" s* ?: E% ~0 n; R. _
) |: Z9 i6 o& b
typedef struct QFsmTag QHsm;
+ N, Y( v# N$ k, p. o, O* i1 r( t2 E3 z4 V9 ]' p  i& a
(3)状态函数处理后的返回结果
每个状态函数中,根据不同的事件处理,处理完后要返回上边的结果之一,供dispatch()了解状态函数对某事件是否忽略、是否处理完、是否转换、是否不能处理而要让父状态函数来处理。
QSUPP(super)中的参数决定了层次状态机的层次结构。
/* 忽略事件 */

% O* Q( o& }& C0 k/ _#define Q_IGNORED()         (Q_RET_IGNORED)7 B6 H: E0 Z. t" `
/* 已处理事件 */
& H6 `6 l' E$ O( O  q- W8 i#define Q_HANDLED()         (Q_RET_HANDLED)
2 R4 M: j/ K2 w# X' {* g/* 状态转移 */
- X6 O, O5 k5 ~6 c7 {8 w* A#define Q_TRAN(target_)      (((QFsm *)me)->state = (QStateHandler)(target_), Q_RET_TRAN)
$ a: ?" x1 ^2 j( t0 o/* 到超状态 */" d2 w" ]& _. P5 I
#define Q_SUPER(super_)      (((QHsm *)me)->state = (QStateHandler)(super_),  Q_RET_SUPER)
: J& m6 u2 C  p5 U! j3 h8 j' c4 O" N5 s3 [
(4)触发动作
dispatch()用于主动去触发具体状态机,以探知状态机的结构、执行进入和退出动作。用QEP_EMPTY_SIG 触发空动作,总是会执行到状态函数的最后一行 QSUPPER(super_),通过触发后的返回结果,可以探知状态机的层次结构。
/* 以sig_信号触发状态机 */

; b, s6 ~+ o, G9 ^; t0 ?$ Z6 g#define QEP_TRIG_(state_, sig_)     ((*(state_))(me, &QEP_reservedEvt_[sig_]))$ t2 V4 v5 y: T6 R* a! Q
/* 触发退出动作,在层次状态机HSM */- m% O5 F! N& s) r0 R! S9 G- b) W
#define QEP_EXIT_(state_)     4 s3 d+ L. P  ~, H4 C- y2 t0 l
if (QEP_TRIG_(state_, Q_EXIT_SIG) == Q_RET_HANDLED) # G0 |; x) \+ g# F9 M
{
5 X# m6 U- O# \) g  H0 w/ H9 {         ...QS     , l7 x" {5 a# T+ x
}
8 F* _, G4 `$ n1 z. y- v3 ~. w# k% T, R

0 b  ~9 Y, ?' j8 p( U/* 触发进入动作,在层次状态机HSM */: V4 e6 q, i: _' W5 I5 G! |: w2 s; _
#define QEP_ENTER_(state_)     ) ~4 P, s! @7 |( R% |
if (QEP_TRIG_(state_, Q_ENTRY_SIG) == Q_RET_HANDLED)   g: x/ w2 b4 H! e3 j; n1 u
{
6 I( }* u% i# W# I7 K         ...QS     
# S+ a: }$ D4 I0 M}
" e- P7 e. X' V5 |" d  p
" [" m. x/ s) P# Y9 H0 O1 W+ n8 v
; t  C' _3 f6 l& H+ J0 i$ L1 G
/* 触发空动作,在层次状态机HSM (自加)*/
8 ^% j. p' i) E#define QEP_EMPTY_(state_)     QEP_TRIG_(state_, QEP_EMPTY_SIG_)  
) E3 {5 r. y2 r' u2 F: h4 L
7 ?  J5 G# \' ]; r2.Fsm状态机init()和dispatch()流程

(1)QFsm_init()流程" j/ x' }9 w' z
815490-20151227210907906-1888535234.png 

   图2.QFsm_init()流程

(2)QFsm_dispatch()流程
$ s7 x  ]& Y! u$ B# a% ]9 {  U8 f 815490-20151227210907999-1694829155.png 

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

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

(1)QHsm_init()流程6 b3 D& M& L! _
815490-20151227210908374-1012628730.png 

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

(2)QHsm_dispatch()流程
4 \, K7 K, @: V: r7 j8 O 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-4-26 00:30 , Processed in 0.045469 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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