Labview程序設(shè)計模式_第1頁
Labview程序設(shè)計模式_第2頁
Labview程序設(shè)計模式_第3頁
Labview程序設(shè)計模式_第4頁
Labview程序設(shè)計模式_第5頁
已閱讀5頁,還剩16頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、LabVIEW程序設(shè)計模式,這個相對學(xué)術(shù)化的詞語是對一系列用于LabVIEW程序設(shè)計結(jié)構(gòu)的歸納和總結(jié)。在建造房子時,需要針對房子的用途設(shè)計整個房屋的架構(gòu),確保房子在這個架構(gòu)上的堅固性和可建造性。寫程序時同樣如此,不同的應(yīng)用需要使用不同的程序設(shè)計結(jié)構(gòu)。例如我們在LabVIEW中構(gòu)建一個用戶界面型程序時,往往首先在背面板中加入一個大的while循環(huán)以使程序持續(xù)運行。如果需要響應(yīng)用戶界面事件則還需要加入一個Event事件結(jié)構(gòu)。那么我們是否曾經(jīng)考慮過以下的這些問題:(1)     應(yīng)用中是否存在并行響應(yīng)的情況?如在持續(xù)的數(shù)據(jù)采集過程中,是否需要同時響應(yīng)

2、單擊菜單的事件?(2)     底層獲取的數(shù)據(jù)如何與上層的數(shù)據(jù)顯示部分進行數(shù)據(jù)交互?(3)     上層的界面如何受底層程序的控制?(4)     同一個循環(huán)中采用哪種方式進行數(shù)據(jù)交換?是局域變量、全局變量、共享變量還是移位寄存器?(5)     程序是否具有可擴展性?(6)     如果程序運行過程中,發(fā)生系統(tǒng)錯誤或者硬件通訊錯誤,是否會停止運行

3、?待錯誤排除后是否會繼續(xù)運行?(7)     如何組織程序中的核心數(shù)據(jù)結(jié)構(gòu)?是否需要采用面向?qū)ο蟪绦蛟O(shè)計?(8)     如何記錄測試數(shù)據(jù)并生成報表?如何保存用戶配置參數(shù)?(9)     如何處理程序運行中的斷電情況?重新啟動時的繼續(xù)運行?數(shù)據(jù)的最低丟失?(10) 如何實現(xiàn)運行過程的采樣觸發(fā)和多點采樣的同步?當然,也許只是使用LabVIEW臨時地調(diào)試或開發(fā)某個小的應(yīng)用,無需考慮上述的問題。但是,如果使用LabVIEW開發(fā)一個典型應(yīng)用的程

4、序卻無法回避這些問題。因此,有必要對各種程序開發(fā)的應(yīng)用進行歸納和總結(jié),提取它們對應(yīng)的LabVIEW程序結(jié)構(gòu)中的共性。此外,針對這些共性研究哪種結(jié)構(gòu)更加適合于應(yīng)用。這些結(jié)論綜合起來就形成了程序設(shè)計的模式。對于初學(xué)者而言,理解和掌握程序設(shè)計模式往往能起到事半功倍的效果;而對高級用戶而言,歸納各種程序設(shè)計模式又能夠不斷完善程序中遇到的問題,并衍生一套符合特定應(yīng)用的特有的程序設(shè)計模式。狀態(tài)機是一種最為經(jīng)典的程序設(shè)計模式,在LabVIEW 7.1(含)之前它幾乎統(tǒng)治了大部分的LabVIEW主程序。最基本的狀態(tài)機結(jié)構(gòu)如圖 1所示。狀態(tài)是狀態(tài)機運行的經(jīng)脈,在開始使用狀態(tài)機模式撰寫程序時需要將應(yīng)用分

5、為若干個狀態(tài)。下面以圖中的應(yīng)用為例說明基本狀態(tài)機的使用?!緫?yīng)用1】前面板具有3個按鈕(Control)和1個波形顯示控件Chart(Indicator),功能分別是:1)        開始采集:Label是start,單擊后開始進行模擬數(shù)據(jù)采集程序(這里使用隨機數(shù)代替)。2)        關(guān)于:Label是dialog,單擊后彈出對話框以說明這個程序的版權(quán)、幫助等信息。3)     

