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

李肖遥

共 5831字,需浏览 12分钟

 ·

2021-08-05 02:20

关注、星标公众号,直达精彩内容

来源:嵌入式云IOT技术圈


NorthFrame是基于非UML极简理念的状态机框架

配合NF_FsmDesigner图形化开发工具,可无负担替代传统switch-case状态机开发

1、NorthFrame的组件

  • NF_FSM :

    极简非UML状态机框架

  • NF_FsmDesigner :

    基于C# Winform开发的状态机图形化开发工具,可直接生成C代码

  • NF_Signal :

    用于代替全局变量的动态信号机制

NF_Signal :代替全局变量,使用方便:

NF_Signal_Set("flag_connect", 1);
NF_Signal_Set("blink_cnt", 3);
NF_SignalValue flag_connect = NF_Signal_Get("flag_connect");

2、NorthFrame图形化状态机开发

以下例程在VS2012环境中运行一个判断QE组合键的状态机:

Step1 : 使用NF_FsmDesigner工具设计绘制状态转换图,并保存为XML文件

Step2 : 点击生成代码,生成如下C语言代码

#include <n_frame.h>
#include <fsm_qande.h>

/* 转换执行的外部函数声明 */
extern void IDLE_TO_Q(void);
extern void Q_TO_QE(void);
extern void QE_TO_IDLE(void);
extern void QE_TO_Q(void);
extern void Q_TO_IDLE(void);

/* 状态处理函数声明 */
void FSM_QandE_IDLE(NF_FSM* me, NF_Event event);
void FSM_QandE_Q_DOWN(NF_FSM* me, NF_Event event);
void FSM_QandE_QE_DOWN(NF_FSM* me, NF_Event event);

/* 状态机对象 */
NF_FSM FSM_QandE = {
    FSM_QandE_IDLE
};

/* IDLE状态处理函数 */
void FSM_QandE_IDLE(NF_FSM* me, NF_Event event)
{

    if (NF_FSM_NameIs(event.Name, "Q_DOWN"))
    {
        IDLE_TO_Q();
        NF_FSM_TRAN(FSM_QandE_Q_DOWN);
        return ;
    }

    if (NF_FSM_NameIs(event.Name, "test"))
    {
        NF_FSM_TRAN(FSM_QandE_IDLE);
        return ;
    }
}

/* Q_DOWN状态处理函数 */
void FSM_QandE_Q_DOWN(NF_FSM* me, NF_Event event)
{

    if (NF_FSM_NameIs(event.Name, "E_DOWN"))
    {
        Q_TO_QE();
        NF_FSM_TRAN(FSM_QandE_QE_DOWN);
        return ;
    }

    if (NF_FSM_NameIs(event.Name, "Q_UP"))
    {
        Q_TO_IDLE();
        NF_FSM_TRAN(FSM_QandE_IDLE);
        return ;
    }
}

/* QE_DOWN状态处理函数 */
void FSM_QandE_QE_DOWN(NF_FSM* me, NF_Event event)
{

    if (NF_FSM_NameIs(event.Name, "Q_UP"))
    {
        QE_TO_IDLE();
        NF_FSM_TRAN(FSM_QandE_IDLE);
        return ;
    }

    if (NF_FSM_NameIs(event.Name, "E_UP"))
    {
        QE_TO_Q();
        NF_FSM_TRAN(FSM_QandE_Q_DOWN);
        return ;
    }
}

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

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

#include "n_frame.h"

#include "windows.h"
#include "stdio.h"

#include "fsm_qande.h"

#define KEY_VALUE(_key) ((GetKeyState(_key) >= 0) ? NF_Bool_False : NF_Bool_True )

/* 信号产生者 */
void Test_Key_Process(void)
{
 static NF_Bool last_q_val = NF_Bool_False;
 static NF_Bool last_e_val = NF_Bool_False;

 NF_Bool then_q_val;
 NF_Bool then_e_val;

 then_q_val = KEY_VALUE('Q');
 then_e_val = KEY_VALUE('E');

 /* Q键事件处理 */
 if ((last_q_val == NF_Bool_False) && (KEY_VALUE('Q') == NF_Bool_True))
 {
  NF_FSM_Dispatch(&FSM_QandE, NF_FSM_Event("Q_DOWN"));
 } 
 else if ((last_q_val == NF_Bool_True) && (KEY_VALUE('Q') == NF_Bool_False))
 {
  NF_FSM_Dispatch(&FSM_QandE, NF_FSM_Event("Q_UP"));
 }

 /* E键事件处理 */
 if ((last_e_val == NF_Bool_False) && (KEY_VALUE('E') == NF_Bool_True))
 {
  NF_FSM_Dispatch(&FSM_QandE, NF_FSM_Event("E_DOWN"));
 } 
 else if ((last_e_val == NF_Bool_True) && (KEY_VALUE('E') == NF_Bool_False))
 {
  NF_FSM_Dispatch(&FSM_QandE, NF_FSM_Event("E_UP"));
 }

 last_q_val = then_q_val;
 last_e_val = then_e_val;
}

void IDLE_TO_Q(void)
{
 printf("state translate : IDLE -> Q_DOWN\n");
}

void Q_TO_QE(void)
{
 printf("state translate : Q_DOWN -> QE_DOWN\n");
}

void QE_TO_IDLE(void)
{
 printf("state translate : QE_DOWN -> IDLE\n");
}

void QE_TO_Q(void)
{
 printf("state translate : QE_DOWN -> Q_DOWN\n");
}

void Q_TO_IDLE(void)
{
 printf("state translate : Q_DOWN -> IDLE\n");
}

int main(void)
{
 for (;;)
 {
  Test_Key_Process();
 }
}

克隆链接:

git clone https://gitee.com/PISCES_X/NorthFrame.git

版权归原作者所有,如有侵权,请联系删除。
‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧  END  ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧

关注我的微信公众号,回复“加群”按规则加入技术交流群。

欢迎关注我的视频号:


点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。

浏览 32
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报