搜索
bottom↓
回复: 82

开源最简状态机框架

  [复制链接]

出0入89汤圆

发表于 2016-5-1 22:24:08 | 显示全部楼层 |阅读模式
我们写状态机时,其实还是很烦的,我觉得PT在这个方面是最直观的,但在一些特定领域并不合适。QP也是大家比较推崇的,但是感觉有点大(至少我觉得),刚好逛github碰到一个叫SM的库,据说是模仿QP的,看起来感觉不错,就改写了一点,我在windows下写了个demo,我觉得在arm下也应该是一样的,大家不妨一起探讨,研究!

本帖子中包含更多资源

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

x

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

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入89汤圆

 楼主| 发表于 2016-5-1 22:27:03 | 显示全部楼层
原作者地址
https://github.com/leijian001/sm
源码

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2016-5-1 22:44:45 | 显示全部楼层
Mark,有讲解就更好了

出0入89汤圆

 楼主| 发表于 2016-5-1 22:49:42 | 显示全部楼层
负西弱 发表于 2016-5-1 22:44
Mark,有讲解就更好了

我改写的那个非常简单,就几行代码(ssm.c),觉得有问题,可以直接提问。我们一起探讨。

出0入0汤圆

发表于 2016-5-1 22:58:16 | 显示全部楼层
mark 一下 状态机

出0入89汤圆

 楼主| 发表于 2016-5-1 23:05:52 | 显示全部楼层
maimaige 发表于 2016-5-1 22:58
mark 一下 状态机

光mark不行啊,如果能一起探讨就最好了 压缩包里面包含一个demo和可执行文件,可以非常容易测试。我过几天再写一个简单的arm测试例子。

出0入0汤圆

发表于 2016-5-1 23:12:16 | 显示全部楼层
youkebing 发表于 2016-5-1 23:05
光mark不行啊,如果能一起探讨就最好了 压缩包里面包含一个demo和可执行文件,可以非常容易测试。 ...

好啊,我还想找人指导一下,消息处理,协议处理的,框架呢,一般是串口方面的控制协议

出0入89汤圆

 楼主| 发表于 2016-5-1 23:19:41 来自手机 | 显示全部楼层
maimaige 发表于 2016-5-1 23:12
好啊,我还想找人指导一下,消息处理,协议处理的,框架呢,一般是串口方面的控制协议 ...

指导谈不上,大家起探讨

出0入0汤圆

发表于 2016-5-2 00:29:26 来自手机 | 显示全部楼层
先收下,谢谢!

出0入0汤圆

发表于 2016-5-2 10:44:16 来自手机 | 显示全部楼层
晚上下来研究下

出0入0汤圆

发表于 2016-5-2 10:48:11 | 显示全部楼层
先了解一下再问

出0入89汤圆

 楼主| 发表于 2016-5-2 14:55:31 | 显示全部楼层
大家可以先想一些场景,我来按照这个场景写一些简单demo,当然要比较简单,有一定的代表性。或者用其他模式写起来不太顺手的。

出0入0汤圆

发表于 2016-5-2 15:17:59 | 显示全部楼层
收藏了,谢谢。

出60入0汤圆

发表于 2016-5-2 17:20:52 | 显示全部楼层
定时器超时消息如何处理?

出0入89汤圆

 楼主| 发表于 2016-5-2 19:06:22 | 显示全部楼层
fchen2 发表于 2016-5-2 17:20
定时器超时消息如何处理?

定时器超时不再这个框架内,
最简单的方式是实现一个定时节拍,而后设定自己要延时的节拍数,在那个节拍处理器中不停的减,为0时,给框架发一个消息。

出0入0汤圆

发表于 2016-5-3 11:07:02 来自手机 | 显示全部楼层
先收下,谢谢!

出0入0汤圆

发表于 2016-5-3 11:10:05 | 显示全部楼层
用switch-case写最简单,但是难维护啊。

出0入89汤圆

 楼主| 发表于 2016-5-3 12:13:30 | 显示全部楼层
笑笑我笑了 发表于 2016-5-3 11:10
用switch-case写最简单,但是难维护啊。

你看看我这个,是不是还可以?

