搜索
bottom↓
回复: 45

[开源框架]极简信号/状态机框架 NorthFrame

  [复制链接]

出0入0汤圆

发表于 2020-2-25 13:00:42 | 显示全部楼层 |阅读模式
本帖最后由 独孤帅 于 2020-2-25 13:03 编辑

NorthFrame 单片机极简信号/状态机框架
讨论QQ群:431600056


gitee地址:https://gitee.com/PISCES_X/NorthFrame

单片机开发中是否被满天飞的全局变量困扰?
是否在寻找一种层级间松耦合的信号传递方式?
是否希望优雅无负担地使用状态机思路进行开发?
调试打Log很麻烦,希望自动生成,最好还有测试脚本?

NF_Signal和NF_FSM 来帮你

用法1:代替全局变量,使用方便
  1. NF_Signal_Set("flag_connect", 1);
  2. NF_Signal_Set("blink_cnt", 3);

  3. NF_SignalValue flag_connect = NF_Signal_Get("flag_connect");
复制代码


用法2:配合状态机使用

以下例程在VS2012环境中运行一个判断QE组合键的状态机
注:未来会更新使用状态图绘图软件自动生成状态机代码 QandE_FSM



  1. #include "n_frame.h"

  2. #include "windows.h"
  3. #include "stdio.h"

  4. #define IS_KEY_PRESS(_key) ((GetKeyState(_key) >= 0) ? NF_Bool_False : NF_Bool_True )

  5. /* 信号产生者 */
  6. void Test_Key_Process(void)
  7. {
  8.         if ( IS_KEY_PRESS('Q') ){
  9.                 NF_Signal_Set("key_q_press", 1);
  10.         }
  11.         else{
  12.                 NF_Signal_Set("key_q_press", 0);
  13.         }

  14.         if ( IS_KEY_PRESS('E') ){
  15.                 NF_Signal_Set("key_e_press", 1);
  16.         }
  17.         else{
  18.                 NF_Signal_Set("key_e_press", 0);
  19.         }
  20. }

  21. /* 状态机对象 */
  22. NF_FSM Test_FSM_QandE;

  23. /* 状态机的三个状态处理函数 */
  24. void Test_FSM_QandE_IDLE(NF_FSM* me, NF_SignalName name, NF_SignalValue val);
  25. void Test_FSM_QandE_QDOWN(NF_FSM* me, NF_SignalName name, NF_SignalValue val);
  26. void Test_FSM_QandE_QEDOWN(NF_FSM* me, NF_SignalName name, NF_SignalValue val);

  27. /* IDLE状态处理函数 */
  28. void Test_FSM_QandE_IDLE(NF_FSM* me, NF_SignalName name, NF_SignalValue val)
  29. {
  30.         if ( NF_FSM_NameIs(name, "key_q_press") )
  31.         {
  32.                 if ( val == 1 )
  33.                 {
  34.                         NF_FSM_TRAN(Test_FSM_QandE_QDOWN);
  35.                         printf("Test_FSM_QandE State Translate : IDLE --> QDOWN\n");
  36.                 }
  37.         }
  38. }

  39. /* QDOWN状态处理函数 */
  40. void Test_FSM_QandE_QDOWN(NF_FSM* me, NF_SignalName name, NF_SignalValue val)
  41. {
  42.         if ( NF_FSM_NameIs(name, "key_e_press") )
  43.         {
  44.                 if ( val == 1 )
  45.                 {
  46.                         NF_FSM_TRAN(Test_FSM_QandE_QEDOWN);
  47.                         printf("Test_FSM_QandE State Translate : QDOWN --> QEDOWN\n");
  48.                 }
  49.         }
  50.         else if( NF_FSM_NameIs(name, "key_q_press") )
  51.         {
  52.                 if ( val == 0 )
  53.                 {
  54.                         NF_FSM_TRAN(Test_FSM_QandE_IDLE);
  55.                         printf("Test_FSM_QandE State Translate : QDOWN --> IDLE\n");
  56.                 }
  57.         }
  58. }

  59. /* QEDOWN状态处理函数 */
  60. void Test_FSM_QandE_QEDOWN(NF_FSM* me, NF_SignalName name, NF_SignalValue val)
  61. {
  62.         if ( NF_FSM_NameIs(name, "key_e_press") )
  63.         {
  64.                 if ( val == 0 )
  65.                 {
  66.                         NF_FSM_TRAN(Test_FSM_QandE_QDOWN);
  67.                         printf("Test_FSM_QandE State Translate : QEDOWN --> QDOWN\n");
  68.                 }
  69.         }
  70.         else if( NF_FSM_NameIs(name, "key_q_press") )
  71.         {
  72.                 if ( val == 0 )
  73.                 {
  74.                         NF_FSM_TRAN(Test_FSM_QandE_IDLE);
  75.                         printf("Test_FSM_QandE State Translate : QEDOWN --> IDLE\n");
  76.                 }
  77.         }
  78. }

  79. int main(void)
  80. {
  81.         /* 初始化状态机 */
  82.         NF_FSM_Translate(&Test_FSM_QandE, NF_FSM_State(Test_FSM_QandE_IDLE));

  83.         for (;;)
  84.         {
  85.                 Test_Key_Process();
  86.                 NF_FSM_CheckSignal(&Test_FSM_QandE, "key_q_press");
  87.                 NF_FSM_CheckSignal(&Test_FSM_QandE, "key_e_press");
  88.         }
  89. }
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

