新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 單片機(jī)之狀態(tài)機(jī)淺談

單片機(jī)之狀態(tài)機(jī)淺談

作者: 時(shí)間:2019-05-28 來(lái)源:網(wǎng)絡(luò) 收藏

說(shuō)到編程,不得不說(shuō)到,做為軟件編程的主要架構(gòu)已經(jīng)在各種語(yǔ)言中應(yīng)用,當(dāng)然包括C語(yǔ)言,在一個(gè)思路清晰而且高效的程序中,必然有的身影浮現(xiàn)。靈活的應(yīng)用狀態(tài)機(jī)不僅是程序更高效,而且可讀性和擴(kuò)展性也很好。狀態(tài)無(wú)處不在,狀態(tài)中有狀態(tài),只要掌握了這種思維,讓它成為您編程中的一種習(xí)慣,相信您會(huì)受益匪淺。

本文引用地址:http://m.butianyuan.cn/article/201905/400945.htm

狀態(tài)機(jī)可歸納為4個(gè)要素,即現(xiàn)態(tài)、條件、動(dòng)作、次態(tài)。這樣的歸納,主要是出于對(duì)狀態(tài)機(jī)的內(nèi)在因果聯(lián)系的考慮。“現(xiàn)態(tài)”和“條件”是因,“動(dòng)作”和“次態(tài)”是果。詳解如下:

①現(xiàn)態(tài):是指當(dāng)前所處的狀態(tài)。

②條件:又稱為“事件”。當(dāng)一個(gè)條件被滿足,將會(huì)觸發(fā)一個(gè)動(dòng)作,或者執(zhí)行一次狀態(tài)的遷移。

③動(dòng)作:條件滿足后執(zhí)行的動(dòng)作。動(dòng)作執(zhí)行完畢后,可以遷移到新的狀態(tài),也可以仍舊保持原狀態(tài)。動(dòng)作不是必需的,當(dāng)條件滿足后,也可以不執(zhí)行任何動(dòng)作,直接遷移到新?tīng)顟B(tài)。

④次態(tài):條件滿足后要遷往的新?tīng)顟B(tài)?!按螒B(tài)”是相對(duì)于“現(xiàn)態(tài)”而言的,“次態(tài)”一旦被激活,就轉(zhuǎn)變成新的“現(xiàn)態(tài)”了。

如果我們進(jìn)一步歸納,把“現(xiàn)態(tài)”和“次態(tài)”統(tǒng)一起來(lái),而把“動(dòng)作”忽略(降格處理),則只剩下兩個(gè)最關(guān)鍵的要素,即:狀態(tài)、遷移條件。

狀態(tài)機(jī)的表示

狀態(tài)機(jī)的表示要領(lǐng)有許多種,我們可以用文字、圖形或表格的形式來(lái)表示一個(gè)狀態(tài)機(jī)。

舉個(gè)簡(jiǎn)單的例子:就按鍵處理來(lái)說(shuō),擊鍵動(dòng)作本身也可以看做一個(gè)狀態(tài)機(jī)。一個(gè)細(xì)小的擊鍵動(dòng)作包含了:釋放、抖動(dòng)、閉合、抖動(dòng)和重新釋放等狀態(tài)。

當(dāng)我們打開(kāi)思路,把狀態(tài)機(jī)作為一種思想導(dǎo)入到程序中去時(shí),就會(huì)找到處理疑問(wèn)的一條有效的捷徑。有時(shí)候用狀態(tài)機(jī)的思維去思考程序該干什么,比用控制流程的思維去思考,可能會(huì)更有效。這樣一來(lái)狀態(tài)機(jī)便有了更實(shí)際的功用。廢話不多說(shuō),實(shí)踐才是檢驗(yàn)真理的唯一標(biāo)準(zhǔn)。

幾種狀態(tài)機(jī)介紹

也許有人覺(jué)得狀態(tài)機(jī)把問(wèn)題復(fù)雜化了,其實(shí)做過(guò)軟件設(shè)計(jì)的人無(wú)形之中已經(jīng)在用狀態(tài)機(jī),下面就總結(jié)介紹幾種狀態(tài)機(jī)。