出0入0汤圆

发表于 2016-5-3 12:21:05 | 显示全部楼层
youkebing 发表于 2016-5-3 12:13
你看看我这个,是不是还可以?

够简洁,但是状态不能嵌套啊。

出0入89汤圆

 楼主| 发表于 2016-5-3 12:41:43 | 显示全部楼层
笑笑我笑了 发表于 2016-5-3 12:21
够简洁,但是状态不能嵌套啊。

呵呵,太复杂可能就失去意义了,一般我也不喜欢过于庞大的框架

出0入0汤圆

发表于 2016-5-3 12:51:25 | 显示全部楼层
下载了,研究研究
写好程序不容易

出0入0汤圆

发表于 2016-5-3 12:52:22 | 显示全部楼层
youkebing 发表于 2016-5-3 12:41
呵呵,太复杂可能就失去意义了,一般我也不喜欢过于庞大的框架

框架复杂呢,应用可能会简单,但是框架简单呢,应用会复杂。
怎么取舍,看你自己啦。

出0入89汤圆

 楼主| 发表于 2016-5-3 12:59:19 | 显示全部楼层
笑笑我笑了 发表于 2016-5-3 12:52
框架复杂呢,应用可能会简单,但是框架简单呢,应用会复杂。
怎么取舍,看你自己啦。
...

每个人看法不一样,所以也要有取舍,如果更复杂的话,其实直接上os,但是许多时候,我们不需要那么大。那么这个时候,可能一个简单的框架更合适

出0入0汤圆

发表于 2016-5-3 13:01:03 | 显示全部楼层
思路都差不多

出0入89汤圆

 楼主| 发表于 2016-5-3 17:03:22 | 显示全部楼层

请发表高见,有没有类似的也发表出来,大家一起交流啊

出0入42汤圆

发表于 2016-5-3 21:20:33 | 显示全部楼层
谢谢分享,mark状态机

出0入0汤圆

发表于 2016-5-4 09:59:58 | 显示全部楼层
给楼主顶下

出0入0汤圆

发表于 2016-5-4 10:11:15 | 显示全部楼层
看不动,求LZ写一个定时炸弹demo,洗衣机也行

出0入0汤圆

发表于 2016-5-4 10:17:25 | 显示全部楼层
很简练的一个

出5入8汤圆

发表于 2016-5-4 11:35:55 | 显示全部楼层
最近正在研究状态机  谢谢分享

出0入89汤圆

 楼主| 发表于 2016-5-4 12:09:39 | 显示全部楼层
RAMILE 发表于 2016-5-4 10:11
看不动,求LZ写一个定时炸弹demo,洗衣机也行

不知道你的定时是啥样的?你写个定时的简单需求呢?

出0入0汤圆

发表于 2016-5-4 12:34:46 | 显示全部楼层
youkebing 发表于 2016-5-4 12:09
不知道你的定时是啥样的?你写个定时的简单需求呢?

void TIMER_IRQ(void)
{
        me->tick--;
}

STATE1
{
        switch(evt)
        {
                case xx:
                        if(me->tick == xxx)
                                xxxx
                        break;

                default:
                        break;
        }
}

出0入89汤圆

 楼主| 发表于 2016-5-4 12:49:06 | 显示全部楼层
