<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 狀態(tài)機(jī)思路在單片機(jī)中的程序?qū)崿F(xiàn)

          狀態(tài)機(jī)思路在單片機(jī)中的程序?qū)崿F(xiàn)

          作者: 時間:2012-07-10 來源:網(wǎng)絡(luò) 收藏

          狀態(tài)機(jī)的概念

          狀態(tài)機(jī)是中的一個重要概念。比這個概念更重要的是對它的靈活應(yīng)用。在一個思路清晰而且高效的程序中,必然有狀態(tài)機(jī)的身影浮現(xiàn)。

          比如說一個按鍵命令解析程序,就可以被看做狀態(tài)機(jī):本來在A狀態(tài)下,觸發(fā)一個按鍵后切換到了B狀態(tài);再觸發(fā)另一個鍵后切換到C狀態(tài),或者返回到A狀態(tài)。這就是最簡單的按鍵狀態(tài)機(jī)例子。實(shí)際的按鍵解析程序會比這更復(fù)雜些,但這不影響我們對狀態(tài)機(jī)的認(rèn)識。

          進(jìn)一步看,擊鍵動作本身也可以看做一個狀態(tài)機(jī)。一個細(xì)小的擊鍵動作包含了:釋放、抖動、閉合、抖動和重新釋放等狀態(tài)。

          同樣,一個串行通信的時序(不管它是遵循何種協(xié)議,標(biāo)準(zhǔn)串口也好、I2C也好;也不管它是有線的、還是紅外的、無線的)也都可以看做由一系列有限的狀態(tài)構(gòu)成。

          顯示掃描程序也是狀態(tài)機(jī);通信命令解析程序也是狀態(tài)機(jī);甚至連繼電器的吸合/釋放控制、發(fā)光管(LED)的亮/滅控制又何嘗不是個狀態(tài)機(jī)。

          當(dāng)我們打開思路,把狀態(tài)機(jī)作為一種思想導(dǎo)入到程序中去時,就會找到解決問題的一條有效的捷徑。有時候用狀態(tài)機(jī)的思維去思考程序該干什么,比用控制流程的思維去思考,可能會更有效。這樣一來狀態(tài)機(jī)便有了更實(shí)際的功用。

          程序其實(shí)就是狀態(tài)機(jī)。

          也許你還不理解上面這句話。請想想看,計算機(jī)的大廈不就是建立在“0”和“1”兩個基本狀態(tài)的地基之上么?

          狀態(tài)機(jī)的要素

          狀態(tài)機(jī)可歸納為4個要素,即現(xiàn)態(tài)、條件、動作、次態(tài)。這樣的歸納,主要是出于對狀態(tài)機(jī)的內(nèi)在因果關(guān)系的考慮?!艾F(xiàn)態(tài)”和“條件”是因,“動作”和“次態(tài)”是果。詳解如下:

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

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

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

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

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

          狀態(tài)機(jī)的表示方法有許多種,我們可以用文字、圖形或表格的形式來表示一個狀態(tài)機(jī)。

          純粹用文字描述是很低效的,所以就不介紹了。接下來先介紹圖形的方式。

          狀態(tài)遷移圖(STD)

          狀態(tài)遷移圖(STD),是一種描述系統(tǒng)的狀態(tài)、以及相互轉(zhuǎn)化關(guān)系的圖形方式。狀態(tài)遷移圖的畫法有許多種,不過一般都大同小異。我們結(jié)合一個例子來說明一下它的畫法,如圖1所示。

          狀態(tài)機(jī)思路在單片機(jī)中的程序?qū)崿F(xiàn)

          圖1 狀態(tài)遷移圖

          ①狀態(tài)框:用方框表示狀態(tài),包括所謂的“現(xiàn)態(tài)”和“次態(tài)”。

          ②條件及遷移箭頭:用箭頭表示狀態(tài)遷移的方向,并在該箭頭上標(biāo)注觸發(fā)條件。

          ③節(jié)點(diǎn)圓圈:當(dāng)多個箭頭指向一個狀態(tài)時,可以用節(jié)點(diǎn)符號(小圓圈)連接匯總。

          ④動作框:用橢圓框表示。

          ⑤附加條件判斷框:用六角菱形框表示。

          狀態(tài)遷移圖和我們常見的流程圖相比有著本質(zhì)的區(qū)別,具體體現(xiàn)為:在流程圖中,箭頭代表了程序PC指針的跳轉(zhuǎn);而在狀態(tài)遷移圖中,箭頭代表的是狀態(tài)的改變。

          我們會發(fā)現(xiàn),這種狀態(tài)遷移圖比普通程序流程圖更簡練、直觀、易懂。這正是我們需要達(dá)到的目的。

          狀態(tài)遷移表

          除了狀態(tài)遷移圖,我們還可以用表格的形式來表示狀態(tài)之間的關(guān)系。這種表一般稱為狀態(tài)遷移表。

          表1就是前面介紹的那張狀態(tài)遷移圖的另一種描述形式。

          表1 狀態(tài)遷移表

          狀態(tài)機(jī)思路在單片機(jī)中的程序?qū)崿F(xiàn)

          ①采用表格方式來描述狀態(tài)機(jī),優(yōu)點(diǎn)是可容納更多的文字信息。例如,我們不但可以在狀態(tài)遷移表中描述狀態(tài)的遷移關(guān)系,還可以把每個狀態(tài)的特征描述也包含在內(nèi)。

          ②如果表格內(nèi)容較多,過于臃腫不利于閱讀,我們也可以將狀態(tài)遷移表進(jìn)行拆分。經(jīng)過拆分后的表格根據(jù)其具體內(nèi)容,表格名稱也有所變化。

          ③比如,我們可以把狀態(tài)特征和遷移關(guān)系分開列表。被單獨(dú)拆分出來的描述狀態(tài)特征的表格,也可以稱為“狀態(tài)真值表”。這其中比較常見的就是把每個狀態(tài)的顯示內(nèi)容單獨(dú)列表。這種描述每個狀態(tài)顯示內(nèi)容的表稱之為“顯示真值表”。同樣,我們把單獨(dú)表述基于按鍵的狀態(tài)遷移表稱為“按鍵功能真值表”。另外,如果每一個狀態(tài)包含的信息量過多,我們也可以把每個狀態(tài)單獨(dú)列表。

          ④由此可見,狀態(tài)遷移表作為狀態(tài)遷移圖的有益補(bǔ)充,它的表現(xiàn)形式是靈活的。

          ⑤狀態(tài)遷移表優(yōu)點(diǎn)是信息涵蓋面大,缺點(diǎn)是視覺上不夠直觀,因此它并不能取代狀態(tài)遷移圖。比較理想的是將圖形和表格結(jié)合應(yīng)用。用圖形展現(xiàn)宏觀,用表格說明細(xì)節(jié)。二者互為參照,相得益彰。


          上一頁 1 2 3 下一頁

          評論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();