1、switch case結(jié)構(gòu)狀態(tài)機(jī)

switch( )

case1:

if(not反復(fù)執(zhí)行狀態(tài)1)

進(jìn)入1狀態(tài)前要做的準(zhǔn)備

進(jìn)入1狀態(tài)的過(guò)程

if(not反復(fù)執(zhí)行狀態(tài)1)

離開(kāi)狀態(tài)1的過(guò)程

case2:

但這種方式不能很有效預(yù)定義所有的狀態(tài),也不能把這些狀態(tài)之間的切換過(guò)程合理的定義出來(lái),“狀態(tài)”本身沒(méi)有一個(gè)合理的定義,幾乎是一種面向過(guò)程的方式,只過(guò)這種方式足夠簡(jiǎn)單,也最容易讓人接受,缺點(diǎn)就沒(méi)有“狀態(tài)”的定義和指派功能,導(dǎo)致?tīng)顟B(tài)的混亂,出現(xiàn)狀態(tài)處理重復(fù)代碼,甚至處理不一致的問(wèn)題,按照OO的觀念,狀態(tài)描述本來(lái)就應(yīng)該是一種實(shí)體。

2、ifelse語(yǔ)句結(jié)構(gòu)狀態(tài)機(jī)

這種狀態(tài)機(jī)相對(duì)靈活一點(diǎn),但對(duì)于一些大的項(xiàng)目,系統(tǒng)軟件設(shè)計(jì)會(huì)相對(duì)復(fù)雜。

3、消息觸發(fā)狀態(tài)機(jī)

該類(lèi)型的狀態(tài)機(jī)實(shí)現(xiàn)方式也是很多的,形態(tài)多樣,但萬(wàn)變不離其宗的就是狀態(tài)機(jī)的4要素及現(xiàn)態(tài)、條件、動(dòng)作、次態(tài)。

原理:一旦有消息觸發(fā),系統(tǒng)服務(wù)函數(shù)立即尋找所在狀態(tài)的消息與消息處理函數(shù)對(duì),找到后執(zhí)行消息處理函數(shù)

步驟:

(1)添加消息與消息映射

BEGIN_MESSAGE_ MAP(Name,Count) :狀態(tài)機(jī)名,消息數(shù)

ADD_NEW_MSG_ITEM (Msg,OnMsg) :消息與消息處理函數(shù)

END_MESSAGE_MAP:結(jié)束

(2)在這里注冊(cè)

BEGIN_Register_Task:頭

...

ADD_Register_Task(Name,Count):狀態(tài)機(jī)名,消息數(shù)

...

END_Register_Task:尾

(3)劃分電子秤狀態(tài),完成以上步驟后,完成OnMsg消息處理函數(shù)。

Void OnMsg(void)

{

}

說(shuō)明:以上用宏完成,具體宏是如下定義:

#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 };

從以上代碼可知:添加消息與消息映射實(shí)際上是定義消息與消息處理函數(shù)對(duì)的數(shù)組,以形成一個(gè)表;注冊(cè)狀態(tài)機(jī)實(shí)際上是把所有消息對(duì)數(shù)組的入口定義成一個(gè)數(shù)組,以形成一個(gè)表。

消息如何被執(zhí)行

1.分發(fā)消息

void Default_DisposeMessage(unsigned char *pMsg)

{

unsigned chari;

unsigned charcount=TaskMap[g_Status].cItemCount;

//定位到狀態(tài)表

for(i=0;i<count;i++)

{

if(*pMsg==TaskMap[g_Status].pMsgItems.msg)

//看能否匹配消息

{

TaskMap[g_Status].pMsgItems.pMsgFunc();

//找到就執(zhí)行消息處理函數(shù)

return;

}

}

}

void DispatchMessage(unsigned char*pMsg)

{

if(*pMsg)

{

Default_DisposeMessage(pMsg);

}

}

2.核心函數(shù):消息處理中心

void Message_Dispose_Central(void)

{

BYTE Msg;

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

{

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

DispatchMessage(&Msg); //分發(fā)消息

}

}



評(píng)論


相關(guān)推薦

技術(shù)專(zhuān)區(qū)

關(guān)閉