打印

单片机裸奔之状态机浅谈

[复制链接]
30515|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=MzkwNTQ5fDMyNjNjOTFkZWVhMTU4Yjc4YjgzZjRiZmU5YTExNzY1fDE3MTM1NjE0MDQ%3D&request=yes&_f=.pdfattach://390547.pdfhttps://bbs.21ic.com/forum.php?mod=attachment&aid=MzkwNTQ1fDk0NTNlY2U2ZGNhMjlkYWU5MjhmNTBhMjUwNTdjZGVlfDE3MTM1NjE0MDQ%3D&request=yes&_f=.pdfattach://390543.pdfhttps://bbs.21ic.com/forum.php?mod=attachment&aid=MzkwNTQxfDdlYzk0YmIzMzhmNDg0NDM5MGM2N2IxNGU2NGMxN2NifDE3MTM1NjE0MDQ%3D&request=yes&_f=.pdfattach://390539.pdfhttps://bbs.21ic.com/forum.php?mod=attachment&aid=MzkwNTM3fDVjY2RiMjFlZjY3M2M0MzkxMThjMmQwMTc5ZTBlNzVlfDE3MTM1NjE0MDQ%3D&request=yes&_f=.pdfattach://390535.pdfhttps://bbs.21ic.com/forum.php?mod=attachment&aid=MzkwNTMzfGY1YzhlYzJlYTc5M2E0YWVlMTc0MDJmNTJkOTUxYmNjfDE3MTM1NjE0MDQ%3D&request=yes&_f=.pdfattach://390531.pdfhttps://bbs.21ic.com/forum.php?mod=attachment&aid=MzkwNTI5fDI1Y2U1MmI1Mzk0YTZiMmY2YmM4MTk0NWM4MTQ0NzU5fDE3MTM1NjE0MDQ%3D&request=yes&_f=.pdfattach://390527.pdfhttps://bbs.21ic.com/forum.php?mod=attachment&aid=MzkwNTI1fDk4YjlhNmUwMzBiMmNmM2FjNWMyNDliMmE2OTFkNTgzfDE3MTM1NjE0MDQ%3D&request=yes&_f=.pdfattach://390523.pdfhttps://bbs.21ic.com/forum.php?mod=attachment&aid=MzkwNTIxfGI4YjUzYWNlZDUxZGM5ODFkMDhhNTlmMWZjNDJiM2FjfDE3MTM1NjE0MDQ%3D&request=yes&_f=.pdfattach://390519.pdfhttps://bbs.21ic.com/forum.php?mod=attachment&aid=MzkwNTE3fGVlODBkZDEzYzcxYWJjNTBkYzliZTRjNDU3ZTM2ODBkfDE3MTM1NjE0MDQ%3D&request=yes&_f=.pdfattach://390515.pdf

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

308.24 KB

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

183.78 KB

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

142.67 KB

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

345.14 KB

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

667.78 KB

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

262.73 KB

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

201.87 KB

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

346.21 KB

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

819.94 KB

评论
wdliming 2018-7-25 18:20 回复TA
但表示很支持楼主~ 
wdliming 2018-7-25 18:19 回复TA
这么大的字体。。。 

相关帖子

沙发
TTK0314|  楼主 | 2015-1-4 09:32 | 只看该作者
坐个沙发吧

使用特权

评论回复
板凳
keer_zu| | 2015-1-4 09:37 | 只看该作者
感谢楼主分享,在单片机应用中状态机绝对是一件利器

使用特权

评论回复
地板
hyh19890917| | 2015-1-4 10:08 | 只看该作者
绝对的强大和牛X~~

使用特权

评论回复
5
TTK0314|  楼主 | 2015-1-4 12:00 | 只看该作者
yyy71cj 发表于 2015-1-4 11:04
2015 的第一个强帖,没抢到座位就站着顶一下,希望把浅谈升级为深谈 ...

大家一起讨论,相互学习。

使用特权

评论回复
6
zhonglong1215| | 2015-1-8 10:03 | 只看该作者
状态机绝对是力气,不过我除了键盘扫描用,别的地方还真没用到……

使用特权

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

有时间整理了一定奉上

使用特权

评论回复
8
TTK0314|  楼主 | 2015-1-8 10:37 | 只看该作者
zhonglong1215 发表于 2015-1-8 10:03
状态机绝对是力气,不过我除了键盘扫描用,别的地方还真没用到……

可以考虑在通信方面试试,比如解码。

使用特权

评论回复
9
TTK0314|  楼主 | 2015-1-8 10:38 | 只看该作者
zhonglong1215 发表于 2015-1-8 10:03
状态机绝对是力气,不过我除了键盘扫描用,别的地方还真没用到……

可以考虑在通信方面试试,比如解码

使用特权

评论回复
10
GZZXB| | 2015-1-8 17:24 | 只看该作者
没有有必要向MFC靠齐吧,单片机只是个小弟弟。

使用特权

评论回复
11
sanxinwei| | 2015-1-8 17:49 | 只看该作者

没有有必要向MFC靠齐吧,单片机只是个小弟弟。

使用特权

评论回复
12
linfulin| | 2015-1-8 23:53 | 只看该作者
谢谢分享!

使用特权

评论回复
13
zhonglong1215| | 2015-1-9 10:14 | 只看该作者
TTK0314 发表于 2015-1-8 10:37
可以考虑在通信方面试试,比如解码。

期待楼主整理一下,让我们好学习学习~~~

使用特权

评论回复
14
dmcz| | 2015-1-9 21:57 | 只看该作者
这个宏定义的挺有水准

使用特权

评论回复
15
baiyunfei.k.f| | 2015-1-22 10:59 | 只看该作者
程序匠人有篇讲述状态机的好**

使用特权

评论回复
16
1021352522| | 2015-1-24 21:25 | 只看该作者
好久没来裸奔大本营了

使用特权

评论回复
17
keer_zu| | 2015-2-6 09:48 | 只看该作者
状态机对于mcu开发是非常有用的,这一点不容置疑。这个MFC不MFC没任何关系。

使用特权

评论回复
18
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.     如何实现这个模型等等。

使用特权

评论回复
19
keer_zu| | 2015-2-6 11:25 | 只看该作者
yyy71cj 发表于 2015-2-6 11:19
如是说,我倒是拭目以待,看看状态机对裸奔到底有多大用处

先这样吧,没时间啊

使用特权

评论回复
20
keer_zu| | 2015-2-6 12:29 | 只看该作者
yyy71cj 发表于 2015-2-6 12:06
一天100字,也比一点时间没有强

这倒是

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

2

主题

53

帖子

2

粉丝