你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

基于单片机的极简图形化状态机框架NorthFrame

[复制链接]
STMCU小助手 发布时间:2021-8-5 10:15
NorthFrame是基于非UML极简理念的状态机框架
; M2 Y* X* v6 {9 J+ Y) Y( [. p
3 G5 W: j' B4 u- o
9 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
  1. <font face="微软雅黑" size="3">NF_Signal_Set("flag_connect", 1);" o! o' g  q+ b! G4 E
  2. ( |4 T$ L  T# ^( {
  3. NF_Signal_Set("blink_cnt", 3);8 |" T* l! j0 `4 R# c& k+ j
  4. 1 q3 m3 b) F0 E% y! B
  5. 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( T
2 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
1.png 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
  1. <font face="微软雅黑" size="3">#include <n_frame.h>
    5 {/ a+ s; `- Q
  2. #include <fsm_qande.h>
    ! t/ o% U$ k. ^/ [* e. n$ b/ d0 S

  3. 6 X; ]- b/ B3 o
  4. /* 转换执行的外部函数声明 */. L' F$ ^1 o* z( J
  5. extern void IDLE_TO_Q(void);
    5 B+ [3 k6 z% ~6 L" p* }
  6. extern void Q_TO_QE(void);
    4 y: ^" E( F% Z; P
  7. extern void QE_TO_IDLE(void);- r3 P$ P) M% D
  8. extern void QE_TO_Q(void);) d9 I! V# P  b7 q- Z5 S$ b
  9. extern void Q_TO_IDLE(void);9 G0 @" D7 }% H- D6 W. \

  10. 4 V6 w. A3 e; K8 Z
  11. /* 状态处理函数声明 */
    ) g7 P5 Z  A) k8 M6 o  K) ^# D0 r
  12. void FSM_QandE_IDLE(NF_FSM* me, NF_Event event);
    ! \: k+ |- T  b
  13. void FSM_QandE_Q_DOWN(NF_FSM* me, NF_Event event);
    7 U- Z7 z- ]$ P8 ~8 R4 R* C
  14. void FSM_QandE_QE_DOWN(NF_FSM* me, NF_Event event);6 C, v( p/ C5 Y+ P0 M' p7 I+ R
  15. 7 w/ K! x6 D. r9 X1 s% x
  16. /* 状态机对象 */% S' ~$ P5 q: @2 I
  17. NF_FSM FSM_QandE = {
    7 B, C' c" Y7 X! |3 ~' j
  18.     FSM_QandE_IDLE$ ^$ ?8 G  R# L& e* X
  19. };) V- D- e5 x& p
  20. % m. H' W9 v, s, O
  21. /* IDLE状态处理函数 */
    # B( e! _- C& b1 K3 g$ D
  22. void FSM_QandE_IDLE(NF_FSM* me, NF_Event event)- ~- R& Q; R5 j* ?0 D: e9 z
  23. {
    $ M1 t3 F9 ?3 u5 g$ V
  24. & M7 @8 I/ g$ W0 d
  25.     if (NF_FSM_NameIs(event.Name, "Q_DOWN"))" X: O! t- @: y# x2 m& @3 ?
  26.     {' d0 w2 j# Y% r/ E) Y( g& y
  27.         IDLE_TO_Q();
    % b/ z1 ], U4 m- Y' U4 s
  28.         NF_FSM_TRAN(FSM_QandE_Q_DOWN);( l! W8 h6 D6 e1 w0 d
  29.         return ;
    / T- _1 U+ l7 j% S& ^
  30.     }
    . e& D0 k" s& m) `

  31. # q6 {. C- i' p& ]
  32.     if (NF_FSM_NameIs(event.Name, "test"))0 v- }- @, G+ w7 q5 X; H
  33.     {
    & o" Z$ s0 E# _; B1 ]" i% }
  34.         NF_FSM_TRAN(FSM_QandE_IDLE);
    ; O1 A; C; S9 E! O% m4 R
  35.         return ;4 h7 `$ P" E* C1 x
  36.     }. V; f' w; O' l( f
  37. }
    0 I! y! S6 @2 D- S7 F3 V& r9 p

  38. # B1 N  F" |* b; p; l% \% W3 H# ~; F
  39. /* Q_DOWN状态处理函数 */
    ' u1 K( E3 r$ N# U5 a. R5 F2 |9 o
  40. void FSM_QandE_Q_DOWN(NF_FSM* me, NF_Event event)
    % @$ X4 U1 ]+ `: x
  41. {
    ( |$ a+ ^# c: P

  42. , ?4 s/ y( o% y( j0 P8 k% W, X: R
  43.     if (NF_FSM_NameIs(event.Name, "E_DOWN"))/ f# z( G7 ?/ @0 x0 z3 E
  44.     {6 Z! A7 s* A) H/ g, @& V
  45.         Q_TO_QE();
    6 H1 ~" [0 p) h* d7 y( J  F0 g% M  @
  46.         NF_FSM_TRAN(FSM_QandE_QE_DOWN);! h4 O9 ]( }1 c8 f4 s
  47.         return ;+ b0 G  q' ^: `, [
  48.     }/ M) B$ ]8 h+ V, f

  49. / ^! a9 Q, U4 V. K. x! J7 F, y
  50.     if (NF_FSM_NameIs(event.Name, "Q_UP"))
    + C, G# T) e5 W7 c4 |
  51.     {
    ; i! d/ i5 X% B! |( j6 p% X
  52.         Q_TO_IDLE();; e# P8 I- M9 y
  53.         NF_FSM_TRAN(FSM_QandE_IDLE);
    . P  ^) Z; G" Z3 K6 ^3 |) |1 `
  54.         return ;
    7 A+ P" g- G+ [5 m6 d
  55.     }0 Q) D7 o& u1 S8 f6 X7 d( ^% m
  56. }
    2 e3 i% w0 \6 G

  57. 6 M# a+ H3 l! w& G$ `
  58. /* QE_DOWN状态处理函数 */; ?9 }0 L( J5 |* q% p% [
  59. void FSM_QandE_QE_DOWN(NF_FSM* me, NF_Event event)
    - e( T' s5 [+ r7 p" f5 F
  60. {# r9 S9 z$ e1 J) H8 V1 [! g: J

  61. # h6 ^2 t( e' w, [& x+ S( g
  62.     if (NF_FSM_NameIs(event.Name, "Q_UP"))2 e) S" S/ Q, o% g9 Z0 y) e. S
  63.     {
    # \! |8 m1 L8 a6 D( w. U; Z
  64.         QE_TO_IDLE();
    ! u# A, I# T  I! A; Y
  65.         NF_FSM_TRAN(FSM_QandE_IDLE);
    9 D' d; `& U, k; u
  66.         return ;* q$ H6 Y& j  U/ u
  67.     }
    6 U: H* }1 b3 X
  68. " G5 P3 v% c' }, U
  69.     if (NF_FSM_NameIs(event.Name, "E_UP"))/ ~$ x8 _" R3 H, z. }
  70.     {
    9 B* d, F# R" F
  71.         QE_TO_Q();
    3 h/ y9 l- G3 t( B, J5 ~! J; f
  72.         NF_FSM_TRAN(FSM_QandE_Q_DOWN);
    . D2 K& \% X9 C" j0 p
  73.         return ;6 K" X4 i8 ~; v+ H$ ?: D7 _( f
  74.     }
    5 L' q, @4 x) k- B% `& @) X
  75. }</font>
复制代码

Step3 : 在main.c文件中实现按键处理,并发送事件给状态机

备注 : 后续版本会加入发布-订阅机制,目前仅支持直接派发

  1. <font face="微软雅黑" size="3">#include "n_frame.h"" I1 Y- I5 h" w
  2. ( \6 `  |2 u) y3 a; V* m$ ?
  3. #include "windows.h"
    7 L$ e/ H6 C6 I, ^# r
  4. #include "stdio.h"
    9 k- x7 F/ E4 V- L
  5. ) Y3 E& z0 V% Q' W0 y) c
  6. #include "fsm_qande.h"
    ! q! t' e1 k, c7 ?
  7. 2 r# ]" C! @2 i& u
  8. #define KEY_VALUE(_key) ((GetKeyState(_key) >= 0) ? NF_Bool_False : NF_Bool_True )
    8 X8 z5 i- y* G- Y
  9. % \7 l* a' r) [; v& j% Q
  10. /* 信号产生者 *// y( [' \% @$ a6 O
  11. void Test_Key_Process(void)
    " K2 l4 w/ }/ K' \+ x
  12. {. ^4 X5 z& a" v3 u
  13. static NF_Bool last_q_val = NF_Bool_False;
    & H9 J, J1 |' h2 j1 T; n$ ^
  14. static NF_Bool last_e_val = NF_Bool_False;2 P( p3 N# N, Y, W

  15. ' \( b) B- \! f9 h' J' e
  16. NF_Bool then_q_val;- b- ?5 U0 [( E; Z4 g8 a
  17. NF_Bool then_e_val;" d, H, [1 B+ m- L. V/ {

  18. * c  ]. D: m; Y3 A: U  q
  19. then_q_val = KEY_VALUE('Q');
    7 l% \, c( d; R  m) \
  20. then_e_val = KEY_VALUE('E');
    ; M. u" {) J# Y( h1 ^/ D
  21. : b) S4 o/ |: w) O; K
  22. /* Q键事件处理 */5 f! {. u5 {4 j' n' e! ?
  23. if ((last_q_val == NF_Bool_False) && (KEY_VALUE('Q') == NF_Bool_True))
    # W* |# l* K8 a. c# q
  24. {
    , b- i/ U. j. R' Y. l  v+ a
  25.   NF_FSM_Dispatch(&FSM_QandE, NF_FSM_Event("Q_DOWN"));" i. F1 f& u0 G& T7 \4 d, O
  26. }
    , ]; K5 `- K6 g4 G: h
  27. else if ((last_q_val == NF_Bool_True) && (KEY_VALUE('Q') == NF_Bool_False))5 \; u& j4 z# E7 K! Z5 y. r1 b
  28. {2 S7 r- y+ L/ e
  29.   NF_FSM_Dispatch(&FSM_QandE, NF_FSM_Event("Q_UP"));
    ) F9 F1 ?$ }  `& |
  30. }: u) T5 P6 D' S3 s" s9 M0 ~

  31. # ]9 x- _1 H2 `$ n
  32. /* E键事件处理 */
    " E$ t$ M7 B2 o, S; L* `
  33. if ((last_e_val == NF_Bool_False) && (KEY_VALUE('E') == NF_Bool_True))4 c& l, D# V, `0 ]) f3 b
  34. {
    4 u' v- i- m5 i: t! w5 \' U
  35.   NF_FSM_Dispatch(&FSM_QandE, NF_FSM_Event("E_DOWN"));
    ! k; G5 y! q" r6 X( H
  36. } 0 s$ j$ v% l9 u7 h
  37. else if ((last_e_val == NF_Bool_True) && (KEY_VALUE('E') == NF_Bool_False))
    ! @& a& T' {3 g1 y
  38. {
    + Q& k: M6 }3 y( I
  39.   NF_FSM_Dispatch(&FSM_QandE, NF_FSM_Event("E_UP"));. e3 |5 {/ a3 Q; w& H
  40. }
    1 s( @- h- x0 o9 j- o# @3 ^

  41. 9 e* ]% `& f. J/ ^8 ?1 |2 d8 b
  42. last_q_val = then_q_val;
      D, Y) Z% ~7 L  _% ^! I6 j6 c5 b
  43. last_e_val = then_e_val;/ Q* c& p4 G  Y
  44. }: F+ T* }; T  K' ~

  45. ( o# F( `$ j9 P
  46. void IDLE_TO_Q(void)
    7 k+ Z0 u. m( ]" d& V5 @7 a5 E
  47. {& F' F4 e" l/ Y
  48. printf("state translate : IDLE -> Q_DOWN\n");
    / M: N+ W2 V" H+ ^# B1 u5 H
  49. }+ o1 K  Q6 H% n. [' w% G4 S. E6 r0 s
  50.   o' J$ m6 M7 c8 r
  51. void Q_TO_QE(void)
      D* c* h3 r; a5 P
  52. {
    " B  b' P0 t- A! q$ r* g
  53. printf("state translate : Q_DOWN -> QE_DOWN\n");5 p( a, G: C- q8 X, |
  54. }
    8 O* S7 ~$ m$ u. I6 [

  55. * T7 ^: G, k6 ^% F& c8 e& P
  56. void QE_TO_IDLE(void)2 ~  \, F4 x2 k: o1 V
  57. {7 T: S0 n3 m8 A+ [9 K0 f
  58. printf("state translate : QE_DOWN -> IDLE\n");
    8 D1 N5 [, c. g0 E1 \: ^9 m1 ?' c
  59. }0 l4 s6 h% a0 L2 k
  60. 2 h9 D# b' R  W$ \) z; z2 A3 S9 s
  61. void QE_TO_Q(void)
    2 T% t- b+ n5 Z
  62. {
    4 h. W, T" C/ C, U7 ~
  63. printf("state translate : QE_DOWN -> Q_DOWN\n");
    $ V; x  j/ t/ G% B
  64. }0 e2 ]" Z3 w) O$ R% D2 r& U

  65. ( S; _1 m" x" h' q6 {
  66. void Q_TO_IDLE(void)
    / E" m: a3 H# x& U# x
  67. {$ _0 l) T- p- t
  68. printf("state translate : Q_DOWN -> IDLE\n");5 h9 }( W5 n+ t* q# H1 k
  69. }
    % @% r9 e$ U, d  G" D9 K) ~1 Z

  70. ! e' @+ O( T* X  \8 @
  71. int main(void); Q+ w" o/ v9 j# V" w  ^! V0 R, m
  72. {4 Y/ c1 l- r4 o) ^4 z, L
  73. for (;;)
    / k" m8 U8 ^- a$ s+ M/ Q
  74. {
    % U* x3 O; `* @9 G$ y
  75.   Test_Key_Process();- L$ g2 m2 }1 y- L3 G1 s
  76. }
    & I$ A$ H% F  o6 \9 w& F% V
  77. }</font>
复制代码

克隆链接:

  1. <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
赞 收藏 评论0 发布时间:2021-8-5 10:15

举报

0个回答

所属标签

相似技术帖

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版