# NorthFrame **Repository Path**: OriginLife/NorthFrame ## Basic Information - **Project Name**: NorthFrame - **Description**: NorthFrame 单片机极简图形化状态机框架 讨论QQ群:431600056 - **Primary Language**: C - **License**: AGPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 105 - **Created**: 2020-10-19 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # NorthFrame 单片机极简图形化状态机框架 # 讨论QQ群:431600056 NorthFrame是基于非UML极简理念的状态机框架 配合NF_FsmDesigner图形化开发工具,可无负担替代传统switch-case状态机开发

### 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"); ```
### 图形化状态机开发 以下例程在VS2012环境中运行一个判断QE组合键的状态机
Step1 : 使用NF_FsmDesigner工具设计绘制状态转换图,并保存为XML文件 ![QandE_FSM](/NF_FsmDesignerDemo.jpg) Step2 : 点击生成代码,生成如下C语言代码 ``` #include #include /* 转换执行的外部函数声明 */ 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(); } } ```