1 引言 在BC3192測試程序的開(kāi)發(fā)過(guò)程中,最復雜的是儀器驅動(dòng)程序的開(kāi)發(fā)。同 VXI總線(xiàn)間進(jìn)行的每一步聯(lián)系和操作,都少不了儀器驅動(dòng)程序的幫助。 用LabWindows/CVI(以下簡(jiǎn)稱(chēng)Labwin)軟件可以開(kāi)發(fā)出儀器的驅動(dòng)程序。這主要是因為L(cháng)abwin具有一部分通用的儀器設備驅動(dòng)庫。有了它們,用戶(hù)可以比較容易地開(kāi)發(fā)出幾個(gè)系列的總線(xiàn)兼容設備驅動(dòng)程序。如RS?232儀器驅動(dòng)系列、 GPIB儀器驅動(dòng)系列、VXI總線(xiàn)系列驅動(dòng)程序,還有一些典型的特定驅動(dòng)程序的實(shí)例,如Fluke45DigitalMultimeter(VISAI/O)(Fluke45數字型萬(wàn)用表)、Hewlett Packard34401AMultimeter( VISA)(惠普34401A型萬(wàn)用表)等。 一個(gè)典型的驅動(dòng)程序由4部分組成。 第一部分是主程序,主要是由*.lib,*.obj,*.dll或*.c文件組成。 第二部分是包含文件(*.h),包括函數功能的定義,常量的聲明以及全局變量的聲明。 第三部分是設備功能面板部分(*.fp),包括樹(shù)狀功能信息定義。 第四部分是由ASCII碼構成的幫助文件(*.doc),它包括指導用戶(hù)的詳細驅動(dòng)程序幫助。 2 儀器驅動(dòng)程序的操作 對用戶(hù)來(lái)說(shuō),驅動(dòng)程序完成一種或多種儀器功能,整個(gè)驅動(dòng)程序庫由多組程序有選擇地構成。在Labwin的編程環(huán)境中選取儀器菜單,再從菜單中選取一個(gè)設備。這時(shí)將從屏幕中彈出一個(gè)功能面板,功能面板顯示儀器的一些交互控制。函數調用自動(dòng)生成的功能也隨之加入整個(gè)應用程序。即使不提供功能面板,也能以手工方式進(jìn)行驅動(dòng)函數的調用?偟貋(lái)說(shuō),設備驅動(dòng)程序包括用以執行高級設備相關(guān)任務(wù)的功能函數。當用戶(hù)把功能函數包含到程序中后,即使不了解設備的編程協(xié)議,也可以控制一個(gè)儀器正常運轉。對它們的應用,可以在很大程度上減輕編程人員的負擔。它們可以在軟件開(kāi)發(fā)中形成模塊化,并大大提高軟件的易用性和可維護性。 3 LabWindows/CVI開(kāi)發(fā)驅動(dòng)程序的優(yōu)勢 Labwin中設備的驅動(dòng)程序是比傳統概念中的驅動(dòng)程序更高一層的概念。他們免去了編程人員頻繁地同I/O端口打交道。它是放入用戶(hù)應用程序的一種高層的軟件功能。它不僅完全適用于目前各種標準的儀器設備,而且可對一大批老的儀器設備提供支持。 所有的Labwin應用的驅動(dòng)程序,傳遞時(shí)在可能的情況下都伴有源碼,并且很多都有完整的幫助文件。它們都是在Labwin的標準開(kāi)發(fā)環(huán)境下開(kāi)發(fā)的,用戶(hù)可以根據具體情況改造自己的程序,使它們更加強大并對自己的應用程序有更大的彈性。 開(kāi)發(fā)儀器驅動(dòng)程序包括外部接口模塊和內部設計模塊。 3.1 外部接口模塊 外部接口模塊如圖1所示。 功能主體:設備驅動(dòng)的代碼部分 程序員交互接口:圖形化的編程助手,把交互控件狀態(tài)轉化為代碼 程序員編程接口:調用各種函數 子程序接口:調用其它軟件模塊 3.2 內部設計模塊 內部設計模塊如圖2所示。 功能主體:設備驅動(dòng)的代碼部分。包括初始化(包括結構復位、自檢等)、設置函數(用一個(gè)軟件程序集來(lái)實(shí)現相應功能。各種設備都有特定的設置函數。)、動(dòng)作/狀態(tài)函數(動(dòng)作函數使儀器開(kāi)始和停止測試,狀態(tài)函數可獲得儀器操作當前和即將出現的狀態(tài)。)、數據函數(向儀器發(fā)送和接收數據)、終結函數(終結同儀器間的連接并釋放系統資源)、應用程序函數(高級面向測試和功能函數)。 4 儀器驅動(dòng)程序的設計 4.1 設計原則 在設計之前,必須進(jìn)行驅動(dòng)程序結構的設計,因為如果驅動(dòng)程序的結構比較明了,會(huì )使程序員設計應用程序時(shí)更有條理。 其次,一定要把設計的驅動(dòng)程序基于一個(gè)已設計好的核心驅動(dòng)程序(即Labwin自帶的驅動(dòng)程序庫)、或者是由一個(gè)核心驅動(dòng)程序演化出來(lái)的驅動(dòng)程序。 最后,以一個(gè)明確的步驟來(lái)編寫(xiě)你的儀器驅動(dòng)程序(將在后面介紹)。 4.2 設計步驟 (1)命名這個(gè)驅動(dòng)程序。 (2)定義這個(gè)驅動(dòng)程序的功能和類(lèi)。 (3)建立一個(gè)驅動(dòng)程序的功能樹(shù)。在Labwin中的功能樹(shù)都以*.fp模式存儲,并在引用時(shí)以層次化形式出現,并且在各分支功能上加幫助信息。 (4)對于程序中的每個(gè)函數: ——對于函數的參數定義包括變量類(lèi)型、變量范圍、錯誤代碼等相關(guān)信息; ——在功能面板上實(shí)現新功能的創(chuàng )建,包括對功能面板和其中各個(gè)控件的幫助信息; ——為執行功能函數寫(xiě)代碼; ——檢驗代碼執行效果。 (5)為最終的設備源程序創(chuàng )建包含文件,包括函數定義和常量聲明。 4.3 兩個(gè)輔助工具介紹 (1)功能樹(shù)的編輯器 用圖3所示的是功能樹(shù)編輯器,可以靈活地添加和刪除各種函數,可從各個(gè)分支進(jìn)入具體的函數定義功能面板編輯器。 圖4所示的功能面板編輯器,可以控件的形式描述諸如函數參數、返回值、參考說(shuō)明等函數的相關(guān)信息。隨著(zhù)各種控件的加入,相應的源代碼也被實(shí)時(shí)地翻譯在面板下方的文本框中。 4.4 自定義的數據類(lèi)型 控件的使用方法相當簡(jiǎn)單,只需補充常說(shuō)的可移植性問(wèn)題,這一點(diǎn)同數據的定義是分不開(kāi)的。Labwin對于驅動(dòng)程序開(kāi)發(fā)有自己專(zhuān)門(mén)的一套數據類(lèi)型,它們可以精確地定義參數的類(lèi)型和大小,而且它們具有很好的可移植性。各種定義如表1所示。 表1各種定義 4.5 函數定義的方法 驅動(dòng)程序函數調用的返回值也與眾不同,VISA/IO(Labwin中的虛擬設備接口)定義了一種非常有用的調用設備函數時(shí)使用的宏,如表2所示。 表2函數的定義 因為沿用了在Pascal語(yǔ)言中調用在DLL程序驅動(dòng)的習慣,當用戶(hù)在Labwin的環(huán)境調用用戶(hù)定義函數時(shí),把宏_VI_FUNC(表示任何用戶(hù)函數)翻譯成_pascal,而使用外部編譯器編譯時(shí),則把宏解釋成_far_pascal_export。同樣在Labwin中,_VI_FAR(表示用戶(hù)函數中任何的數組參數和輸出變量)被翻譯成空,而用其它編譯程序時(shí),被翻譯成_far。 如下面這個(gè)函數 : ViStatus _VI_FUNC tek2430a_read_waveform (ViSession instrSession, ViReal64 _VI_FAR wvfm[], ViReal64 _VI_FAR * xin, ViReal64 _VI_FAR * trig_off); 在 LabWindows/CVI環(huán)境時(shí),表示為: ViStatus _pascal tek2430a_read_waveform (ViSession instrSession, ViReal64 wvfm[], ViReal64 * xin, ViReal64 * trig_off); 而在其它編譯環(huán)境下,表示為: ViStatus _far _pascal _export tek2430a_read_waveform (ViSession instrSession, ViReal64 _far wvfm[], ViReal64 _far * xin, ViReal64 _far * trig_off); 5 在BC3192測試程序中的應用實(shí)例 VXI的設備驅動(dòng)程序包括以下幾個(gè)主要功能。首先是分配設備的地址指針,這需要定義動(dòng)態(tài)鏈接庫的代碼段和數據段為可移動(dòng)和可刪除,因為要用基指針指向每一個(gè)I/O動(dòng)作,所以代碼段和數據段是不定的;其次是VXI總線(xiàn)寄存器的寫(xiě)入和讀取動(dòng)作,這些操作需要我們使用剛得到的設備地址指針;再次是向緩存中讀取和寫(xiě)入信息。另外,還有初始化,以及系統固定延遲時(shí)間等一系列功能。 在BC3192的測試程序中,結合Labwin自帶的VXI總線(xiàn)的設備驅動(dòng)程序,編寫(xiě)了一個(gè)簡(jiǎn)單的VXI驅動(dòng)程序。它存于程序的根目錄中,有4個(gè)支持文件,分別是vxirw.c、vxirw.dll、vxirw.h以及vxirw.lib。在我們的程序中,由于考慮到工作的效率,決定使用在VisualC++1.5的編譯環(huán)境下,編譯vxirw.c和vxirw.h程序,生成vxirw.dll及vxirw.lib的高效方法。這是由于Labwin使用一種LCC內建解釋器對程序進(jìn)行解釋?zhuān)湫蔬h不如直接使用動(dòng)態(tài)鏈接庫方便。用VC編譯器編譯的動(dòng)態(tài)鏈接文件,可以在Labwin的函數中方便地進(jìn)行調用。而且其效率同VC自身的調用不相上下。 如下面代碼所示,正是使用了剛才所表示的函數調用方法。 void FAR PASCAL __export __loadds ReadReg(UINT La, UINT Offset, UINT FAR * Data) /* 這 是 用 于 讀 取 總 線(xiàn) 寄 存 器 的 函 數 。 * / { /* * Data=(UINT)(* (pPointer+ La* 32+ Offset/2)); * / /* get the address pointer * / GetPointer(La); /* 調用La全局變量取得寄存器地址* /* read register * / * Data=(UINT)(* (pPointer+ Offset/2)); / *把寄存器中的值通過(guò)偏移地址取出* / /* free the selector * / FreeSelector(wSelector);/*釋放在取寄存器的值時(shí)所用到的字選擇臨時(shí)變量。 * / } 程序的調用要熟悉大量硬件的特性,不屬于軟件總體設計之列,在此不再介紹。 6 結論 LabWindows這種以C語(yǔ)言為中心的編程方式有其優(yōu)勢,所帶的C語(yǔ)言的功能比較靈活,而又便于開(kāi)發(fā)一些大型的工程。它的類(lèi)庫的功能又可以開(kāi)放地進(jìn)行擴充,使系統的功能得到進(jìn)一步增強。相對地,新型編程方式只能在固定的自帶環(huán)境中運行,而且在表達復雜關(guān)系時(shí),流程圖的聯(lián)系方式有很大的局限性。所以,Labwindows的編程方式在一段時(shí)間內將仍然擁有其地位。而今后的發(fā)展很可能是把兩種編程方法進(jìn)行集成,使我們在建立流程圖后可以生成大部分程序代碼,而細微的地方又可以進(jìn)行C語(yǔ)言的調整。這樣,我們的編程人員將擁有更方便的編程工具。 |