6、   停止:Label是stop,單擊后停止程序的運行。4)        Chart:用于顯示獲取的隨機數(shù)。這是一個非常簡單的應(yīng)用,但是具有一定的代表性。根據(jù)要求,該應(yīng)用至少包含以下5種狀態(tài)結(jié)構(gòu)。1)        Initial:初始化狀態(tài);2)        Idle:空閑狀態(tài),用于響應(yīng)各種用戶界面操作;3) &

7、#160;      acquire:采集狀態(tài),用于持續(xù)模擬采集數(shù)據(jù);4)        about:用于彈出關(guān)于和幫助對話框;5)        stop:停止狀態(tài),退出循環(huán)并中止程序。(a)    背面板(b)    前面板圖 1 基本的狀態(tài)機結(jié)構(gòu)背面板仔細分析圖中的基本狀態(tài)

8、機,可以看出狀態(tài)始終貫穿整個應(yīng)用程序,并由移位寄存器進行值的寄存和傳遞。當前狀態(tài)分支的結(jié)果將決定下一個狀態(tài),如圖中的Idle狀態(tài)。在這個狀態(tài)中,程序?qū)⒆詣訖z測前面板的三個按鈕是否被按下。如果start被按下,則進入acquire狀態(tài);如果dialog被按下,則進入about狀態(tài);如果stop被按下,則進入stop狀態(tài);否則如果沒有任何按鈕被按下,則仍然進入當前的Idle狀態(tài)繼續(xù)檢測。在acquire狀態(tài)中,為了保證程序的重復(fù)采集使得下一個狀態(tài)仍然為acquire,但是這樣會導(dǎo)致程序無法停止(中斷采集)。于是需要在acquire狀態(tài)分支中加入stop的探測,如果stop被按下,則不再進入acqu

9、ire狀態(tài)而直接進入stop狀態(tài)。從應(yīng)用1可以看出,基本狀態(tài)機模式大體上能夠滿足主程序結(jié)構(gòu)的需要。該模式能夠很好地使得應(yīng)用程序的各個功能以狀態(tài)的方式有順序地執(zhí)行,并且保證了程序的可讀性(以狀態(tài)圖的方式顯示清晰明了)和擴展性(日后只需要擴展狀態(tài)即可擴展相應(yīng)的功能)。事例中使用的是“string”型結(jié)構(gòu)來標記狀態(tài),事實上也可以使用其它的數(shù)據(jù)類型替換,如ring、numeric或enum。從嚴格意義而言,ring并不屬于一種數(shù)據(jù)類型,它只是一種特殊的numeric性,其性質(zhì)與numeric基本上一樣。盡管ring與enum控件從外觀上看是一樣的,如圖 2所示,但是它們實質(zhì)上是不同的。主要體

10、現(xiàn)為以下7點:針對基本狀態(tài)機模式的第(13)個問題,需要對模式進行改進。本節(jié)將一一分析這些問題對應(yīng)的解決方案,并最終形成一種新的狀態(tài)機模式消息隊列型狀態(tài)機模式。(1)     狀態(tài)的分類不清晰。這是一個涉及各個狀態(tài)分類管理的問題,是一個組織問題。我們可以做一個類比,在一個書桌上有許多種類的書籍(通信、計算機、機械、法律等),這些書都擺放在書桌上很整齊。但是我們在尋找一本書時并不會覺得很迅速和隨意,因為書籍的擺放是無序的,每次尋找書籍我們不得不從第一本開始瀏覽直至找到我們想要的書籍?;蛟S可以做一些改變,我們設(shè)置一些書立,將不同種類的書使用書立分開

