用Borland C 3.1實現外設與Windows應用程式實時通訊

才智咖 人氣:2.98W
用Borland C 3.1實現外設與Windows應用程式實時通訊
摘要該文提出了一種在Windows3.1保護模式下,通過動態連線庫(DLL)生成中斷服務程式程式碼,實現外設與Windows應用程式實時通訊的有效方法。

一、前言
計算機的日益普及和計算機技術日益成熟,使得計算機在工業控制監測中的應用漸漸深入。但工業應用不同於其它方面,它要求有較強的實時性。現在有很多的DOS軟體在執行過程中通過掛接外部中斷方式實現DOS應用軟體與外設的實時通訊,這種方法實現起來十分簡單。而在Windows中應用程式能否也能夠利用外部硬中斷實現外設與Windows應用程式的實時通訊呢?答案是肯定的。這裡的關鍵是要解決好中斷程式碼與Windows應用程式相互之間交換資訊的問題。
從外設傳送非同步的硬中斷,通過中斷處理程式傳遞一條資訊給Windows應用程式。這時可以初始化相關埠,準備好資料,然後進行資料傳送,從而做到實時通訊。
實現Windows應用程式響應外部中斷的方法有很多,如Microsoft公司自己開發的SDK、DDK軟體包,使用嵌入式彙編等等。本文將介紹一種在BC 3.1的基礎上利用Windows3.1擁有的一些功能實現Windows實時通訊的例項。

二、中斷程式碼的位置
在Windows中,幾乎所有的非同步事件都是由中斷處理程式來管理的。中斷處理程式包含在裝置驅動程式中,由Windows在環境初始化中安裝。例如,KEYBOARD.DRV、MOUSE.DRV和COMM.DRV均含有中斷處理程式,以處理相應的鍵盤、滑鼠和序列口的非同步中斷。可以仿照標準裝置驅動程式,編寫中斷處理程式碼,以響應外設的通訊請求,從而完成一次實時通訊。
中斷程式碼既可以包含在應用程式的可執行程式碼中,也可以包含在動態連線庫(DLL)中。包含在應用程式中的程式碼只能在一個程式中使用,而在動態連線庫中的程式碼則可以在Windows系統中所有的應用程式所共享。這樣不僅在整個Windows系統中只有一箇中斷程式碼的副本,提高了記憶體的使用效率,更重要的是可以防止由於同時存在多箇中斷程式碼的副本而發生衝突。本文將在DLL中編制中斷處理程式。
當動態連線庫被裝入時,要呼叫DLL庫的.入口點LibMain(),利用這一點可以執行一些初始化工作,可以分配一些記憶體塊,可以初始化一些全域性變數或者靜態變數,可以安裝中斷服務程式的程式碼等等。例如:
voidinterrupt(oldIsr)(--CPPARGS)
/*舊的中斷服務程式地址*/
LibMain(HANDLEhInstance,WORDwDataSeg,WORDcbHeapSize,L
PSTR
lpszCmdLine)
{

oldIsr=getvect(IRQNum);
/*IRQNum指中斷號*/
setvect(IRQNum,newIsr);
/*newIsr指新中斷服務程式程式碼*/
return(1);
}
函式setvect()既可在真實模式下,也可在保護模式下設定中斷處理向量。
上述程式碼也可以放在一個由使用者設定的引出(export)函式中,在應用程式中使用者可以呼叫此引出函式來安裝中斷服務程式程式碼。
由於中斷可以在任何時刻發生,中斷程式碼必須駐留在記憶體中,並且在應用程式執行的過程中一直處於某一固定記憶體中。這一點無論是在真實模式還是在保護模式下都是一致的。
在DLL的模組定義檔案中應注意:

語句為固定程式碼段,即FIXED;

RTS語句要引出被應用程式和其它DLL用作入口點的函式。

三、通訊機制
編寫實時通訊例程關鍵在於必須認識到,非同步事件對應用程式的觸發是非同步發生的,不在Windows的訊息處理機制和多工範圍內。為了使通訊例程能夠正確地工作,通訊例程必須通知Windows有非同步事件發生,且不能打斷應用程式的任務管理或訊息流。要作到這一點,通訊例程必須通過呼叫PostMessage或PostAppMessage函式嚮應用程式的訊息佇列中加入一條訊息。
需要注意的是,在DLL中呼叫PostMessage(HWNDhwnd,…)時,必須先確定hwnd的實際值,可以通過使用引出函式的辦法來實現,如下所示:
staticHWNDhWndApp;
voidFARPASCALSetIsrWin(HWNDhwnd)
{
hWndApp=hwnd;
}
然後在應用程式的視窗函式中,對WM-CREATE訊息進行處理時呼叫此函式來初始化DLL中的靜態變數hWndApp: