单片机裸奔之状态机浅谈

[复制链接]
35744|103
 楼主| TTK0314 发表于 2015-1-4 09:31 | 显示全部楼层 |阅读模式
本帖最后由 TTK0314 于 2015-1-4 09:31 编辑

说到单片机编程,不得不说到状态机,状态机做为软件编程的主要架构已经在各种语言中应用,当然包括C语言,在一个思路清晰而且高效的程序中,必然有状态机的身影浮现。灵活的应用状态机不仅是程序更高效,而且可读性和扩展性也很好。状态无处不在,状态中有状态,只要掌握了这种思维,让它成为您编程中的一种习惯,相信您会受益匪浅。
 状态机可归纳为4个要素,即现态、条件、动作、次态。这样的归纳,主要是出于对状态机的内在因果联系的考虑。“现态”和“条件”是因,“动作”和“次态”是果。详解如下:
①现态:是指当前所处的状态。
  ②条件:又称为“事件”。当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。
  ③动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。
  ④次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了。
  如果我们进一步归纳,把“现态”和“次态”统一起来,而把“动作”忽略(降格处理),则只剩下两个最关键的要素,即:状态、迁移条件。
  状态机的表示要领有许多种,我们可以用文字、图形或表格的形式来表示一个状态机。
举个简单的例子:就按键处理来说,击键动作本身也可以看做一个状态机。一个细小的击键动作包含了:释放、抖动、闭合、抖动和重新释放等状态。  当我们打开思路,把状态机作为一种思想导入到程序中去时,就会找到处理疑问的一条有效的捷径。有时候用状态机的思维去思考程序该干什么,比用控制流程的思维去思考,可能会更有效。这样一来状态机便有了更实际的功用。废话不多说,实践才是检验真理的唯一标准。
    也许有人觉得状态机把问题复杂化了,其实做过软件设计的人无形之中已经在用状态机,下面就总结介绍几种状态机。
    第一种:switch case结构状态机
 switch()。

  case1:。

  if(not反复执行状态1)。

  进入1状态前要做的准备。

  进入1状态的过程。

  if(not反复执行状态1)。

  离开状态1的过程。

  case2:。

  ...。

  但这种方式不能很有效预定义所有的状态,也不能把这些状态之间的切换过程合理的定义出来,“状态”本身没有一个合理的定义,几乎是一种面向过程的方式,只过这种方式足够简单,也最容易让人接受,缺点就没有“状态”的定义和指派功能,导致状态的混乱,出现状态处理重复代码,甚至处理不一致的问题,按照OO的观念,状态描述本来就应该是一种实体。
第二种状态机:ifelse语句结构状态机
    这种状态机相对灵活一点,但对于一些大的项目,系统软件设计会相对复杂。
    以上2种状态机是是大家接触最多的,也是经常用到的,这里不多说了。下面重点谈谈第三种状态机。
第三种状态机:消息触发状态机
    该类型的状态机实现方式也是很多的,形态多样,但万变不离其宗的就是状态机的4要素及现态、条件、动作、次态。
    下面介绍一种消息触发类型的状态机。
基于消息驱动的状态机机制
原理:一旦有消息触发,系统服务函数立即寻找所在状态的消息与消息处理函数对,找到后执行消息处理函数
步骤:
1.添加消息与消息映射
BEGIN_MESSAGE_ MAP(Name,Count) :状态机名,消息数
ADD_NEW_MSG_ITEM (Msg,OnMsg) :消息与消息处理函数
END_MESSAGE_MAP:结束
2.在这里注册
BEGIN_Register_Task:头
...
ADD_Register_Task(Name,Count):状态机名,消息数
...
END_Register_Task:尾
1.划分电子秤状态,完成以上步骤后,完成OnMsg消息处理函数
Void OnMsg(void)
{
}
说明:以上用宏完成,具体宏是如下定义:
#defineBEGIN_MESSAGE_MAP(Name,Count)    constMSG_NODE_TYP MSG_node_Array_##Name[(Count)]={                                                                        
#define ADD_NEW_MSG_ITEM(Msg,OnMsg)                                              {Msg,OnMsg},
#define END_MESSAGE_MAP                                              };