11、。并且在書立上標明這些書籍表示的種類。這樣我們在尋找某一種書籍時就不需要從第一本書開始尋找了,只需要找到對應(yīng)的書立,在這些書立中尋找即可。讓我們回到程序,并給程序的狀態(tài)設(shè)置一些“書立”。如圖 4所示,系統(tǒng)共有9個有效狀態(tài)(UI Initial、Data Initial、Instr Initial、Temperature、Power、FFT、JTFA、Data Clean、Exit)。如果把這些狀態(tài)混在一起,我們需要找到某一個狀態(tài)時會比較困惑和麻煩。如同上面所述,將這些狀態(tài)分為4類并設(shè)置了4個“書立”(Initial、Acquire、Analyse、System)分隔這些狀態(tài)。在實際的

12、狀態(tài)控制中,需要確保程序只會進入實際的狀態(tài)中運行而不會進入到“書立”分支中,因此對每個“書立”加入了“-”以示區(qū)別。圖 4 狀態(tài)分類盡管我們只是進行了少量的修改,但是這的確有利于程序狀態(tài)的組織和閱讀,尤其是當程序具有很多個狀態(tài)的時候。(2)     缺乏數(shù)據(jù)共享和錯誤處理機制。在層疊式的順序結(jié)構(gòu)中,數(shù)據(jù)在幀之間的傳遞是靠“順序局域變量”實現(xiàn)的。那么如果在case結(jié)構(gòu)中如何傳遞不同分支的數(shù)據(jù)呢?這個問題似乎很容易解決,使用局域變量,全局變量或共享變量都能夠解決,但是這些并不是最優(yōu)的解決方案。因為上述的方式會明顯系統(tǒng)運行的內(nèi)存空

13、間和時間。由于狀態(tài)機的基本組成元素除了case結(jié)構(gòu)之外還有循環(huán),因此可以使用移位寄存器來傳遞數(shù)據(jù)。如圖 5所示。圖 5 狀態(tài)機中的數(shù)據(jù)傳遞圖 5使用移位寄存器進行數(shù)據(jù)共享和傳遞,將所有的數(shù)據(jù)封裝在一個簇中并對每個數(shù)據(jù)命名,這樣在使用數(shù)據(jù)時就可以使用“Unbundle by name”或“bundle by name”。需要說明的是,即使使用一個數(shù)據(jù)需要共享,仍然希望采用簇的封裝形式,這樣當后續(xù)需要增加擴展數(shù)據(jù)的時候并不會影響現(xiàn)有的數(shù)據(jù)引用。(3)     每一個狀態(tài)分支只能夠決定后面的一個狀態(tài),而無法決定

14、一個狀態(tài)序列(多個狀態(tài))。在基本狀態(tài)機中之所以存在這個問題是因為狀態(tài)的傳遞使用的是Scalar(標量)形式,如果需要傳遞一個狀態(tài)序列,很明顯可以使用隊列或數(shù)組進行狀態(tài)的傳遞。在LabVIEW程序設(shè)計模式中將這種具備處理狀態(tài)序列的狀態(tài)機稱為“消息隊列型狀態(tài)機”,它是在基本狀態(tài)機基礎(chǔ)上的改進。顧名思義,這種模式就像銀行辦理業(yè)務(wù)時排隊一樣采用隊列的方式。當儲戶進入銀行時,首先到叫號機處領(lǐng)取號碼進行排隊(進入隊列)并等待。然后,當前面的儲戶辦理完業(yè)務(wù)后就可以到相應(yīng)的窗口辦理業(yè)務(wù)(退出隊列)。事實上,這種方式在現(xiàn)代生活中隨處可見。在LabVIEW中至少有兩種實現(xiàn)消息隊列的方法。如圖 6所示。前

15、者使用數(shù)組函數(shù)實現(xiàn)隊列元素的入列和出列;后者使用隊列函數(shù)實現(xiàn)隊列元素的入列和出列。二者都能夠?qū)崿F(xiàn)隊列的有序操作和狀態(tài)的序列變化。圖 6 消息隊列型狀態(tài)機模式本節(jié)解決了基本狀態(tài)機模式中的(1)(3)個問題,為了更好地比較和使用這些特點,特使用一個實例說明消息隊列型狀態(tài)機的使用過程?!緫?yīng)用2】本例要模擬一個自動販賣機的工作過程。它的一次正常交易過程為:投幣選擇需要購買的商品找?guī)牛攷胖挡蛔慊蛏唐芬呀?jīng)銷售完畢時則無法購買。程序的前面板如圖 7所示。在販賣機的左上側(cè)有4個按鈕。(1)     1USD:單擊時表示投入1美元