如果想吃一顿饺子,就得从冰箱里取出肉,剁馅儿,倒面粉、揉面、醒面,擀成皮儿,下锅……
一整个繁琐流程,就是为了出锅时那一嘴滚烫流油的热饺子。

如果这个过程,禁不住饿,零食下肚了,饺子出锅时也就不香了……《非诚勿扰3》

出0入0汤圆

发表于 2020-2-25 13:04:13 | 显示全部楼层
跟定义结构体相比
有啥好处

出0入0汤圆

 楼主| 发表于 2020-2-25 13:08:46 | 显示全部楼层
qq335702318 发表于 2020-2-25 13:04
跟定义结构体相比
有啥好处

1、框架是对状态机思想的封装,字面意思更规范 程序流程 --> 与状态转换图一一对应
2、信号、状态机由框架管理,对于log调试和脚本测试更方便,不需要手动log
3、由于代码字面与状态图一一对应,可以使用绘图软件自动生成代码
4、本框架采用极简设计,可以只使用信号代替全局变量,也可以全面采用,花费很小的代价就可以规范程序思路
5、从本人实际项目角度出发,赶工的、传承的代码使用这个框架配合代码规范、管理制度,可以解决大部分代码乱套问题

出0入0汤圆

发表于 2020-2-25 13:13:54 | 显示全部楼层
用了你这个反而更复杂了 增加空间使用量 增加运算成本 使用变量的使用还需要去维护变量表 没什么意义啊 还要很多宏 一点脱裤子放屁的感觉

出0入10汤圆

发表于 2020-2-25 13:16:24 | 显示全部楼层
没发现有啥好处  lz解释下吧

出0入0汤圆

 楼主| 发表于 2020-2-25 13:28:44 | 显示全部楼层
凌海滨 发表于 2020-2-25 13:13
用了你这个反而更复杂了 增加空间使用量 增加运算成本 使用变量的使用还需要去维护变量表 没什么意义啊 还 ...


这位朋友点评得很到位,功能上来说是没有任何作用的,还会增加一定运行时间
但这个框架的主要作用是:规范代码风格、结构

它是类似《C语言编程规范》这种规范的延伸版,
除了在命名、结构、思路上解决问题外,额外花费一些运行时间让结构更清晰、避免代码问题
我给它的定位:语法糖

这个框架是我从生产环境中总结出来的,旨在解决赶工、传承代码的逻辑混乱问题
生产环境下使用,STM32F1 O(n)复杂度的信号访问时间是个位数的us量级
O(1)就不用说了,仅多了函数调用

出20入62汤圆

发表于 2020-2-25 13:45:35 | 显示全部楼层
支持下楼主~
但很多时候是这样的~
不懂的人啊不敢用~
懂的人呢自己写~

出0入0汤圆

发表于 2020-2-25 17:21:52 | 显示全部楼层
说到语法糖,想到了傻孩子的教程,他的状态机框架是面向对象的记得。

出0入0汤圆

 楼主| 发表于 2020-2-25 17:30:46 | 显示全部楼层
lhaoyue 发表于 2020-2-25 17:21
说到语法糖,想到了傻孩子的教程,他的状态机框架是面向对象的记得。

我这个框架也是啊

出0入0汤圆

发表于 2020-2-26 08:42:05 | 显示全部楼层
凌海滨 发表于 2020-2-25 13:13
用了你这个反而更复杂了 增加空间使用量 增加运算成本 使用变量的使用还需要去维护变量表 没什么意义啊 还 ...

