网站首页
IC库存
IC展台
电子资讯
技术资料
PDF文档
我的博客
IC72论坛
ic72 logo
资料首页最新产品 技术参数 电路图 设计应用 解决方案 代理商查询 IC替换 IC厂商 电子辞典
关键字: 技术文章 PDF资料 IC价格 电路图 代理商查询 IC替换 IC厂商 电子辞典

单片机之状态机浅谈

状态机可归纳为4个要素,即现态、条件、动作、次态。这样的归纳,主要是出于对状态机的内在因果联系的考虑。“现态”和“条件”是因,“动作”和“次态”是果。详解如下:

①现态:是指当前所处的状态。

②条件:又称为“事件”。当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。

③动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。

④次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了。

如果我们进一步归纳,把“现态”和“次态”统一起来,而把“动作”忽略(降格处理),则只剩下两个最关键的要素,即:状态、迁移条件。

状态机的表示

状态机的表示要领有许多种,我们可以用文字、图形或表格的形式来表示一个状态机。

举个简单的例子:就按键处理来说,击键动作本身也可以看做一个状态机。一个细小的击键动作包含了:释放、抖动、闭合、抖动和重新释放等状态。

当我们打开思路,把状态机作为一种思想导入到程序中去时,就会找到处理疑问的一条有效的捷径。有时候用状态机的思维去思考程序该干什么,比用控制流程的思维去思考,可能会更有效。这样一来状态机便有了更实际的功用。废话不多说,实践才是检验真理的唯一标准。

几种状态机介绍

也许有人觉得状态机把问题复杂化了,其实做过软件设计的人无形之中已经在用状态机,下面就总结介绍几种状态机。

1、switch case结构状态机

switch( )

case1:

if(not反复执行状态1)

进入1状态前要做的准备

进入1状态的过程

if(not反复执行状态1)

离开状态1的过程

case2:

但这种方式不能很有效预定义所有的状态,也不能把这些状态之间的切换过程合理的定义出来,“状态”本身没有一个合理的定义,几乎是一种面向过程的方式,只过这种方式足够简单,也最容易让人接受,缺点就没有“状态”的定义和指派功能,导致状态的混乱,出现状态处理重复代码,甚至处理不一致的问题,按照OO的观念,状态描述本来就应该是一种实体。

2、ifelse语句结构状态机

这种状态机相对灵活一点,但对于一些大的项目,系统软件设计会相对复杂。

3、消息触发状态机

该类型的状态机实现方式也是很多的,形态多样,但万变不离其宗的就是状态机的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:尾

(3)划分电子秤状态,完成以上步骤后,完成OnMsg消息处理函数。

Void OnMsg(void)

{

}

说明:以上用宏完成,具体宏是如下定义:

#defineBEGIN_MESSAGE_MAP(Name,Count)constMSG_NODE_TYP MSG_node_Array_##Name[(Count)]={

#defineADD_NEW_MSG_ITEM(Msg,OnMsg){Msg,OnMsg},

#define END_MESSAGE_MAP };

#define BEGIN_Register_Task const MSG_MAP TaskMap[TotalTask]={

#defineADD_Register_Task(Name,Count) {(MSG_NODE_TYP*)MSG_node_Array_##Name,Count},

#define END_Register_Task };

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

消息如何被执行

1.分发消息

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);

}

}

2.核心函数:消息处理中心

void Message_Dispose_Central(void)

{

BYTE Msg;

while(GetMessage(&Msg)) //获取消息

{

TranslateMessage(&Msg); //解释消息

DispatchMessage(&Msg); //分发消息

}

}

热门搜索:ADS1013IDGSR 602-15 TLM615SA TLP712B 2320089 2866352 02M5000JF RBC62-1U 2320306 2762265 02B0500JF 2838319 RS-1215 SS7415-15 PS-615-HG 2856142 SS240806 BT152-500R/600R SUPER6OMNI D CC2544RHBR 8300SB2-LF TLP606B 1301380020 PS-415-HG-OEM TLM626SA
COPYRIGHT:(1998-2010) IC72 达普IC芯片交易网
客户服务:service@IC72.com 库存上载:IC72@IC72.com
(北京)联系方式: 在线QQ咨询:点击这里给我发消息 联系电话:010-82614113 传真:010-82614123
京ICP备06008810号-21 京公网安备 11010802032910 号 企业资质