16、的貨幣,2USD和5USD類同;(2)     Change Back:表示找零,也就是將目前剩余的貨幣退還給用戶。程序的右側(cè)是5個按鈕,表示5種不同類別的可樂(這里均使用了可口可樂的圖標),每種可樂的價格均是1美元??蓸返南旅鏀?shù)字表示販賣機中剩余的該商品的數(shù)量,初始為每種20瓶。Current money顯示販賣機中剩余的貨幣數(shù),你可以繼續(xù)購買可樂或者選擇退回。單擊Stop按鈕將退出應(yīng)用程序。本例將使用本節(jié)介紹的消息隊列狀態(tài)機模式解決這個應(yīng)用(也可以使用其它的設(shè)計模式)。系統(tǒng)的功能并不復(fù)雜,關(guān)鍵是要判斷販賣機中的剩余錢數(shù)和剩余的貨物數(shù)以決定交

17、易是否成功。圖 7 自動販賣機前面板程序背面板如圖 8所示。系統(tǒng)分為5個狀態(tài),并分為2大類。(1)     第一類:Initiala)        UI Initial:前面板界面的初始化。b)        Data Initial:數(shù)據(jù)的初始化。(2)     第二類:Systema) 

18、60;      Idle(Default):空閑狀態(tài)。b)        CheckMoney:販賣機中的剩余錢數(shù)和剩余的貨物數(shù)以決定交易是否成功。c)        Exit:退出程序。程序開始運行時進入UI Initial和Data Initial狀態(tài),完成初始化操作。從圖中可以看出系統(tǒng)采用數(shù)組函數(shù)處理消息隊列。圖 8 自動販賣機背面板在UI Init

19、ial中,系統(tǒng)給標題欄和說明欄賦值,并將前面板的商品設(shè)置為不可購買狀態(tài),因為在初始化時還沒有完成投幣動作。如圖 9所示。圖 9 UI Initial分支在Data Initial中包含兩個共享的數(shù)據(jù):Money和GState,前者表示販賣機中剩余的幣值,初始化值為0;而后者表示販賣機中各個商品剩余的數(shù)量,初始化值為20。數(shù)據(jù)使用移位寄存器傳遞以便于在各個case分支中共享和使用,如圖 10所示。圖 10 Data Initial分支CheckMoney分支主要是為了防止不合法的交易(如投入的幣值不足或商品數(shù)量不足),如圖 1

20、1所示。圖 11 CheckMoney分支當程序運行到Exit分支時,將停止循環(huán)并退出程序,如圖 12所示。圖 12 Exit分支Idle分支用來監(jiān)控前面板各個按鈕控件的變化并執(zhí)行相應(yīng)的狀態(tài)。該分支比較復(fù)雜,當檢測到第0個按鈕被按下時(即1USD按鈕),販賣機中的貨幣值應(yīng)該加一,同時需要判斷是否達到了交易條件(即進入CheckMoney狀態(tài))。其它的狀態(tài)可以執(zhí)行相應(yīng)的代碼即可,這里不再重復(fù)解釋。圖 13 Idle分支從本例可以看出,相比基本狀態(tài)機而言,盡管程序的復(fù)雜度增加了,但是在構(gòu)建大型的應(yīng)用程序時也更加地健壯,代碼也易于

21、維護和查看。針對基本狀態(tài)機模式的第(45)個問題,需要對模式進行改進。本節(jié)將一一分析這些問題對應(yīng)的解決方案,并最終形成一種新的狀態(tài)機模式用戶界面事件模式。(1)     程序一直在占用CPU資源。(2)     無法響應(yīng)更多的前面板事件。熟悉LabVIEW的工程師應(yīng)該能夠很容易地解決這兩個問題,在LabVIEW 7.0以后的版本中提供的事件結(jié)構(gòu)(Event Structure)能夠讓我們非常便捷地處理這兩類問題。在LabVIEW中事件結(jié)構(gòu)的使用并不是一件難事,根據(jù)事件的發(fā)出源,事件可以抽象地分為