虽然楼主的代码会增加运行时间,降低效率,增加ROM
但规范化是要看应用场景的
至少你用2K ROM的片子和H7的片子
编程方法就肯定不一样

出0入0汤圆

发表于 2020-2-26 08:54:16 | 显示全部楼层
qq335702318 发表于 2020-2-26 08:42
虽然楼主的代码会增加运行时间,降低效率,增加ROM
但规范化是要看应用场景的
至少你用2K ROM的片子和H7 ...

代码规范 可以有各种方法 虽然看应用场景 但是为了代码规范就舍弃了性能和效率的 是不可取的 不是cpu主频该 ROM大就可以肆无忌惮的 国内的android就是这样 一个app臃肿的很 硬件怎么升都跟不上

出0入0汤圆

发表于 2020-2-26 09:04:15 | 显示全部楼层
凌海滨 发表于 2020-2-26 08:54
代码规范 可以有各种方法 虽然看应用场景 但是为了代码规范就舍弃了性能和效率的 是不可取的 不是cpu主频 ...

我觉得这是别人的商业套路
软件给硬件一条活路
硬件软件互相迭代持续发展
让这个平台下的软件开发不要太难

出0入20汤圆

发表于 2020-2-26 15:58:15 | 显示全部楼层
支持LZ
程序是写给人看的, 而不是写给机器看的.
任何追求极致效率和代码容量的行为本质上是一种工程技巧,是在hack编译器,既然这样,我一句都不如汇编不就完了(而且一般人写的汇编未必有编译器输出的好)
如果因为成本或者其他追求,去修炼这种技巧本身没有问题,但是这不应该是一种编程思想,也不值得推荐.

出50入255汤圆

发表于 2020-2-26 16:09:49 | 显示全部楼层
-----------------------------------------------------------------------------------------------------------------
这个框架是我从生产环境中总结出来的,旨在解决赶工、传承代码的逻辑混乱问题
生产环境下使用,STM32F1 O(n)复杂度的信号访问时间是个位数的us量级
O(1)就不用说了,仅多了函数调用
-----------------------------------------------------------------------------------------------------------------
这个就是关键了。
如果您的程序复杂度低, 用了这个反而麻烦。
但如果复杂度提高,普通方式可能是指数级增加的麻烦,而用了状态机框架只是线性增加。
这个就是状态机框架的意义。

出40入42汤圆

发表于 2020-2-26 17:22:14 | 显示全部楼层
软件还是为了给应用服务的,好的框架只是能满足多种应用需求,或是非常契合某种应用需求,并不绝对
代码框架也是差不多,满足需求就是好的

出0入0汤圆

发表于 2020-2-26 18:58:20 | 显示全部楼层
楼主自己用它在什么MCU上呀?是因为片上资源不够吗?

出0入4汤圆

发表于 2020-2-26 19:23:02 | 显示全部楼层
请问code size多大?qpc/qfn 框架值得拥有

出0入0汤圆

发表于 2020-2-26 21:33:56 来自手机 | 显示全部楼层
我就看看。

出0入0汤圆

发表于 2020-2-26 22:09:45 | 显示全部楼层
学习一下

出0入0汤圆

发表于 2020-2-26 23:45:37 来自手机 | 显示全部楼层
支持楼主,有耐心

出0入8汤圆

发表于 2020-2-27 08:45:46 | 显示全部楼层
xy-mcu 发表于 2020-2-26 16:09
---------------------------------------------------------------------------------------------------- ...

这个确实是关键。

另外,我觉得单片机的全局变量,用 static 限制就好了,回归本质,
通过名字来创建、设置、销毁,代码不直观、且牺牲了码字速度。

出0入0汤圆

发表于 2020-2-27 08:51:54 | 显示全部楼层
独孤帅 发表于 2020-2-25 13:08
1、框架是对状态机思想的封装,字面意思更规范 程序流程 --> 与状态转换图一一对应
2、信号、状态机由框 ...

感谢楼主分享。

出4375入62汤圆

发表于 2020-2-27 10:13:57 | 显示全部楼层
谢谢楼主分享

出4375入62汤圆

发表于 2020-2-27 11:42:29 | 显示全部楼层
styleno1 发表于 2020-2-26 18:58
楼主自己用它在什么MCU上呀?是因为片上资源不够吗?

是因为片上资源足够  

出0入0汤圆

发表于 2020-2-27 12:11:11 | 显示全部楼层
supercoo 发表于 2020-2-27 11:42
是因为片上资源足够

