論狀態(tài)機與模塊化_談?wù)勎覍硐刖幊棠P偷目捶╛圖文_第1頁
論狀態(tài)機與模塊化_談?wù)勎覍硐刖幊棠P偷目捶╛圖文_第2頁
論狀態(tài)機與模塊化_談?wù)勎覍硐刖幊棠P偷目捶╛圖文_第3頁
論狀態(tài)機與模塊化_談?wù)勎覍硐刖幊棠P偷目捶╛圖文_第4頁
論狀態(tài)機與模塊化_談?wù)勎覍硐刖幊棠P偷目捶╛圖文_第5頁
已閱讀5頁,還剩1頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、 三、 無法分割的功能 有些功能, 它不長也不短, 大致與系統(tǒng)的查詢周期相當(dāng), 且不好分片; 另外還有些功能, 漫長又無法分片,但是系統(tǒng)允許在它運行期間獨占控制權(quán)。這兩類功能,就像骨頭一樣,把 程序卡在那里,我們稱之為 骨頭 功能。吃飯時吃到骨頭怎么辦?有時你運氣好,剛好是 塊軟骨,那就把它咬碎吞了。實在是咬不動的骨頭怎么辦?那就只有硬吞了。如果你的消化 夠好,那塊骨頭能夠很好地融入你的身體;如果你消化不行,那就可能造成硬傷了。編程也 一樣, 遇到骨頭不要急,先仔細(xì)分析, 看能不能把它分片, 如果能分片,那就變成裹腳布了。 如果不能分片,而且系統(tǒng)允許,那就直接嵌入這么個長時間執(zhí)行的功能,但是程

2、序員要很清 楚由此對系統(tǒng)造成的影響, 特別是在后面追加功能的時候, 這個潛在的威脅可能會影響新功 能的實現(xiàn)。 那么硬骨頭究竟會對我們的系統(tǒng)造成什么影響呢? 1) 首先,由于它拖慢了系統(tǒng)的運行,使系統(tǒng)的響應(yīng)周期變長。當(dāng)然,這都是對處于主 執(zhí)行緒中(即中斷外)的輸入響應(yīng)造成影響,如果對一個輸入的所有響應(yīng)都在中斷 中完成,那是不會受到硬骨頭影響的。 2) 其次,由于它拖慢了系統(tǒng)的運行周期,而查詢周期沒有變,可能會造成某些輸入的 丟失。例如,有個系統(tǒng)的查詢周期是 10ms,但是系統(tǒng)中的一個寫 FLASH 功能可能 要 60ms,那么它就可能丟失 5 個 10ms 觸發(fā)消息。 其實硬骨頭也不可怕, 對于

3、每一塊硬骨頭, 我們在編寫的時候都分析清楚由此對系統(tǒng)造 成的影響,消除由此產(chǎn)生的不良影響,就不會有問題了。很多時候,小骨頭(長度在一個查 詢周期左右) 幾乎不會對系統(tǒng)有任何不良影響, 甚至于在編程時很多小骨頭都不知道它的存 在。對于大骨頭,我們就要謹(jǐn)慎對待了(因為大骨頭很少,所以也花不了多少時間) 。一定 要清楚在它執(zhí)行期間,系統(tǒng)無法響應(yīng)其它輸入(消息) ,由此造成的消息丟失和處理滯后必 須在系統(tǒng)能承受的范圍內(nèi)。 另外一方面,對于一些頻率高的消息(如果 1ms 定時消息) ,我們要清楚地知道它有丟 失的可能,因此,不要試圖在它等于某一個特定值時執(zhí)行一些操作,而應(yīng)該改成在它大于等 于某個特定值時