22、用戶界面事件和用戶自定義事件。相關(guān)的基本知識可以參考有關(guān)的書籍,這里不再闡述事件結(jié)構(gòu)的使用方法。圖 14所示的結(jié)構(gòu)稱為用戶界面事件模式,它能夠很便捷地響應(yīng)各種事件并且不占用CPU的資源,這是由LabVIEW中事件結(jié)構(gòu)本身的特性決定的。圖 14 用戶界面事件模式【應(yīng)用3】本例要模擬一個簡單的畫圖板功能。它有4個功能選項:點(point)、線(line)、圓(circle)和橢圓(oval),一次完成的繪畫過程是:在畫布上單擊鼠標開始繪制按住鼠標的同時在畫布上拖動鼠標在畫布上放開鼠標結(jié)束繪制。程序的前面板如圖 15所示,由上下兩大部分組成。上面用于選擇需要畫

23、圖的樣式,下面是畫布,右上方的X表示程序的結(jié)束。圖 15 畫圖板前面板由于系統(tǒng)需要響應(yīng)鼠標在畫布上單擊、移動和釋放事件,因此使用狀態(tài)機模式是無法解決的,只能通過事件結(jié)構(gòu)。因此本例將使用用戶界面事件模式實現(xiàn)上述的畫圖板功能。程序的背面板如圖 16所示。共有4個事件。(1)     Panel Close?:響應(yīng)前面板的X動作,這是一個過濾性事件,當事件發(fā)生時并不真正關(guān)閉前面板而只是停止程序的運行。(2)     Picture <Mouse Down>:表

24、示繪畫的開始。(3)     Picture <Mouse Move>:表示繪畫的路徑和軌跡。(4)     Picture <Mouse Up> <Mouse Leave>:表示繪畫的結(jié)束,此時一定要加入<Mouse Leave>事件,因為當鼠標移動到畫布的外面時就可以認為是繪畫結(jié)束了,并不需要一定要求鼠標在畫布中釋放。圖 16 畫圖板背面板Picture <Mouse Down>事件如圖 17所示,這個

25、步驟表示繪制的開始,每次的繪制都必須從這個步驟開始。事件分支左側(cè)的Button參數(shù)表示單擊鼠標的鍵位,只有在單擊鼠標左鍵時才被認為是合理的和有效的,當單擊其它的鍵位時并不開始繪制。在有效繪制中,需要將畫筆移動到鼠標當前單擊的位置。當選擇的畫圖模式是Line、和Point時,使用Draw point.vi函數(shù)可以在當前的位置上畫一個點并且將畫筆移動到當前位置。從圖中可以看出系統(tǒng)定義了4個移位寄存器變量以實現(xiàn)不同事件分支的共享,它們的含義如下:(1)     表示當前畫布中的圖像,事實上就是前面板picture中的內(nèi)容。因為每次畫圖時都是在當前畫布

26、上圖像進行疊加,所以需要使用移位寄存器以避免過多地局域變量。(2)     表示開始繪制時的鼠標位置,也就是Mouse Down在畫布上的相對位置,繪制的起點。(3)     表示是否開始了繪制。前面提過每次的繪制過程都是從Mouse Down開始的,如果沒有這個動作,那么在鼠標在畫布上的移動是無效的。(4)     表示開始繪制時的圖像,這個變量與(1)是不一樣的。它表示在Mouse Down時畫布上的圖像,而不是畫布中的實時圖像。圖 