我想问:楼主写这个框架的是不是因为MCU资源不足(以跑轻量级的OS)?括号里内容省了。你是有用楼主这个吗?

出0入119汤圆

发表于 2020-2-27 12:21:57 | 显示全部楼层
学习一下~

出4375入62汤圆

发表于 2020-2-27 12:22:57 | 显示全部楼层
styleno1 发表于 2020-2-27 12:11
我想问:楼主写这个框架的是不是因为MCU资源不足(以跑轻量级的OS)?括号里内容省了。你是有用楼主这个 ...

我没用过

楼主应该主要是规范代码格式,益于维护

出105入79汤圆

发表于 2020-2-27 12:30:33 | 显示全部楼层
GPL协议,用了你的代码,整个程序就要开源了

出0入0汤圆

发表于 2020-2-27 12:31:47 | 显示全部楼层
supercoo 发表于 2020-2-27 12:22
我没用过

楼主应该主要是规范代码格式,益于维护

个人认为,对于事件驱动状态机,主要局部(状态处理函数内)易于维护,如果不画状态图,稍复杂的状态转换可读性就比较差了。已知的FSM/HSM框架基本上由上位机生成代码。

出4375入62汤圆

发表于 2020-2-27 13:38:24 | 显示全部楼层
styleno1 发表于 2020-2-27 12:31
个人认为,对于事件驱动状态机,主要局部(状态处理函数内)易于维护,如果不画状态图,稍复杂的状态转换 ...

嗯  有道理

出0入0汤圆

 楼主| 发表于 2020-2-27 14:48:59 | 显示全部楼层
cnshibo 发表于 2020-2-26 19:23
请问code size多大?qpc/qfn 框架值得拥有

我的定位:极简接口
看一眼DEMO就会用,是这个框架存在的意义

在我目前环境中,QP是不能直接使用的,会被否掉

出0入0汤圆

 楼主| 发表于 2020-2-27 14:49:59 | 显示全部楼层
styleno1 发表于 2020-2-27 12:31
个人认为,对于事件驱动状态机,主要局部(状态处理函数内)易于维护,如果不画状态图,稍复杂的状态转换 ...

后续版本会更新极简状态机绘图软件,状态转换图直接生成代码

出0入0汤圆

 楼主| 发表于 2020-2-27 14:50:28 | 显示全部楼层
styleno1 发表于 2020-2-27 12:11
我想问:楼主写这个框架的是不是因为MCU资源不足(以跑轻量级的OS)?括号里内容省了。你是有用楼主这个 ...

主要是领导不想听复杂的

出0入0汤圆

 楼主| 发表于 2020-2-27 14:51:11 | 显示全部楼层
security 发表于 2020-2-27 08:45
这个确实是关键。

另外,我觉得单片机的全局变量,用 static 限制就好了,回归本质,

一个一天被产品经理催三遍的赶工开发者是不会做这些的

出0入0汤圆

 楼主| 发表于 2020-3-23 14:24:48 | 显示全部楼层
捞一捞

出0入4汤圆

发表于 2020-3-23 16:21:21 | 显示全部楼层
你这个有点类似于QP状态机

出0入0汤圆

发表于 2020-3-24 09:56:44 | 显示全部楼层
你这个协议是GPL3.0?那能用你这个框架的项目还不如用QP框架。

出0入0汤圆

发表于 2020-8-22 21:25:57 | 显示全部楼层
尝试下用在4G模块的操作中

出0入8汤圆

发表于 2020-8-22 22:42:55 | 显示全部楼层
一说到框架,还是RTOS省心

出0入0汤圆

发表于 2021-4-7 13:01:21 | 显示全部楼层
NorthFrame 楼主还在更新吗

出0入0汤圆

发表于 2021-4-7 20:43:31 | 显示全部楼层
NorthFrame 楼主还在更新吗

出0入0汤圆

发表于 2021-7-2 12:54:37 来自手机 | 显示全部楼层
NorthFrame 楼主还在更新吗

出0入0汤圆

 楼主| 发表于 2021-10-21 15:40:52 | 显示全部楼层
统一回答楼上各位,最近公司采用,会有一次迭代

出0入0汤圆

发表于 2021-10-21 17:32:00 | 显示全部楼层
感谢楼主分享,学习一下楼主的思路

出0入0汤圆

发表于 2021-10-22 08:40:11 | 显示全部楼层
感谢楼主分享

出0入0汤圆

发表于 2021-10-22 08:49:33 | 显示全部楼层
能提供一个OS功能,代码内 延时函数,
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-29 00:34

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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