笑笑我笑了 发表于 2016-5-4 12:34
void TIMER_IRQ(void)
{
        me->tick--;

你这个代码好难懂,似乎就一个状态,一个状态还叫状态机吗?麻烦些个详细的需求呢?

出0入0汤圆

发表于 2016-5-4 13:54:41 | 显示全部楼层
youkebing 发表于 2016-5-4 12:49
你这个代码好难懂,似乎就一个状态,一个状态还叫状态机吗?麻烦些个详细的需求呢? ...

事件+时间片轮转

出0入0汤圆

发表于 2016-5-4 15:36:27 | 显示全部楼层
mark一下

出0入0汤圆

发表于 2016-5-4 18:45:40 | 显示全部楼层
之前用过不少pt,感觉挺好,也没出过什么问题,不知道这个怎么样,下载看看,谢谢楼主。

出0入0汤圆

发表于 2016-5-4 20:20:21 | 显示全部楼层
谢谢,收藏了,以后研究一下。

出0入0汤圆

发表于 2016-5-5 09:22:47 来自手机 | 显示全部楼层
mark              .

出0入0汤圆

发表于 2016-5-6 10:14:06 | 显示全部楼层
看了一下,里面的超状态什么意思啊。没弄懂

出0入0汤圆

发表于 2016-5-6 11:07:58 | 显示全部楼层
下下来,学习一下

出0入89汤圆

 楼主| 发表于 2016-5-6 11:27:46 | 显示全部楼层
watcherone 发表于 2016-5-6 10:14
看了一下,里面的超状态什么意思啊。没弄懂

你说的什么抄状态?我不知道你说的是哪一块

出0入0汤圆

发表于 2016-5-6 12:13:20 | 显示全部楼层
HSM中的SM_RET_SUPER,/*!< event passed to superstate to handle */

出0入89汤圆

 楼主| 发表于 2016-5-6 12:16:46 | 显示全部楼层
因为这是参照QP的,所以有些定义是没有用的,简化的,忽略掉就可以,看好原理就可以了

出0入0汤圆

发表于 2016-5-6 12:19:13 | 显示全部楼层
自己新手,基础不够。就结合QP-nano源码对这个框架做了一个详细的注释。希望大家有用,可能有点错误。但是整体还是正确的

本帖子中包含更多资源

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

x

出0入89汤圆

 楼主| 发表于 2016-5-6 12:22:29 | 显示全部楼层
watcherone 发表于 2016-5-6 12:19
自己新手,基础不够。就结合QP-nano源码对这个框架做了一个详细的注释。希望大家有用,可能有点错误。但是 ...

呵呵,大家一起学习,我没有全部看,我只找了一点最简单的看了下

出0入0汤圆

发表于 2016-5-6 12:31:53 | 显示全部楼层
下了,慢慢看

出0入0汤圆

发表于 2016-5-6 15:57:28 | 显示全部楼层
标签:状态机

出0入0汤圆

发表于 2016-5-11 10:27:36 | 显示全部楼层
收藏备用

出0入0汤圆

发表于 2016-5-13 15:33:57 | 显示全部楼层
还有此等好东西,收藏了~

出0入0汤圆

发表于 2016-5-14 11:11:10 | 显示全部楼层
楼主,我很好奇,你那个文件夹里的.exe是怎么生成的,这个可执行文件太给力了。我好像意识到了它背后的力量

出0入89汤圆

 楼主| 发表于 2016-5-14 11:14:48 | 显示全部楼层
ywlzh 发表于 2016-5-14 11:11
楼主,我很好奇,你那个文件夹里的.exe是怎么生成的,这个可执行文件太给力了。我好像意识到了它背后的力量 ...

一点也不好奇啊,那个是gcc编译的

出0入0汤圆

发表于 2016-5-14 13:28:12 | 显示全部楼层
收藏学习。                 

出425入0汤圆

发表于 2016-5-14 14:05:29 | 显示全部楼层
支持状态机的嵌套吗?

出0入0汤圆

发表于 2016-5-14 14:13:27 | 显示全部楼层
来个更简单的,只给接口,怎么用,自己琢磨吧,很简单。
  1. /*******************************************************************************
  2. *  Copyright(C)2016 by Dreistein<mcu_shilei@hotmail.com>                     *
  3. *                                                                            *
  4. *  This program is free software; you can redistribute it and/or modify it   *
  5. *  under the terms of the GNU Lesser General Public License as published     *
  6. *  by the Free Software Foundation; either version 3 of the License, or      *
  7. *  (at your option) any later version.                                       *
  8. *                                                                            *
  9. *  This program is distributed in the hope that it will be useful, but       *
  10. *  WITHOUT ANY WARRANTY; without even the implied warranty of                *
  11. *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU          *
  12. *  General Public License for more details.                                  *
  13. *                                                                            *
  14. *  You should have received a copy of the GNU Lesser General Public License  *
  15. *  along with this program; if not, see http://www.gnu.org/licenses/.        *
  16. *******************************************************************************/

  17. //! \note do not move this pre-processor statement to other places
  18. #define __EVENT_FSM_C__

  19. /*============================ INCLUDES ======================================*/
  20. #include ".\app_cfg.h"

  21. /*============================ MACROS ========================================*/
  22. /*============================ MACROFIED FUNCTIONS ===========================*/
  23. /*============================ TYPES =========================================*/
  24. typedef uint8_t (fn_state_t)(void *pArg);
  25. typedef fn_state_t *event_fsm_stack_t;

  26. typedef struct {
  27.     event_fsm_stack_t *pStack;
  28.     uint8_t     chStackSize;
  29.     uint8_t     chSP;
  30.     uint8_t     chCurrentSP;
  31. } event_fsm_tcb_t;

  32. /*============================ PROTOTYPES ====================================*/
  33. /*============================ LOCAL VARIABLES ===============================*/
  34. /*============================ GLOBAL VARIABLES ==============================*/
  35. /*============================ IMPLEMENTATION ================================*/
  36. bool event_fsm_init(event_fsm_tcb_t *ptTCB,
  37.                     event_fsm_stack_t *pStack,
  38.                     uint8_t chStackSize,
  39.                     fn_state_t *pInitState)
  40. {
  41.     ptTCB->pStack       = pStack;
  42.     ptTCB->chStackSize  = chStackSize;
  43.     ptTCB->chSP         = 0;
  44.     ptTCB->chCurrentSP  = 0;
  45.     ptTCB->pStack[0]    = pInitState;

  46.     return true;
  47. }

  48. bool event_fsm_transfer_to(event_fsm_tcb_t *ptTCB, fn_state_t *pState)
  49. {
  50.     ptTCB->chSP = ptTCB->chCurrentSP;
  51.     ptTCB->pStack[ptTCB->chCurrentSP] = pState;
  52.    
  53.     return true;
  54. }

  55. bool event_fsm_transfer_to_end(event_fsm_tcb_t *ptTCB)
  56. {
  57.     ptTCB->chSP = ptTCB->chCurrentSP;
  58.     ptTCB->pStack[ptTCB->chCurrentSP] = NULL;

  59.     if (ptTCB->chSP) {
  60.         ptTCB->chSP--;
  61.     } else {
  62.         //! event fsm run complete.
  63.     }
  64.    
  65.     return true;
  66. }

  67. bool event_fsm_to_current_Level(event_fsm_tcb_t *ptTCB)
  68. {
  69.     ptTCB->chSP = ptTCB->chCurrentSP;
  70.     return true;
  71. }

  72. bool event_fsm_transfer_to_uper(event_fsm_tcb_t *ptTCB, fn_state_t *pState)
  73. {
  74.     if (ptTCB->chStackSize == (ptTCB->chSP + 1)) {
  75.         return false;
  76.     }

  77.     ptTCB->chSP++;
  78.     ptTCB->pStack[ptTCB->chSP] = pState;
  79.    
  80.     return true;
  81. }

  82. //! internal use only.
  83. bool event_fsm_current_level_decrease(event_fsm_tcb_t *ptTCB)
  84. {
  85.     if (ptTCB->chCurrentSP) {
  86.         ptTCB->chCurrentSP--;
  87.         return true;
  88.     } else {
  89.         return false;
  90.     }
  91. }

  92. bool event_fsm_transfer_to_lower(event_fsm_tcb_t *ptTCB, fn_state_t *pState)
  93. {
  94.     if (!event_fsm_current_level_decrease(ptTCB)) {
  95.         return false;
  96.     }

  97.     return event_fsm_transfer_to(ptTCB, pState);
  98. }

  99. fn_state_t *event_fsm_get_current_state(event_fsm_tcb_t *ptTCB)
  100. {
  101.     return ptTCB->pStack[ptTCB->chCurrentSP];
  102. }

  103. fn_state_t *event_fsm_get_state(event_fsm_tcb_t *ptTCB)
  104. {
  105.     ptTCB->chCurrentSP = ptTCB->chSP;
  106.     return ptTCB->pStack[ptTCB->chSP];
  107. }


  108. /* EOF */
复制代码

用在DTU上,AT指令的处理。

出0入89汤圆

 楼主| 发表于 2016-5-14 14:50:40 | 显示全部楼层
zhenghe 发表于 2016-5-14 14:13
来个更简单的,只给接口,怎么用,自己琢磨吧,很简单。

用在DTU上,AT指令的处理。 ...

似乎没有我那个简单

出0入89汤圆

 楼主| 发表于 2016-5-14 14:54:28 | 显示全部楼层
guolun 发表于 2016-5-14 14:05
支持状态机的嵌套吗?

这个是很简单的,不支持嵌套,当然,你可以修改,

出0入0汤圆

发表于 2016-5-14 15:12:53 | 显示全部楼层
youkebing 发表于 2016-5-14 14:50
似乎没有我那个简单

你只做了fsm,我只做了hsm,人家都做了好吧。原理都那样,不同实现罢了。

出0入89汤圆

 楼主| 发表于 2016-5-14 15:29:31 | 显示全部楼层
zhenghe 发表于 2016-5-14 15:12
你只做了fsm,我只做了hsm,人家都做了好吧。原理都那样,不同实现罢了。 ...

好吧,我错了

出0入0汤圆

发表于 2016-5-14 18:47:27 | 显示全部楼层
fsm  hsm  是有限状态机吗?能否详细说明一下?

出0入0汤圆

发表于 2016-5-14 20:17:00 | 显示全部楼层
好东西 下载下来学习

出0入0汤圆

发表于 2016-5-16 19:11:58 来自手机 | 显示全部楼层
感谢分享,下载学习!

出0入0汤圆

发表于 2016-5-17 08:47:12 | 显示全部楼层
现在我都是用switch写。。

出0入89汤圆

 楼主| 发表于 2016-5-17 10:55:50 | 显示全部楼层
tianyime 发表于 2016-5-17 08:47
现在我都是用switch写。。

这个由很多方法,我这个仅仅是一个例子,switch当然是可以得。

出0入0汤圆

发表于 2016-5-17 14:58:55 | 显示全部楼层
mark一下

出0入0汤圆

发表于 2016-5-17 15:40:50 来自手机 | 显示全部楼层
学习一下,不错。

出0入0汤圆

发表于 2016-5-25 09:35:50 | 显示全部楼层
有事件框架么,还是说只是状态机框架。只是状态机的话将QP里的qfsm弄出来就是了。

出140入8汤圆

发表于 2016-10-19 06:57:32 | 显示全部楼层
看来除了switch,我需要花点时间学习一下了

出0入0汤圆

发表于 2016-10-24 20:29:45 | 显示全部楼层
支持创新

出0入0汤圆

发表于 2016-10-24 20:57:57 | 显示全部楼层
学习。简单的状态机。

出0入0汤圆

发表于 2016-11-2 16:38:16 | 显示全部楼层
赶脚是一坨shit,这样封装和重新写有什么区别。

出0入0汤圆

发表于 2017-1-5 17:27:05 | 显示全部楼层
谢谢分享 下来看看

出0入0汤圆

发表于 2017-1-5 19:23:31 | 显示全部楼层
这个可以有,搞来研究学习下

出0入0汤圆

发表于 2017-1-5 23:05:07 | 显示全部楼层
还可以,学习下下

出0入0汤圆

发表于 2017-1-6 13:21:01 | 显示全部楼层
压缩包不利于直观看代码探讨,我先把你的代码贴出来。再探讨。

  1. //ssm.c
  2. #include "ssm.h"

  3. ssm_event_t ssm_reserved_event[] = {
  4.     { SSM_EMPTY_SIG, 0 },
  5.     { SSM_ENTRY_SIG, 0 },
  6.     { SSM_EXIT_SIG,  0 },
  7.     { SSM_INIT_SIG,  0 },
  8.     { SSM_USER_SIG,  0 },
  9. };

  10. static ssm_ret_t null_state_handler(ssm_t *fsm, ssm_event_t const *e) {
  11.     return SSM_EMPTY_SIG;
  12. }

  13. void fsm_ctor(ssm_t *me, ssm_state_handler_t init) {
  14.     me->state = null_state_handler;
  15.     me->temp  = init;
  16.     fsm_dispatch(me, &ssm_reserved_event[1]);
  17. }

  18. void fsm_dispatch(ssm_t *me, ssm_event_t *e) {
  19.     ssm_ret_t ret;

  20.     ret = (me->temp)(me, e);
  21.     if (SSM_RET_TRAN == ret) {
  22.         SSM_EXIT(me, me->state);
  23.         SSM_ENTRY(me, me->temp);
  24.         me->state = me->temp;
  25.     }
  26. }
复制代码
  1. //ssm.h

  2. #ifndef __SM_H__
  3. #define __SM_H__

  4. #ifdef __cplusplus
  5. extern "C" {
  6. #endif


  7. typedef int ssm_sig_t;

  8. /**
  9. * @bref 状态机事件
  10. */
  11. typedef struct ssm_event_s {
  12.     ssm_sig_t sig;
  13.     void *event;
  14. } ssm_event_t;

  15. /**
  16. * @bref 状态处理函数返回值, 指示事件被怎么处理了
  17. */
  18. typedef unsigned char ssm_ret_t;

  19. //struct ssm_fsm_s;
  20. typedef struct ssm_s ssm_t;
  21. typedef ssm_ret_t (*ssm_state_handler_t)(ssm_t *fsm, ssm_event_t const *e);

  22. /**
  23. * @bref 状态机
  24. */
  25. struct ssm_s {
  26.     ssm_state_handler_t state;
  27.     ssm_state_handler_t temp;
  28. };

  29. /**
  30. * @bref 状态机返回值
  31. *
  32. */
  33. enum {
  34.     SSM_RET_HANDLED,
  35.     SSM_RET_IGNORE,
  36.     SSM_RET_UNHANDLED,

  37.     SSM_RET_TRAN,
  38.     SSM_RET_SUPER,
  39. };
  40. #define SSM_RET_CAST(x)  ( (ssm_ret_t)(x) )

  41. #define SSM_HANDLED()        SSM_RET_CAST(SSM_RET_HANDLED)
  42. #define SSM_IGNORE()         SSM_RET_CAST(SSM_RET_IGNORE)
  43. #define SSM_UNHANDLED()      SSM_RET_CAST(SSM_RET_UNHANDLED)

  44. #define SSM_TRAN(me, target) \
  45.             ((me)->temp = (target), SSM_RET_CAST(SSM_RET_TRAN))
  46. #define SSM_SUPER(me, super) \
  47.             ((me)->temp = (super), SSM_RET_CAST(SSM_RET_SUPER))

  48. #define SSM_SIG(e) (e->sig)

  49. enum ssm_reserved_sig {
  50.     SSM_EMPTY_SIG = -5,
  51.     SSM_ENTRY_SIG = -4,
  52.     SSM_EXIT_SIG  = -3,
  53.     SSM_INIT_SIG  = -2,
  54.     SSM_USER_SIG  = -1,
  55. };
  56. extern ssm_event_t ssm_reserved_event[];
  57. #define SSM_TRIG(me, state, sig)     ((state)(me, &ssm_reserved_event[5 + (sig)]))
  58. #define SSM_ENTRY(me, state)         SSM_TRIG(me, state, SSM_ENTRY_SIG)
  59. #define SSM_EXIT(me, state)      SSM_TRIG(me, state, SSM_EXIT_SIG)

  60. void fsm_ctor(ssm_t *me, ssm_state_handler_t init);
  61. void fsm_dispatch(ssm_t *me, ssm_event_t *e);

  62. #ifdef __cplusplus
  63. }
  64. #endif

  65. #endif
复制代码

  1. //main.c

  2. #include "ssm.h"
  3. #include <windows.h>
  4. #include <stdio.h>

  5. #define SSM_TIMEOUT_SIG  0
  6. static ssm_ret_t off_state_handler(ssm_t *fsm, ssm_event_t const *e);
  7. static ssm_ret_t on_state_handler(ssm_t *fsm, ssm_event_t const *e);

  8. static ssm_ret_t off_state_handler(ssm_t *fsm, ssm_event_t const *e) {
  9.     ssm_ret_t status;

  10.     switch (SSM_SIG(e)) {
  11.         case SSM_ENTRY_SIG: {
  12.             printf("close led\r\n");
  13.             status = SSM_HANDLED();
  14.             break;
  15.         }
  16.         case SSM_TIMEOUT_SIG: {
  17.             printf("off time ev\r\n");
  18.             status = SSM_TRAN(fsm, &on_state_handler);
  19.             break;
  20.         }
  21.         default: {
  22.             status = SSM_HANDLED();
  23.             break;
  24.         }
  25.     }
  26.     return status;
  27. }
  28. static ssm_ret_t on_state_handler(ssm_t *fsm, ssm_event_t const *e) {
  29.     ssm_ret_t status;

  30.     switch (SSM_SIG(e)) {
  31.         case SSM_ENTRY_SIG: {
  32.             printf("open led\r\n");
  33.             status = SSM_HANDLED();
  34.             break;
  35.         }
  36.         case SSM_TIMEOUT_SIG: {
  37.             printf("on time ev\r\n");
  38.             status = SSM_TRAN(fsm, &off_state_handler);
  39.             break;
  40.         }
  41.         default: {
  42.             status = SSM_HANDLED();
  43.             break;
  44.         }
  45.     }
  46.     return status;
  47. }
  48. int main(int argc, char **argv) {
  49.     ssm_event_t ev = {SSM_TIMEOUT_SIG, 0};
  50.     ssm_t me;

  51.     fsm_ctor(&me, off_state_handler);

  52.     while (1) {
  53.         Sleep(1000);
  54.         fsm_dispatch(&me, &ev);
  55.     }
  56.     return 0;
  57. }
复制代码

出0入0汤圆

发表于 2017-1-6 13:28:58 | 显示全部楼层
代码看了一下,指针利用非常轻熟。  
1.但这样的状态机缺少异步事件处理,还有就是单一状态下事件的时间可能远远大于TIMEOUT的值,造成其它事件直接死等。
2.适合于处理简单事务,单一状态处理函数中可做的事务越简单,耗时越小,整体状态循环就快。
3.代码的偶合性太高了,如果事件状态超过10个,20个,50个的时候,状态迁移就需要表来维护了,代码的后期维护难度将直线上升,非常困难。

我简单列一下我的观点:
1.将所要实现的功能分解成任务,各任务下再划分出不同状态,状态表要全局的;
2.状各任务配备一份状态控制表,每一状态完成后检查是否需要跳转任务状态;
3.设定定时器,处理异步事务,中断事务。

出0入89汤圆

 楼主| 发表于 2017-1-6 22:21:37 | 显示全部楼层
谢谢你的建议

出0入0汤圆

发表于 2017-4-10 22:07:42 | 显示全部楼层
学习一下!谢谢

出0入0汤圆

发表于 2017-5-14 19:45:19 | 显示全部楼层
这个最简状态机框架可以这样用:
- 定义一个FSM,再定义这个FSM的一个通用消息变量Evt,把FSM+Evt封装起来,这样就得到一个AO,然后程序里可以有多个AO,它们互相通过发送消息进行协作。
- 每个AO再增加一个定时器消息变量EvtTimer,可以实现延时动作。

由于消息变量Evt可以看成是长度为1的队列,所以AO可能丢失消息。但如果把Evt扩展为长度大于1的队列,就又回到QPN的完整设计。

所以,简单的项目可以用这个框架,实际工程里建议直接用QPN框架,它基本功能都齐了。

出0入0汤圆

发表于 2017-5-30 15:00:35 | 显示全部楼层
学习学习。。。。

出0入0汤圆

发表于 2018-6-23 17:03:37 | 显示全部楼层
很不错的东西,状态机在嵌入式简直是无敌的存在。

出425入0汤圆

发表于 2018-6-23 21:44:46 | 显示全部楼层
这个状态机也做过产品,就是事件的生成和派送繁琐。用QPN较省事。

出0入0汤圆

发表于 2018-6-23 21:46:49 | 显示全部楼层
非常不错。

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-4-25 23:54

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

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