27、;17 Picture <Mouse Down>事件Picture <Mouse Move>事件如圖 18所示,該事件是繪圖的過程中,因此移位寄存器(3)的值必須是true。可以根據(jù)不同的畫圖類型使用相應(yīng)的函數(shù)進行繪圖,如畫Line時,只需要把當前鼠標的位置作為Line的終點。圖 18 Picture <Mouse Move>事件Picture <Mouse Up> <Mouse Leave>事件如圖 19所示,該事件表示繪制的結(jié)束,因此只需要把移位寄存器(3)的值設(shè)置為false即可

28、。圖 19 Picture <Mouse Up> <Mouse Leave>事件本例的實現(xiàn)過程并不復(fù)雜,但是涉及到了4個移位寄存器變量。一旦變量共享的數(shù)據(jù)較多時往往需要使用大量的移位寄存器,因為建議使用cluster的形式將各個變量有序地組織起來上兩節(jié)分別解決了基本狀態(tài)機的第(15)個問題,但是是否具備一種模式能夠綜合隊列型狀態(tài)機模式和用戶界面事件型模式的優(yōu)點呢?這樣可以同時避免基本狀態(tài)機的第(15)個問題。答案是肯定的,本節(jié)將介紹如何將狀態(tài)機與事件結(jié)構(gòu)結(jié)合起來形成一種新的、穩(wěn)定的模式。狀態(tài)機模式的基本構(gòu)成元素是while循環(huán)和case結(jié)構(gòu),而事件結(jié)

29、構(gòu)模式的基本構(gòu)成元素是while循環(huán)和event結(jié)構(gòu),因此新的模式應(yīng)該由while循環(huán)、case結(jié)構(gòu)和event結(jié)構(gòu)組成。而while循環(huán)的目的是為了保證程序的持續(xù)運行,因此必須在最外層,這樣就只剩下了圖 20所示的兩種組合方式。在第一種方式中,每次循環(huán)的運行需要經(jīng)過一個事件結(jié)構(gòu)才能夠?qū)崿F(xiàn)case中各個分支的運行,那么到底需要多少個分支呢?一般而言不同的事件都會有不同的事件處理函數(shù)(這些函數(shù)可以在case結(jié)構(gòu)中共用),顯示這是無法滿足要求的,它從本質(zhì)上而言仍然是一種事件結(jié)構(gòu)。在第二種方式中,程序的主體是一個狀態(tài)機結(jié)構(gòu),不同的是在某一個狀態(tài)分子中有一個事件結(jié)構(gòu)。我們可以回憶狀態(tài)機模式中

30、的“空閑Idle”狀態(tài),這正是長時間占用CPU資源的源頭,如果在Idle中加入一個事件結(jié)構(gòu)后就有效地規(guī)避了這個問題。圖 20 三種結(jié)構(gòu)的組合方式因此圖 20中的第二種結(jié)構(gòu)綜合了狀態(tài)機和事件結(jié)構(gòu)的優(yōu)點,有效地克服了基本狀態(tài)機的第(15)個問題。此外,在【應(yīng)用2_自動販賣機】例程中,按鈕1USD、2USD和5USD的作用是相同的,唯一不同的是它們的代表的幣值不同。如果我們希望系統(tǒng)共用“幣值相加”這個功能,即當這三個按鈕任何一個被按下后都調(diào)用同一個函數(shù)(該函數(shù)的功能是將系統(tǒng)中原來的貨幣值與新加入的幣值相加得到新的值)。這樣,需要有一種途徑把1USD、2USD和5USD代

31、表的幣值作為參數(shù)傳遞給函數(shù)。圖 21所示為帶參數(shù)的狀態(tài)機結(jié)構(gòu),在消息隊列的狀態(tài)機模式中,加入了一個變體型的變量作為狀態(tài)傳遞的參數(shù)。實際上,可以把紅色的部分做成子vi,不僅節(jié)省了背面板空間而且能夠進行錯誤處理。程序中應(yīng)該設(shè)置一個專門的錯誤處理狀態(tài),當任何一個狀態(tài)運行后如果發(fā)生錯誤將直接轉(zhuǎn)到錯誤處理狀態(tài)。當然,也可以在圖 21的基礎(chǔ)上做一些改進和變形,假定參數(shù)的數(shù)據(jù)類型為string型,這樣就把Data參數(shù)和State合并起來,中間使用特殊符號(如)隔開。圖 21 帶參數(shù)的狀態(tài)機結(jié)構(gòu)【應(yīng)用4】本節(jié)的例程將使用Multicolumn Listbox控件處理2維

