网络开发 调用API函数 报表打印 常用技术 经验汇总 控件使用 软件工程 数据处理
您的位置:首页 >> vfp教程 >> 网上文摘 >> 数据处理 >> 正文

VFP环境下实时数据采集的实现
周卫平 出处:网络

----VFP作为新一代数据库管理系统,在数据的存取、编辑、显示、处理等方面具有强大和丰富的工具,在国内外得到了广泛应用。在许多工业应用中,往往要对现场模拟数据进行A/D转换且实时处理,由于VFP不能对端口进行直接访问,因而无法实现数据采集。幸好VFP提供了DDE功能。DDE是Windows应用程序之间进行动态信息传递和共享的一个消息协议,利用DDE可实现Windows的服务程序和客户程序的相互独立运行,具有很好的实时性。在实践中,我们利用高级语言BorLand C++ for Windows实现96路A/D数据采集,并以此为服务程序;在VFP环境下建立客户程序,将服务程序传递过来的数据及时进行运算处理后,存入数据库,并作为各种表单、报表、曲线的数据源。该方法在VB或ACCESS97环境下同样适用,只要将客户程序稍加修改即可。下面就如何实现VFP环境下的实时数据采集作一介绍。1.建立数据采集服务程序
----服务程序包括二个基本部分:其一是WinMain入口函数,它主要完成一此初始化任务,建立一个名为hwnd的原始数据显示窗口,服务程序名为PFBCdas。其二是应用程序功能函数MainWndProc。下面是程序清单(因篇幅关系,在此省去WinMain函数)。