4、執(zhí)行一些操作。 概括一下,對待無法分片的功能,我們要做到:咬碎軟骨頭,吞掉硬骨頭。 四、 模塊化編程 一聽到模塊化,可能很多人會說,這有什么可講的,現(xiàn)在哪個人編程不是模塊化啊?如 果現(xiàn)在還有誰編的程序只有一個源文件,估計他是過不了試用期的。_,當(dāng)然肯定有例外, 比如 4 位機編程,不過那離我們太遙遠(yuǎn)了。 但是, 你劃分的模塊別人是否認(rèn)同?你編程時是否糾結(jié)過這個函數(shù)到底該放到哪個模塊 內(nèi)呢? 模塊化不清晰的主要原因在于劃分模塊沒有一個統(tǒng)一的標(biāo)準(zhǔn), 每個程序員、 每個應(yīng)用都 不一樣,結(jié)果模塊化也就因人而異了。 那么,到底要怎么劃分模塊才能清晰呢?接觸過 C+或面向?qū)ο缶幊痰娜硕贾?,在?向?qū)ο蟪?/p>

5、序里面,把所有的東西都看作對象,每個對象就是現(xiàn)實世界中的一個物體。從面向 對象的角度來看,劃分模塊就很簡單了。每個對象劃分成一個模塊,就這么容易。 但是我們單片機編程用的是 C 語言呀,又不是 C+,哪來的類和面向?qū)ο螅坎诲e,我們 用的是 C 語言,但是我們不需要用類,我們只是用對象的觀點來劃分模塊。比如:你的系統(tǒng) 有鍵盤、LED、USART0、USART1、SPI0,那么就將它們各自劃分成一個模塊。 從我編程的經(jīng)驗來看,我們盡量用模塊來表示對象(單個物體) ,而不是用模塊來表示 類。比如上面,我們要定義 USART0、USART1 兩個模塊,而不是定義一個 USART 模塊。這 樣做的好處是

6、當(dāng)我們要實現(xiàn)一個器件的特殊功能時, 就不會牽扯到其它器件, 從而不會使模 塊的實現(xiàn)復(fù)雜化。 概括一下,用面向?qū)ο蟮挠^點來劃分模塊。 五、 狀態(tài)機與模塊化 狀態(tài)機模塊化編程的理論基礎(chǔ)是:將一個系統(tǒng)劃分成若干個子系統(tǒng),那么,整個系統(tǒng)的 狀態(tài)表現(xiàn)為所有子系統(tǒng)的狀態(tài)之和; 整個系統(tǒng)對輸入的響應(yīng)表現(xiàn)為所有子系統(tǒng)對輸入的響應(yīng) 之和。 例如,一個血氧系統(tǒng)有三個主要的子系統(tǒng):血氧采集、血氧存儲、血氧發(fā)送。那么這三 個子系統(tǒng)所做的事加起來,就是整個系統(tǒng)所做的事。反過來,我們可以把整個系統(tǒng)要做的事 分給這三個子系統(tǒng)做,每個子系統(tǒng)只做自己份內(nèi)的事就行了。這樣一來,系統(tǒng)的設(shè)計就變得 很簡單了。 六、 管道 管道用于在

7、各個模塊間傳遞數(shù)據(jù)??赡芎芏嗳藭耄苯佣x幾個全局變量不就行了 嗎?扯那么多彎彎繞干什么?這個想法其實也沒有錯, 管道的本質(zhì)就是全局變量, 管道封裝 了對全局變量的操作,使模塊間的數(shù)據(jù)傳送更簡單,更不容易出錯。 最常用管道就是 FIFO(先進(jìn)先出) 。發(fā)送數(shù)據(jù)的模塊把數(shù)據(jù)寫進(jìn) FIFO,接收數(shù)據(jù)的模塊 從 FIFO 讀出數(shù)據(jù),所讀數(shù)據(jù)的順序與寫入的順序一致,并且 FIFO 能夠緩沖一定量數(shù)據(jù)。換 句話說,發(fā)送數(shù)據(jù)的模塊只管往里面寫數(shù)據(jù),而不用等它處理完畢。 很顯然,管道的應(yīng)用使各個模塊各干各的,不必同步。 其實,大家都用過管道,只是沒有將它封裝起來,或者沒有叫它 管道 而已。比如, 一個使用