32、數(shù)組排序問題,前面板如圖 22所示。該Listbox用于顯示系統(tǒng)中的各種采集數(shù)據(jù)值,分為5列。程序的功能是當單擊Listbox的列頭時,對數(shù)據(jù)以該列的升序/降序進行排序。單擊Stop按鈕或×按鈕則停止程序運行。圖 22 2D數(shù)組排序_前面板系統(tǒng)使用狀態(tài)機和事件結(jié)構(gòu)相結(jié)合的模式,如圖 23所示。程序分為8個狀態(tài),共有4類。各個狀態(tài)的功能與消息隊列型的狀態(tài)機模式類似,程序加入了錯誤處理部分。在背面板的循環(huán)中共享同一個“錯誤簇”結(jié)構(gòu)的移位寄存器,當存在錯誤時程序?qū)簳r停止運行其它的狀態(tài)而優(yōu)先進入錯誤狀態(tài)(這里是Error分支)。圖 23&#

33、160;2D數(shù)組排序_背面板在Idle狀態(tài)中,事件結(jié)構(gòu)可以防止CPU資源的長時間占用,也可以響應(yīng)各種前面板事件,如圖 24所示。圖 24 狀態(tài)機中的事件結(jié)構(gòu)本例中引入了4個變量以供不同的狀態(tài)分支調(diào)用,如圖 25所示。其中的意義如下所述。(1)     Index:當前排序的列號,表示Listbox以哪一列為依據(jù)進行排序。(2)     ASC:表示當前排序的方式,true表示升序,而false表示降序。(3)    

34、 Column Header:表示Listbox的列頭數(shù)據(jù)。(4)     Data:表示Listbox的內(nèi)容數(shù)據(jù)。圖 25 數(shù)據(jù)變量在圖 26中,事件結(jié)構(gòu)處理的是Listbox的<Mouse Up>事件,此時只需要對內(nèi)部的變量賦值即可,并且當該單擊是有效單擊時進入“DSort”狀態(tài)進行排序操作。圖 26 排序事件在圖 27所示的DSort狀態(tài)中,根據(jù)內(nèi)部變量的值對Listbox賦值并更新列頭的顯示。圖 27 DSort狀態(tài)圖 27調(diào)

35、用了2D數(shù)組的排序函數(shù),該函數(shù)的實現(xiàn)過程如圖 28所示。LabVIEW并沒有提供2D數(shù)組的排序方式,只提供了1D數(shù)組的排序函數(shù)。本例充分利用了LabVIEW提供的排序函數(shù)功能,當然并不是唯一的,也可以使用LabVIEW實現(xiàn)常用的排序算法。圖 28 2D數(shù)組排序簡單而言,動態(tài)調(diào)用指的是通過程序控制另外一個程序的運行、停止、賦值和獲取值等。LabVIEW提供了多種動態(tài)調(diào)用的方式,從底層而言是通過VI Server技術(shù)實現(xiàn)的。圖 31所示為LabVIEW中的Application Control選板,動態(tài)調(diào)用所使用的節(jié)點都位于這個選板。當調(diào)用一個在硬盤、內(nèi)存甚

36、至是網(wǎng)絡(luò)路徑上的vi時,首先要使用Open VI Reference以將該VI載入內(nèi)存并獲取VI的“句柄(Reference)”;然后再使用該句柄進行其它的控制操作;最后再關(guān)閉該VI的句柄避免內(nèi)存泄漏,這就完成了一次對VI的調(diào)用。圖 31 Application Control選板圖 32是一個動態(tài)調(diào)用的具體實現(xiàn)代碼,首先使用Open VI Reference獲取被動態(tài)調(diào)用VI的Reference(例子中是C:average.vi);再使用Call By Reference Node節(jié)電動態(tài)運行該VI;最后關(guān)閉VI的Reference。在使用Call By Ref