#define BEGIN_Register_Task             const     MSG_MAP TaskMap[TotalTask]={                                                                                                                             
#define ADD_Register_Task(Name,Count)       {(MSG_NODE_TYP*)MSG_node_Array_##Name,Count},
#define END_Register_Task                                                    };

从以上代码可知:
1. 添加消息与消息映射实际上是定义消息与消息处理函数对的数组,以形成一个表
2. 注册状态机实际上是把所有消息对数组的入口定义成一个数组,以形成一个表


消息是如何被执行的?
分发消息
void Default_DisposeMessage(unsigned char *pMsg)
{
   unsigned chari;
   unsigned charcount=TaskMap[g_Status].cItemCount;//定位到状态表
   
  for(i=0;i<count;i++)
   {
    if(*pMsg==TaskMap[g_Status].pMsgItems.msg)//看能否匹配消息
    {
        TaskMap[g_Status].pMsgItems.pMsgFunc();//找到就执行消息处理函数
        return;
    }
   }
}
void DispatchMessage(unsigned char*pMsg)
{
if(*pMsg)
{
  Default_DisposeMessage(pMsg);
  
}
}
核心函数:消息处理中心
void Message_Dispose_Central(void)
{
    BYTE Msg;
   
    while(GetMessage(&Msg))      //获取消息
    {
       TranslateMessage(&Msg);   //解释消息
       DispatchMessage(&Msg);    //分发消息
    }
}
发帖仓促,以上只是个人愚见,不足的地方请大神们来吐槽和指教,之前在学习的时候我常接触到网友“傻孩子”的编程思想,受益匪浅,推荐大家去搜索他的资料学习。
下面还有一些我之前网上搜集的关于状态机的资料分享给大家,希望对大家有所帮助。
https://bbs.21ic.com/forum.php?mod=attachment&aid=MzkwNTQ5fDI0MzkyZGVhfDE3NTgzNDgzMTR8MHw%3D://390547.pdfhttps://bbs.21ic.com/forum.php?mod=attachment&aid=MzkwNTQ1fDI0YjhkN2M2fDE3NTgzNDgzMTR8MHw%3D://390543.pdfhttps://bbs.21ic.com/forum.php?mod=attachment&aid=MzkwNTQxfDBiODc3MzQ0fDE3NTgzNDgzMTR8MHw%3D://390539.pdfhttps://bbs.21ic.com/forum.php?mod=attachment&aid=MzkwNTM3fGUzNTViMmNkfDE3NTgzNDgzMTR8MHw%3D://390535.pdfhttps://bbs.21ic.com/forum.php?mod=attachment&aid=MzkwNTMzfGZkOTEwYzAyfDE3NTgzNDgzMTR8MHw%3D://390531.pdfhttps://bbs.21ic.com/forum.php?mod=attachment&aid=MzkwNTI5fDliOWJmZmUyfDE3NTgzNDgzMTR8MHw%3D://390527.pdfhttps://bbs.21ic.com/forum.php?mod=attachment&aid=MzkwNTI1fDJjOTQ0ZTM4fDE3NTgzNDgzMTR8MHw%3D://390523.pdfhttps://bbs.21ic.com/forum.php?mod=attachment&aid=MzkwNTIxfGViY2ExMWYwfDE3NTgzNDgzMTR8MHw%3D://390519.pdfhttps://bbs.21ic.com/forum.php?mod=attachment&aid=MzkwNTE3fGViN2Y4ZTU2fDE3NTgzNDgzMTR8MHw%3D://390515.pdf

CAN控制器状态机的分析与实现.pdf

819.94 KB, 下载次数: 436

基于抽象状态机的网格系统设计和分析.pdf

346.21 KB, 下载次数: 366

基于有限状态机的工控系统软件设计.pdf

201.87 KB, 下载次数: 437

嵌入式软件中状态机的抽象与实现.pdf

262.73 KB, 下载次数: 467

有限状态机FSM在PLD中的实现分析.pdf

667.78 KB, 下载次数: 357

有限状态机的一种实现框架.pdf

345.14 KB, 下载次数: 546

有限状态机在嵌入式软件中的应用.pdf

142.67 KB, 下载次数: 463

有限状态机在数控系统软件中的应用研究.pdf

183.78 KB, 下载次数: 404

状态机原理在控制程序设计中的应用.pdf

308.24 KB, 下载次数: 775

评论

