提到单片机编程,不得不提到状况机,状况机做为软件编程的首要架构现已在各种言语中使用,当然包含C言语,在一个思路清晰并且高效的程序中,必定有状况机的身影显现。灵敏的使用状况机不仅是程序更高效,并且可读性和扩展性也很好。状况无处不在,状况中有状况,只需把握了这种思想,让它成为您编程中的一种习气,信任您会收获颇丰。
状况机可概括为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); //分发音讯
}
}