8、中斷的串口程序,它有兩個 FIFO,一個接收 FIFO,一個發(fā)送 FIFO。接收數(shù)據(jù)時, 中斷內(nèi)將數(shù)據(jù)存入接收 FIFO 內(nèi),然后中斷外從 FIFO 讀出數(shù)據(jù)進(jìn)行處理。 管道不只用于中斷內(nèi)/外傳送數(shù)據(jù),還用于模塊間傳送數(shù)據(jù)。比如,血氧系統(tǒng)中,血氧 采集模塊采到數(shù)據(jù)后,將它放入一個 FIFO 中,然后就可以開始下一次采集了。而血氧存儲 模塊總是從 FIFO 中讀取數(shù)據(jù),然后將它存到 FLASH 中。 管道不但有 FIFO,還有 LIFO(后進(jìn)先出) 、按優(yōu)先級出隊等多種方式,不過這些咱們都 用得很少。 附 A:一個 FIFO 的典型接口 一個 FIFO 所應(yīng)該具有的典型對外接口如下: void

9、FifoCreate(FIFO *ptFifo, void *puPool, INT32U uWidth, INT32U uDepth; 建立 INT32U FifoIn(FIFO *ptFifo, void *puBuf, INT32U uReqNum; /入隊. INT32U FifoOut(FIFO *ptFifo, void *puBuf, INT32U uReqNum; /出隊. void FifoClean(FIFO *ptFifo; /清空. INT32U FifoLen(FIFO *ptFifo; /得到隊列長度.有效數(shù)據(jù)個數(shù). 其中,ptFifo 是所要操作的 FIFO。pu

10、Pool 是該 FIFO 所用的緩沖池,實際的數(shù)據(jù)就是存在這 里面的。uWidth 為 FIFO 中單個元素的寬度(字節(jié)數(shù)) 。uDepth 為整個 FIFO 的深度,就是緩 沖池能容納的最大元素個數(shù)。puBuf 為出隊/入隊時的目標(biāo)緩沖區(qū),uRealNum 為請求出隊/ 入隊的元素個數(shù)。 附 B:BOS 在使用 switch 將漫長的功能剪碎的時候,如果碎片比較多,整個函數(shù)看起來就是一團 麻,編程的時候很容易出錯。如果一個功能編好以后,后面又要加上幾個步驟,這個時候會 很麻煩。另外,用 switch 實現(xiàn)的分步功能,整體看起來前后邏輯性不強,也就比較難理解。 如果我們將 switch 改頭換

11、面,封裝一下,看起來就會爽很多,編程的時候也會覺得前 后是連在一起操作的。BOS 就是因此而產(chǎn)生的。BOS 封裝了 switch 實現(xiàn)分片的功能,使分片 的功能更加容易書寫,也更容易讀懂。 塊操作流,Block Operation Stream,簡稱 BOS.BOS 用塊操作的方式建立模擬任務(wù),實現(xiàn)并發(fā) 執(zhí)行.每一個模擬任務(wù)看起來像操作系統(tǒng)中的任務(wù),可以與其它程序?qū)崿F(xiàn)并發(fā)執(zhí)行,但它們又 不是真正的任務(wù),各個任務(wù)之間不存在搶占資源,互斥訪問的問題,因為任何一個任務(wù)的執(zhí)行 都不用擔(dān)心被其它任務(wù)打斷. BOS 用于前后臺系統(tǒng)中 , 使用 switch case 實現(xiàn) , 將任務(wù)分成很多個小塊執(zhí)行 . BOS 是用于幫助程序員書寫出更加易懂的程序的,而不是實現(xiàn)一個操作系統(tǒng). BosTaskStart(ptTask; /啟動任務(wù)。 BosTaskEnd(ptTask; /結(jié)束任務(wù)。 BosTaskBodyBegin(ptTask; /開始一個任務(wù)體。 BosTaskBodyEnd(ptTask; /結(jié)束一個任務(wù)體。 BosTaskStepBegin(ptTask,STEP_NO; /開

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論