但表示很支持楼主~  发表于 2018-7-25 18:20
这么大的字体。。。  发表于 2018-7-25 18:19
 楼主| TTK0314 发表于 2015-1-4 09:32 | 显示全部楼层
坐个沙发吧
keer_zu 发表于 2015-1-4 09:37 来自手机 | 显示全部楼层
感谢楼主分享,在单片机应用中状态机绝对是一件利器
hyh19890917 发表于 2015-1-4 10:08 | 显示全部楼层
绝对的强大和牛X~~
 楼主| TTK0314 发表于 2015-1-4 12:00 | 显示全部楼层
yyy71cj 发表于 2015-1-4 11:04
2015 的第一个强帖,没抢到座位就站着顶一下,希望把浅谈升级为深谈 ...

大家一起讨论,相互学习。
zhonglong1215 发表于 2015-1-8 10:03 | 显示全部楼层
状态机绝对是力气,不过我除了键盘扫描用,别的地方还真没用到……

评论

我基本上做什么控制都用状态机的方式,感觉非常好用  发表于 2018-6-15 08:28
 楼主| TTK0314 发表于 2015-1-8 10:36 | 显示全部楼层
yyy71cj 发表于 2015-1-6 22:51
楼主这点解释还不够让人饱餐一顿,希望能更系统化些。或者一次说个简单而典型的特点,让坛友们能够边互动 ...

有时间整理了一定奉上
 楼主| TTK0314 发表于 2015-1-8 10:37 | 显示全部楼层
zhonglong1215 发表于 2015-1-8 10:03
状态机绝对是力气,不过我除了键盘扫描用,别的地方还真没用到……

可以考虑在通信方面试试,比如解码。
 楼主| TTK0314 发表于 2015-1-8 10:38 | 显示全部楼层
zhonglong1215 发表于 2015-1-8 10:03
状态机绝对是力气,不过我除了键盘扫描用,别的地方还真没用到……

可以考虑在通信方面试试,比如解码
GZZXB 发表于 2015-1-8 17:24 | 显示全部楼层
没有有必要向MFC靠齐吧,单片机只是个小弟弟。
sanxinwei 发表于 2015-1-8 17:49 | 显示全部楼层

没有有必要向MFC靠齐吧,单片机只是个小弟弟。
linfulin 发表于 2015-1-8 23:53 | 显示全部楼层
谢谢分享!
zhonglong1215 发表于 2015-1-9 10:14 | 显示全部楼层
TTK0314 发表于 2015-1-8 10:37
可以考虑在通信方面试试,比如解码。

期待楼主整理一下,让我们好学习学习~~~
dmcz 发表于 2015-1-9 21:57 | 显示全部楼层
这个宏定义的挺有水准
baiyunfei.k.f 发表于 2015-1-22 10:59 | 显示全部楼层
程序匠人有篇讲述状态机的好**
1021352522 发表于 2015-1-24 21:25 | 显示全部楼层
好久没来裸奔大本营了
keer_zu 发表于 2015-2-6 09:48 | 显示全部楼层
状态机对于mcu开发是非常有用的,这一点不容置疑。这个MFC不MFC没任何关系。
keer_zu 发表于 2015-2-6 09:52 | 显示全部楼层
本帖最后由 keer_zu 于 2015-2-6 09:53 编辑
keer_zu 发表于 2015-2-6 09:48
状态机对于mcu开发是非常有用的,这一点不容置疑。这个MFC不MFC没任何关系。 ...

问题其实就是:
1.     状态机到底是什么?
        状态机的迁移机制是什么?
        哪些是事件?
        哪些是状态?
        状态之间的关系是怎样的?(例如:或状态,与状态等等)对于这些关系如何处理。等等

2.     你所遇到的问题如何采用上面的思想建立具体的模型。(如何建模)

3.     如何实现这个模型等等。
keer_zu 发表于 2015-2-6 11:25 | 显示全部楼层
yyy71cj 发表于 2015-2-6 11:19
如是说,我倒是拭目以待,看看状态机对裸奔到底有多大用处

先这样吧,没时间啊
keer_zu 发表于 2015-2-6 12:29 | 显示全部楼层
yyy71cj 发表于 2015-2-6 12:06
一天100字,也比一点时间没有强

这倒是
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:专注成就梦想。

2

主题

53

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部