37、erence Node時需要事先指定被調(diào)用VI的輸入輸出接口,也就是說這種動態(tài)調(diào)用的前提是必須知道被調(diào)用VI的輸入輸出接口,否則無法進行動態(tài)調(diào)用。圖 32 VI的動態(tài)調(diào)用Open VI Reference的路徑輸入是一個多態(tài)的輸入口,也可以使用String輸入,如圖 33所示。此時被調(diào)用的VI必須在內(nèi)存中,且輸入的是被調(diào)用VI的文件名。值得一提的是這種“文件名”調(diào)用方式在可執(zhí)行程序中是無法被調(diào)用的,因此建議最好采用路徑的調(diào)用方式。圖 33 Open VI Reference的多態(tài)性【應(yīng)用5】本例將使用LabVIEW的動態(tài)調(diào)用方式實現(xiàn)斐波那契數(shù)列

38、(Fibonacci數(shù)列)。斐波那契數(shù)列指的是這樣一個數(shù)列:1,1,2,3,5,8,13,21 這個數(shù)列從第三項開始,每一項都等于前兩項之和。在數(shù)學(xué)上表述為:f(n)=f(n-1)+f(n-2),其中n>=3,f(1)=f(2)=1。顯然這是一個比較熟悉的遞歸調(diào)用,但是在LabVIEW中似乎很難實現(xiàn)。由于LabVIEW不允許同名的VI同時在內(nèi)存中,因此一個VI是無法VI調(diào)用本身的。但是,通過VI的可重入技術(shù)和動態(tài)調(diào)用技術(shù)卻可以實現(xiàn)VI的遞歸調(diào)用。圖 34所示為Fibonacci數(shù)列在LabVIEW中遞歸的實現(xiàn)方式。case結(jié)構(gòu)有兩個分支,當n<=2時直接輸出f(

39、n)=1;當n>=3時,輸出f(n)=f(n-1)+f(n-2)。此時需要把VI設(shè)置為可重入狀態(tài)。圖 34 Fibonacci數(shù)列同理我們也可以使用這種遞歸的方式實現(xiàn)f(n)=n!的算法,從數(shù)學(xué)上可以寫作f(n)=n*f(n-1),其中n>=1,f(0)=1。具體的實例將不再詳述。此外,遞歸算法的效率比較低,在實際應(yīng)用中應(yīng)謹慎使用。打開Highlight工具,在Call By Reference Node運行時,程序是處于等待狀態(tài)的,只有被調(diào)用的VI運行完畢,主程序才會繼續(xù)執(zhí)行。這似乎無法解決在本節(jié)開頭提到的問題,那么是否存在一種動態(tài)調(diào)用方式使被調(diào)用的VI與主V

40、I之間分別獨立運行呢?答案是肯定的。VI本身是有很多的屬性和方法的,如圖 35所示。使用這些方法就可以動態(tài)控制VI的運行、停止和賦值,各個屬性節(jié)點和方法的具體含義見LabVIEW的幫助文檔。使用這種方式動態(tài)調(diào)用VI時,并不需要知道VI的輸入輸出接口。圖 35 VI Method圖 36是該使用“屬性節(jié)點和方法”實現(xiàn)動態(tài)調(diào)用的一個實例。在大多數(shù)應(yīng)用程序啟動時會顯示一個啟動畫面用來顯示版權(quán)、開發(fā)單位、軟件版本等信息,等待2秒之后關(guān)閉啟動界面并啟動應(yīng)用程序主界面。圖中使用了動態(tài)調(diào)用的方式啟動主程序(Main.vi)并使主程序獨立運行,首先運行程序后設(shè)置2秒鐘的延時;其次,將啟動畫面的界面設(shè)置為“隱藏”(并沒有退出內(nèi)存,只是隱藏了前面板),并且使用Open VI Reference獲取VI的句柄;然后使用FP.Open屬性打開主程序的前面板(只是打開

溫馨提示

  • 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論