NorthFrame是基于非UML极简理念的状态机框架
; M2 Y* X* v6 {9 J+ Y) Y( [. p
3 G5 W: j' B4 u- o9 G1 Y0 I# M9 Z+ }9 [
配合NF_FsmDesigner图形化开发工具,可无负担替代传统switch-case状态机开发
$ K9 R H3 h3 H
. M* ]+ e. a( l/ f
- r# v: Z& u# Y, D1、NorthFrame的组件
4 f/ g; `$ r5 n" b5 O3 k: ENF_FSM :
) W' ?% P% n4 [- h& u% e' N# H/ }5 T; e, Z
- B/ i- P" \/ G) n- H! f2 b7 k( m极简非UML状态机框架
3 I ^! i6 w. N6 n/ H# Z/ B% {' P$ u6 F; W5 p/ r8 t7 {
- \ h( b' [( C+ KNF_FsmDesigner :
4 H3 d4 i* z Q9 A; o, C" S5 F# e* q. r5 G4 Z$ D& q
9 d3 O Z, G4 v Z% g
基于C# Winform开发的状态机图形化开发工具,可直接生成C代码% a7 t7 x. e9 `8 h! ?- [" w+ F7 X
, \- M* n3 B, D/ g: q; z
$ y# |, x& {; Z* Q7 H) M
NF_Signal :9 e; [4 ?% m2 y$ L# A4 Z) n$ T2 G
& c Y. ]5 C Y0 `8 N) P& T
H3 v; [ p/ H- _9 k) b) p( @
用于代替全局变量的动态信号机制
/ {2 v& ]2 p, r9 A' Z) I4 } m/ |2 o" i/ W4 e+ I
& H) n, y3 _" `% ENF_Signal :代替全局变量,使用方便:1 f2 }4 g9 r. y* e* s' E
- <font face="微软雅黑" size="3">NF_Signal_Set("flag_connect", 1);" o! o' g q+ b! G4 E
- ( |4 T$ L T# ^( {
- NF_Signal_Set("blink_cnt", 3);8 |" T* l! j0 `4 R# c& k+ j
- 1 q3 m3 b) F0 E% y! B
- NF_SignalValue flag_connect = NF_Signal_Get("flag_connect");</font>
复制代码 {7 |1 a& V/ s" e) K# \
, I P: z n; k
' F# I9 M1 D0 _7 h1 u( T2 m3 q- g. D4 ~1 n8 I6 Q/ n
2、NorthFrame图形化状态机开发
/ B2 N6 }1 J: j; K: \+ [% C以下例程在VS2012环境中运行一个判断QE组合键的状态机:
5 y3 ]/ ~: ?+ U: `% z/ c1 C. Z- o! e6 e9 L
C7 Z3 |6 L1 S0 Y1 L+ ]Step1 : 使用NF_FsmDesigner工具设计绘制状态转换图,并保存为XML文件
' U. }$ p: |% X: A$ T6 h
: h! d& B3 O' a# H$ q, T1 O1 P5 s/ c# z
2 n c$ W' G$ A8 r1 v: g$ K9 q" o
# J4 W0 o0 X j/ _/ O
! y' I/ f- ~ f4 A4 OStep2 : 点击生成代码,生成如下C语言代码: }$ [! @' R8 H9 l# o7 c7 s& g
- <font face="微软雅黑" size="3">#include <n_frame.h>
5 {/ a+ s; `- Q - #include <fsm_qande.h>
! t/ o% U$ k. ^/ [* e. n$ b/ d0 S
6 X; ]- b/ B3 o- /* 转换执行的外部函数声明 */. L' F$ ^1 o* z( J
- extern void IDLE_TO_Q(void);
5 B+ [3 k6 z% ~6 L" p* } - extern void Q_TO_QE(void);
4 y: ^" E( F% Z; P - extern void QE_TO_IDLE(void);- r3 P$ P) M% D
- extern void QE_TO_Q(void);) d9 I! V# P b7 q- Z5 S$ b
- extern void Q_TO_IDLE(void);9 G0 @" D7 }% H- D6 W. \
4 V6 w. A3 e; K8 Z- /* 状态处理函数声明 */
) g7 P5 Z A) k8 M6 o K) ^# D0 r - void FSM_QandE_IDLE(NF_FSM* me, NF_Event event);
! \: k+ |- T b - void FSM_QandE_Q_DOWN(NF_FSM* me, NF_Event event);
7 U- Z7 z- ]$ P8 ~8 R4 R* C - void FSM_QandE_QE_DOWN(NF_FSM* me, NF_Event event);6 C, v( p/ C5 Y+ P0 M' p7 I+ R
- 7 w/ K! x6 D. r9 X1 s% x
- /* 状态机对象 */% S' ~$ P5 q: @2 I
- NF_FSM FSM_QandE = {
7 B, C' c" Y7 X! |3 ~' j - FSM_QandE_IDLE$ ^$ ?8 G R# L& e* X
- };) V- D- e5 x& p
- % m. H' W9 v, s, O
- /* IDLE状态处理函数 */
# B( e! _- C& b1 K3 g$ D - void FSM_QandE_IDLE(NF_FSM* me, NF_Event event)- ~- R& Q; R5 j* ?0 D: e9 z
- {
$ M1 t3 F9 ?3 u5 g$ V - & M7 @8 I/ g$ W0 d
- if (NF_FSM_NameIs(event.Name, "Q_DOWN"))" X: O! t- @: y# x2 m& @3 ?
- {' d0 w2 j# Y% r/ E) Y( g& y
- IDLE_TO_Q();
% b/ z1 ], U4 m- Y' U4 s - NF_FSM_TRAN(FSM_QandE_Q_DOWN);( l! W8 h6 D6 e1 w0 d
- return ;
/ T- _1 U+ l7 j% S& ^ - }
. e& D0 k" s& m) `
# q6 {. C- i' p& ]- if (NF_FSM_NameIs(event.Name, "test"))0 v- }- @, G+ w7 q5 X; H
- {
& o" Z$ s0 E# _; B1 ]" i% } - NF_FSM_TRAN(FSM_QandE_IDLE);
; O1 A; C; S9 E! O% m4 R - return ;4 h7 `$ P" E* C1 x
- }. V; f' w; O' l( f
- }
0 I! y! S6 @2 D- S7 F3 V& r9 p
# B1 N F" |* b; p; l% \% W3 H# ~; F- /* Q_DOWN状态处理函数 */
' u1 K( E3 r$ N# U5 a. R5 F2 |9 o - void FSM_QandE_Q_DOWN(NF_FSM* me, NF_Event event)
% @$ X4 U1 ]+ `: x - {
( |$ a+ ^# c: P
, ?4 s/ y( o% y( j0 P8 k% W, X: R- if (NF_FSM_NameIs(event.Name, "E_DOWN"))/ f# z( G7 ?/ @0 x0 z3 E
- {6 Z! A7 s* A) H/ g, @& V
- Q_TO_QE();
6 H1 ~" [0 p) h* d7 y( J F0 g% M @ - NF_FSM_TRAN(FSM_QandE_QE_DOWN);! h4 O9 ]( }1 c8 f4 s
- return ;+ b0 G q' ^: `, [
- }/ M) B$ ]8 h+ V, f
/ ^! a9 Q, U4 V. K. x! J7 F, y- if (NF_FSM_NameIs(event.Name, "Q_UP"))
+ C, G# T) e5 W7 c4 | - {
; i! d/ i5 X% B! |( j6 p% X - Q_TO_IDLE();; e# P8 I- M9 y
- NF_FSM_TRAN(FSM_QandE_IDLE);
. P ^) Z; G" Z3 K6 ^3 |) |1 ` - return ;
7 A+ P" g- G+ [5 m6 d - }0 Q) D7 o& u1 S8 f6 X7 d( ^% m
- }
2 e3 i% w0 \6 G
6 M# a+ H3 l! w& G$ `- /* QE_DOWN状态处理函数 */; ?9 }0 L( J5 |* q% p% [
- void FSM_QandE_QE_DOWN(NF_FSM* me, NF_Event event)
- e( T' s5 [+ r7 p" f5 F - {# r9 S9 z$ e1 J) H8 V1 [! g: J
# h6 ^2 t( e' w, [& x+ S( g- if (NF_FSM_NameIs(event.Name, "Q_UP"))2 e) S" S/ Q, o% g9 Z0 y) e. S
- {
# \! |8 m1 L8 a6 D( w. U; Z - QE_TO_IDLE();
! u# A, I# T I! A; Y - NF_FSM_TRAN(FSM_QandE_IDLE);
9 D' d; `& U, k; u - return ;* q$ H6 Y& j U/ u
- }
6 U: H* }1 b3 X - " G5 P3 v% c' }, U
- if (NF_FSM_NameIs(event.Name, "E_UP"))/ ~$ x8 _" R3 H, z. }
- {
9 B* d, F# R" F - QE_TO_Q();
3 h/ y9 l- G3 t( B, J5 ~! J; f - NF_FSM_TRAN(FSM_QandE_Q_DOWN);
. D2 K& \% X9 C" j0 p - return ;6 K" X4 i8 ~; v+ H$ ?: D7 _( f
- }
5 L' q, @4 x) k- B% `& @) X - }</font>
复制代码Step3 : 在main.c文件中实现按键处理,并发送事件给状态机 备注 : 后续版本会加入发布-订阅机制,目前仅支持直接派发 - <font face="微软雅黑" size="3">#include "n_frame.h"" I1 Y- I5 h" w
- ( \6 ` |2 u) y3 a; V* m$ ?
- #include "windows.h"
7 L$ e/ H6 C6 I, ^# r - #include "stdio.h"
9 k- x7 F/ E4 V- L - ) Y3 E& z0 V% Q' W0 y) c
- #include "fsm_qande.h"
! q! t' e1 k, c7 ? - 2 r# ]" C! @2 i& u
- #define KEY_VALUE(_key) ((GetKeyState(_key) >= 0) ? NF_Bool_False : NF_Bool_True )
8 X8 z5 i- y* G- Y - % \7 l* a' r) [; v& j% Q
- /* 信号产生者 *// y( [' \% @$ a6 O
- void Test_Key_Process(void)
" K2 l4 w/ }/ K' \+ x - {. ^4 X5 z& a" v3 u
- static NF_Bool last_q_val = NF_Bool_False;
& H9 J, J1 |' h2 j1 T; n$ ^ - static NF_Bool last_e_val = NF_Bool_False;2 P( p3 N# N, Y, W
' \( b) B- \! f9 h' J' e- NF_Bool then_q_val;- b- ?5 U0 [( E; Z4 g8 a
- NF_Bool then_e_val;" d, H, [1 B+ m- L. V/ {
* c ]. D: m; Y3 A: U q- then_q_val = KEY_VALUE('Q');
7 l% \, c( d; R m) \ - then_e_val = KEY_VALUE('E');
; M. u" {) J# Y( h1 ^/ D - : b) S4 o/ |: w) O; K
- /* Q键事件处理 */5 f! {. u5 {4 j' n' e! ?
- if ((last_q_val == NF_Bool_False) && (KEY_VALUE('Q') == NF_Bool_True))
# W* |# l* K8 a. c# q - {
, b- i/ U. j. R' Y. l v+ a - NF_FSM_Dispatch(&FSM_QandE, NF_FSM_Event("Q_DOWN"));" i. F1 f& u0 G& T7 \4 d, O
- }
, ]; K5 `- K6 g4 G: h - else if ((last_q_val == NF_Bool_True) && (KEY_VALUE('Q') == NF_Bool_False))5 \; u& j4 z# E7 K! Z5 y. r1 b
- {2 S7 r- y+ L/ e
- NF_FSM_Dispatch(&FSM_QandE, NF_FSM_Event("Q_UP"));
) F9 F1 ?$ } `& | - }: u) T5 P6 D' S3 s" s9 M0 ~
# ]9 x- _1 H2 `$ n- /* E键事件处理 */
" E$ t$ M7 B2 o, S; L* ` - if ((last_e_val == NF_Bool_False) && (KEY_VALUE('E') == NF_Bool_True))4 c& l, D# V, `0 ]) f3 b
- {
4 u' v- i- m5 i: t! w5 \' U - NF_FSM_Dispatch(&FSM_QandE, NF_FSM_Event("E_DOWN"));
! k; G5 y! q" r6 X( H - } 0 s$ j$ v% l9 u7 h
- else if ((last_e_val == NF_Bool_True) && (KEY_VALUE('E') == NF_Bool_False))
! @& a& T' {3 g1 y - {
+ Q& k: M6 }3 y( I - NF_FSM_Dispatch(&FSM_QandE, NF_FSM_Event("E_UP"));. e3 |5 {/ a3 Q; w& H
- }
1 s( @- h- x0 o9 j- o# @3 ^
9 e* ]% `& f. J/ ^8 ?1 |2 d8 b- last_q_val = then_q_val;
D, Y) Z% ~7 L _% ^! I6 j6 c5 b - last_e_val = then_e_val;/ Q* c& p4 G Y
- }: F+ T* }; T K' ~
( o# F( `$ j9 P- void IDLE_TO_Q(void)
7 k+ Z0 u. m( ]" d& V5 @7 a5 E - {& F' F4 e" l/ Y
- printf("state translate : IDLE -> Q_DOWN\n");
/ M: N+ W2 V" H+ ^# B1 u5 H - }+ o1 K Q6 H% n. [' w% G4 S. E6 r0 s
- o' J$ m6 M7 c8 r
- void Q_TO_QE(void)
D* c* h3 r; a5 P - {
" B b' P0 t- A! q$ r* g - printf("state translate : Q_DOWN -> QE_DOWN\n");5 p( a, G: C- q8 X, |
- }
8 O* S7 ~$ m$ u. I6 [
* T7 ^: G, k6 ^% F& c8 e& P- void QE_TO_IDLE(void)2 ~ \, F4 x2 k: o1 V
- {7 T: S0 n3 m8 A+ [9 K0 f
- printf("state translate : QE_DOWN -> IDLE\n");
8 D1 N5 [, c. g0 E1 \: ^9 m1 ?' c - }0 l4 s6 h% a0 L2 k
- 2 h9 D# b' R W$ \) z; z2 A3 S9 s
- void QE_TO_Q(void)
2 T% t- b+ n5 Z - {
4 h. W, T" C/ C, U7 ~ - printf("state translate : QE_DOWN -> Q_DOWN\n");
$ V; x j/ t/ G% B - }0 e2 ]" Z3 w) O$ R% D2 r& U
( S; _1 m" x" h' q6 {- void Q_TO_IDLE(void)
/ E" m: a3 H# x& U# x - {$ _0 l) T- p- t
- printf("state translate : Q_DOWN -> IDLE\n");5 h9 }( W5 n+ t* q# H1 k
- }
% @% r9 e$ U, d G" D9 K) ~1 Z
! e' @+ O( T* X \8 @- int main(void); Q+ w" o/ v9 j# V" w ^! V0 R, m
- {4 Y/ c1 l- r4 o) ^4 z, L
- for (;;)
/ k" m8 U8 ^- a$ s+ M/ Q - {
% U* x3 O; `* @9 G$ y - Test_Key_Process();- L$ g2 m2 }1 y- L3 G1 s
- }
& I$ A$ H% F o6 \9 w& F% V - }</font>
复制代码克隆链接: - <font face="微软雅黑" size="3">git clone https://gitee.com/PISCES_X/NorthFrame.git</font>
复制代码 % w( R* e! A$ ]' p2 y5 {2 [3 _- b
. o/ \" c/ p7 J+ x6 s% r |