#define AD_Interval 1000 //采样周期为 1000ms
#define base 0x280 // A/D采样板基地址
/* base+k (k=1,2,…14)为A/D板各寄存器地址 */
#include
#include
#include
#include
#include
#include
#include
#include
#include
int i, j, k , AD_Status, idTimer;
int AD_Data[8][16]; // A/D数据存储单元
int DdeAdviseStatus=0;
char buf[64], DDEbuf[2048]; //数据暂存缓冲器
char szAppName[]="PFBCdas"; //服务程序名
char szDdeTopic[]="AD001"; //主题名
char szDdeItem[]="DATA"; // 数据项名
long FAR PASCAL _export MainWndProc(HWND, UINT, UINT, LONG) ;
long FAR PASCAL _export MainWndProc (HWND hwnd, UINT message, UINT
wParam, LONG lParam)
//应用程序功能函数
{
ATOM aAppName,aTopic;
ATOM aItem;
GLOBALHANDLE hDdeData;
DDEDATA FAR *lpDdeData;
static HWND hwndClient;
switch (message)
{
case WM_CREATE:
idTimer=SetTimer(hwnd,NULL,AD_Interval,NULL);
//打开定时器
outportb(base+11,0x10); //选择软件触发方式
outportb(base+9,1); //选择输入信号放大倍数为10
outportb(base+14,0);
outportb(base+13,0); //清A/D完成位
outportb(base+10,0); //选择通道0
return 0;
case WM_TIMER:
for(i=0;i<6;i++)
for(j=0;j<16;j++) //采样点为6*16=96个
{
outportb(base+13,j);
outportb(base+10,i);
outportb(base+12,0); //启动A/D转换
do AD_Status=inportb(base+5);
while ((AD_Status&0x10)==0x10);
//判转换是否结束?
AD_Data[i][j]=(inportb(base+5)&0x0f)*256+inportb(base+4);
/* 读A/D转换后的数字值 */
}
_strdate(buf); //取采样日期
strcpy(DDEbuf,buf);
strcat(DDEbuf,",");
_strtime(buf); //取采样时间
strcat(DDEbuf,buf);
strcat(DDEbuf,",");
for(i=0;i<6;i++)
for(j=0;j<16;j++)
{
char temp[32];
strcat(itoa(AD_Data[i][j],buf,10),",");
/*各采样数据之间以逗号分隔*/
strcat(DDEbuf,buf);
}
if(DdeAdviseStatus!=0) //如果建立了DDE服务
{
aItem = GlobalAddAtom (szDdeItem) ;
//添加DDE数据项为全局原子
hDdeData = GlobalAlloc (GHND | GMEM_DDESHARE,
sizeof (DDEDATA) + strlen (DDEbuf)) ;
/*给采样数据分配全局内存块*/
lpDdeData = (DDEDATA FAR *) GlobalLock (hDdeData) ;
lpDdeData->fResponse = 0 ;
lpDdeData->fRelease = 1 ;
lpDdeData->fAckReq = 0 ;
lpDdeData->cfFormat = CF_TEXT ;
//采样数据为文本格式
lstrcpy ((LPSTR) lpDdeData->Value,DDEbuf) ;
/*将采样数据从缓冲器放至DDE内存*/
GlobalUnlock (hDdeData) ;
if(!PostMessage(hwndClient,WM_DDE_DATA,hwnd,
MAKELONG(hDdeData,aItem))) //发送DDE数据
{
GlobalFree(hDdeData);
//若发送失败,则释放资源
GlobalDeleteAtom(aItem);
}
}
return 0;
case WM_DDE_INITIATE: //DDE初始化
hwndClient=wParam;
hdc=GetDC(hwnd);
aAppName=GlobalAddAtom(szAppName);
aTopic=GlobalAddAtom(szDdeTopic);
if ((LOWORD (lParam) == NULL || LOWORD (lParam) == aAppName)
&& (HIWORD (lParam) == NULL || HIWORD (lParam) == aTopic))
{ // 发送服务程序名和主题名
SendMessage(hwndClient,WM_DDE_ACK,hwnd,
MAKELONG(aAppName,aTopic));
}
else
{
GlobalDeleteAtom (aAppName) ;
GlobalDeleteAtom (aTopic) ;
}
return 0 ;
case WM_DDE_TERMINATE: //关闭DDE服务
hwndClient=wParam;
PostMessage (hwndClient, WM_DDE_TERMINATE, hwnd, 0L) ;
return 0 ;
case WM_DDE_ADVISE: //建立DDE服务
DdeAdviseStatus=1; //已建立DDE服务标志
hwndClient=wParam;
aItem=HIWORD(lParam);
if(!PostMessage(hwndClient, WM_DDE_ACK, hwnd,
MAKELONG(0x8000,aItem))) //发送DDE应答
{
GlobalDeleteAtom(aItem);
}
return 0;
case WM_DESTROY: //程序失败处理
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
2. 建 立VFP 环 境 下 的 客 户 端 程 序
---- 首 先 建 立 和 服 务 程 序 之 间 的 通 道, 然 后 将 服 务 程 序 传 递 来 的 数 据 放 至 字 符 串DATA 内, 再 通 过 自 定 义 函 数recdata 将 采 样 数 据 存 入 数 据 库 中 待 用。 下 面 是 客 户 程 序 清 单。 PROCEDURE getdata
PUBLIC mchannel
mchannel = DDEInitiate('PFBCdas','AD001')
&&建立客户程序和服务程序间的通道
IF mchannel !=-1
=DDEadvise(mchannel,'DATA','recdata',2)
&&建立DDE热连接,数据项为DATA
ENDIF
RETURN

PROCEDURE recdata &&用户自定义函数
PARAMETERS channel,action,item,data,format,status
PRIVATE newdata
newdata=""
IF action='ADVISE' &&若连接成功
newdata=DATA &&将采样数据传递至newdata
do process with newdata &&调用数据处理程序
ELSE
IF action='TERMINATE'
= DDETerminate(mchannel) &&关闭通道
ENDIF
ENDIF
RETURN

PROCEDURE process
PARAMETER newdata
PRIVATE i,loc1,loc2
DIMENSION gdata(98)
* 从字符串 newdata中取采样值
gdata(97)=CTOD(left(newdata,8)) &&取日期值
gdata(98)=SUBSTR(newdata,10,8) &&取时间值
* 从字符串newdata的相邻逗号间取采样值,
并将采样值转化为毫伏值
FOR i=3 TO 98
loc1=ATC(",", newdata, (i-1))
loc2=ATC(",", newdata, (i))
gdata(i-2)=VAL(SUBSTR(newdata,(loc1+1),(loc2-loc1)))
*0.024414062
ENDFOR
IF USED("onedata")
SELECT onedata
ELSE
SELECT 0
USE onedata ALIAS onedata
&&打开数据库onedata
ENDIF
APPEND FROM ARRAY gdata
&&将数组gdata中的转换数据添加到数据库中
RETURN
---- 联 系 地 址: 南 京 市 东 南 大 学 热 能 工 程 研 究 所
---- 邮 编:210096
---- 联 系 人: 周 卫 平
---- 电 话:(025)3794191
---- EMAIL 地 址:qhye@seu.edu.cn

[返回]

     

首页 | 设为首页 | 加入收藏 | 关于本站 | 友情链接 | 版权声明

     
 
Copyright© www.bianceng.cn Powered by 编程入门网 All Rights Reserved
吉ICP备06005558号