VFP 環(huán) 境 下 實(shí) 時(shí) 數(shù) 據(jù) 采 集 的 實(shí) 現(xiàn) <BR> 東 南 大 學(xué) 熱 能 所(210096)---- 周 衛(wèi) 平 </P><P> --- VFP 作 為 新 一 代 數(shù) 據(jù) 庫 管 理 系 統(tǒng), 在 數(shù) 據(jù) 的 存 取、 編 輯、 顯 示、 處 理 等 方 面 具 有 強(qiáng) 大 和 豐 富 的 工 具, 在 國 內(nèi) 外 得 到 了 廣 泛 應(yīng) 用。 在 許 多 工 業(yè) 應(yīng) 用 中, 往 往 要 對 現(xiàn) 場 模 擬 數(shù) 據(jù) 進(jìn) 行A/D 轉(zhuǎn) 換 且 實(shí) 時(shí) 處 理, 由 于VFP 不 能 對 端 口 進(jìn) 行 直 接 訪 問, 因 而 無 法 實(shí) 現(xiàn) 數(shù) 據(jù) 采 集。 幸 好VFP 提 供 了DDE 功 能。DDE 是Windows 應(yīng) 用 程 序 之 間 進(jìn) 行 動(dòng) 態(tài) 信 息 傳 遞 和 共 享 的 一 個(gè) 消 息 協(xié) 議, 利 用DDE 可 實(shí) 現(xiàn)Windows 的 服 務(wù) 程 序 和 客 戶 程 序 的 相 互 獨(dú) 立 運(yùn) 行, 具 有 很 好 的 實(shí) 時(shí) 性。 在 實(shí) 踐 中, 我 們 利 用 高 級 語 言BorLand C++ for Windows 實(shí) 現(xiàn)96 路A/D 數(shù) 據(jù) 采 集, 并 以 此 為 服 務(wù) 程 序; 在VFP 環(huán) 境 下 建 立 客 戶 程 序, 將 服 務(wù) 程 序 傳 遞 過 來 的 數(shù) 據(jù) 及 時(shí) 進(jìn) 行 運(yùn) 算 處 理 后, 存 入 數(shù) 據(jù) 庫, 并 作 為 各 種 表 單、 報(bào) 表、 曲 線 的 數(shù) 據(jù) 源。 該 方 法 在VB 或ACCESS 97 環(huán) 境 下 同 樣 適 用, 只 要 將 客 戶 程 序 稍 加 修 改 即 可。 下 面 就 如 何 實(shí) 現(xiàn)VFP 環(huán) 境 下 的 實(shí) 時(shí) 數(shù) 據(jù) 采 集 作 一 介 紹。 <BR> 1. 建 立 數(shù) 據(jù) 采 集 服 務(wù) 程 序 <BR> ---- 服 務(wù) 程 序 包 括 二 個(gè) 基 本 部 分: 其 一 是WinMain 入 口 函 數(shù), 它 主 要 完 成 一 此 初 始 化 任 務(wù), 建 立 一 個(gè) 名 為hwnd 的 原 始 數(shù) 據(jù) 顯 示 窗 口, 服 務(wù) 程 序 名 為PFBCdas。 其 二 是 應(yīng) 用 程 序 功 能 函 數(shù)MainWndProc。 下 面 是 程 序 清 單( 因 篇 幅 關(guān) 系, 在 此 省 去WinMain 函 數(shù))。 <BR> #define AD_Interval 1000 //采樣周期為 1000ms<BR> #define base 0x280 // A/D采樣板基地址<BR> /* base+k (k=1,2,…14)為A/D板各寄存器地址 */<BR> #include <BR> #include <BR> #include <BR> #include <BR> #include <BR> #include <BR> #include <BR> #include <BR> #include <BR> int i, j, k , AD_Status, idTimer;<BR> int AD_Data[8][16]; // A/D數(shù)據(jù)存儲單元 <BR> int DdeAdviseStatus=0;<BR> char buf[64], DDEbuf[2048]; //數(shù)據(jù)暫存緩沖器 <BR> char szAppName[]="PFBCdas"; //服務(wù)程序名<BR> char szDdeTopic[]="AD001"; //主題名 <BR> char szDdeItem[]="DATA"; // 數(shù)據(jù)項(xiàng)名<BR> long FAR PASCAL _export MainWndProc(HWND, UINT, UINT, LONG) ;<BR> long FAR PASCAL _export MainWndProc (HWND hwnd, UINT message, UINT <BR> wParam, LONG lParam) <BR> //應(yīng)用程序功能函數(shù) <BR> {<BR> ATOM aAppName,aTopic;<BR> ATOM aItem;<BR> GLOBALHANDLE hDdeData;<BR> DDEDATA FAR *lpDdeData;<BR> static HWND hwndClient;<BR> switch (message)<BR> { <BR> case WM_CREATE:<BR> idTimer=SetTimer(hwnd,NULL,AD_Interval,NULL); <BR> //打開定時(shí)器<BR> outportb(base+11,0x10); //選擇軟件觸發(fā)方式<BR> outportb(base+9,1); //選擇輸入信號放大倍數(shù)為10<BR> outportb(base+14,0);<BR> outportb(base+13,0); //清A/D完成位<BR> outportb(base+10,0); //選擇通道0<BR> return 0;<BR> case WM_TIMER:<BR> for(i=0;i<6;i++)<BR> for(j=0;j<16;j++) //采樣點(diǎn)為6*16=96個(gè)<BR> {<BR> outportb(base+13,j); <BR> outportb(base+10,i); <BR> outportb(base+12,0); //啟動(dòng)A/D轉(zhuǎn)換<BR> do AD_Status=inportb(base+5);<BR> while ((AD_Status&0x10)==0x10); <BR> //判轉(zhuǎn)換是否結(jié)束? <BR> AD_Data[i][j]=(inportb(base+5)&0x0f)*256+inportb(base+4); <BR> /* 讀A/D轉(zhuǎn)換后的數(shù)字值 */<BR> }<BR> _strdate(buf); //取采樣日期<BR> strcpy(DDEbuf,buf);<BR> strcat(DDEbuf,",");<BR> _strtime(buf); //取采樣時(shí)間<BR> strcat(DDEbuf,buf);<BR> strcat(DDEbuf,",");<BR> for(i=0;i<6;i++)<BR> for(j=0;j<16;j++)<BR> {<BR> char temp[32];<BR> strcat(itoa(AD_Data[i][j],buf,10),",");<BR> /*各采樣數(shù)據(jù)之間以逗號分隔*/<BR> strcat(DDEbuf,buf);<BR> }<BR> if(DdeAdviseStatus!=0) //如果建立了DDE服務(wù)<BR> {<BR> aItem = GlobalAddAtom (szDdeItem) ;<BR> //添加DDE數(shù)據(jù)項(xiàng)為全局原子<BR> hDdeData = GlobalAlloc (GHND | GMEM_DDESHARE,<BR> sizeof (DDEDATA) + strlen (DDEbuf)) ;<BR> /*給采樣數(shù)據(jù)分配全局內(nèi)存塊*/<BR> lpDdeData = (DDEDATA FAR *) GlobalLock (hDdeData) ;<BR> lpDdeData->fResponse = 0 ;<BR> lpDdeData->fRelease = 1 ;<BR> lpDdeData->fAckReq = 0 ;<BR> lpDdeData->cfFormat = CF_TEXT ;<BR> //采樣數(shù)據(jù)為文本格式<BR> lstrcpy ((LPSTR) lpDdeData->value,DDEbuf) ;<BR> /*將采樣數(shù)據(jù)從緩沖器放至DDE內(nèi)存*/<BR> GlobalUnlock (hDdeData) ;<BR> if(!PostMessage(hwndClient,WM_DDE_DATA,hwnd,<BR> MAKELONG(hDdeData,aItem))) //發(fā)送DDE數(shù)據(jù)<BR> {<BR> GlobalFree(hDdeData); <BR> //若發(fā)送失敗,則釋放資源<BR> GlobalDeleteAtom(aItem); <BR> }<BR> }<BR> return 0;<BR> case WM_DDE_INITIATE: //DDE初始化<BR> hwndClient=wParam;<BR> hdc=GetDC(hwnd);<BR> aAppName=GlobalAddAtom(szAppName);<BR> aTopic=GlobalAddAtom(szDdeTopic);<BR> if ((LOWORD (lParam) == NULL || LOWORD (lParam) == aAppName)<BR> && (HIWORD (lParam) == NULL || HIWORD (lParam) == aTopic))<BR> { // 發(fā)送服務(wù)程序名和主題名<BR> SendMessage(hwndClient,WM_DDE_ACK,hwnd,<BR> MAKELONG(aAppName,aTopic));<BR> } <BR> else<BR> {<BR> GlobalDeleteAtom (aAppName) ;<BR> GlobalDeleteAtom (aTopic) ;<BR> }<BR> return 0 ;<BR> case WM_DDE_TERMINATE: //關(guān)閉DDE服務(wù)<BR> hwndClient=wParam; <BR> PostMessage (hwndClient, WM_DDE_TERMINATE, hwnd, 0L) ;<BR> return 0 ;<BR> case WM_DDE_ADVISE: //建立DDE服務(wù)<BR> DdeAdviseStatus=1; //已建立DDE服務(wù)標(biāo)志<BR> hwndClient=wParam;<BR> aItem=HIWORD(lParam);<BR> if(!PostMessage(hwndClient, WM_DDE_ACK, hwnd,<BR> MAKELONG(0x8000,aItem))) //發(fā)送DDE應(yīng)答<BR> {<BR> GlobalDeleteAtom(aItem);<BR> }<BR> return 0;<BR> case WM_DESTROY: //程序失敗處理<BR> PostQuitMessage (0) ;<BR> return 0 ;<BR> }<BR> return DefWindowProc (hwnd, message, wParam, lParam) ;<BR> }</P><P> 2. 建 立VFP 環(huán) 境 下 的 客 戶 端 程 序 <BR> ---- 首 先 建 立 和 服 務(wù) 程 序 之 間 的 通 道, 然 后 將 服 務(wù) 程 序 傳 遞 來 的 數(shù) 據(jù) 放 至 字 符 串DATA 內(nèi), 再 通 過 自 定 義 函 數(shù)recdata 將 采 樣 數(shù) 據(jù) 存 入 數(shù) 據(jù) 庫 中 待 用。 下 面 是 客 戶 程 序 清 單。 <BR> PROCEDURE getdata<BR> PUBLIC mchannel<BR> mchannel = DDEInitiate('PFBCdas','AD001') <BR> &&建立客戶程序和服務(wù)程序間的通道 <BR> IF mchannel !=-1<BR> =DDEadvise(mchannel,'DATA','recdata',2)<BR> &&建立DDE熱連接,數(shù)據(jù)項(xiàng)為DATA<BR> ENDIF<BR> RETURN</P><P> PROCEDURE recdata &&用戶自定義函數(shù)<BR> PARAMETERS channel,action,item,data,format,status<BR> PRIVATE newdata<BR> newdata=""<BR> IF action='ADVISE' &&若連接成功<BR> newdata=DATA &&將采樣數(shù)據(jù)傳遞至newdata<BR> do process with newdata &&調(diào)用數(shù)據(jù)處理程序 <BR> ELSE<BR> IF action='TERMINATE' <BR> = DDETerminate(mchannel) &&關(guān)閉通道<BR> ENDIF<BR> ENDIF<BR> RETURN</P><P> PROCEDURE process<BR> PARAMETER newdata<BR> PRIVATE i,loc1,loc2<BR> DIMENSION gdata(98)<BR> * 從字符串 newdata中取采樣值<BR> gdata(97)=CTOD(left(newdata,8)) &&取日期值<BR> gdata(98)=SUBSTR(newdata,10,8) &&取時(shí)間值<BR> * 從字符串newdata的相鄰逗號間取采樣值,<BR> 并將采樣值轉(zhuǎn)化為毫伏值<BR> FOR i=3 TO 98<BR> loc1=ATC(",", newdata, (i-1))<BR> loc2=ATC(",", newdata, (i))<BR> gdata(i-2)=VAL(SUBSTR(newdata,(loc1+1),(loc2-loc1)))<BR> *0.024414062<BR> ENDFOR<BR> IF USED("onedata")<BR> SELECT onedata<BR> ELSE<BR> SELECT 0<BR> USE onedata ALIAS onedata<BR> &&打開數(shù)據(jù)庫onedata<BR> ENDIF<BR> APPEND FROM ARRAY gdata<BR> &&將數(shù)組gdata中的轉(zhuǎn)換數(shù)據(jù)添加到數(shù)據(jù)庫中 <BR> RETURN </P><P> ---- 聯(lián) 系 地 址: 南 京 市 東 南 大 學(xué) 熱 能 工 程 研 究 所 <BR> ---- 郵 編:210096 <BR> ---- 聯(lián) 系 人: 周 衛(wèi) 平 <BR> ---- 電 話:(025)3794191 <BR> ---- EMAIL 地 址:qhye@seu.edu.cn
|