基于DDE协议的Modbus Plus与Ethernet数据交换
hconv4=ddeconnecttotopic(idinst,szapp,sztopic4,hsztopic4);
if( hconv4 != null )
{
ddeautorequest(idinst,hconv4,szwidth,hszwidth);
}
此处的ddeconnecttotopic和ddeautorequest为自定义的函数
hconv ddeconnecttotopic(dword idddeinst, lpctstr szapp, lpctstr
sztopic, hsz * hsztopic)
{
hsz
hszapp=ddecreatestringhandle(idddeinst,szapp,cp_winunicode);
*
hsztopic=ddecreatestringhandlew(idddeinst,sztopic,cp_winunicode);
return ddeconnect(idddeinst,hszapp,*hsztopic,null);
}
使用ddecreatestringhandle来获取服务器和主题名的字符句柄,使用ddeconnect来建立指定服务下的指定的主题的连接。之后使用ddeautorequest函数来向dde服务器请求置顶项目名的数据,在数据发生变化后dde服务器会自动将新的数据发送给客户端,客户端在回调函数中就可以获取到新的数据,具体方法见下文。如果某个主题下有多个项目需要处理,都用ddeautorequest来处理即可,此函数的实现如下:
void ddeautorequest(dword idddeinst, hconv hconv, lpctstr
szitem, hsz * hszitem)
{
*hszitem=ddecreatestringhandle(idddeinst,szitem,cp_winunicode);
hddedata hdata=ddeclienttransaction
(null,0,hconv,*hszitem,cf_text,xtyp_advstart| xtypf_ackreq,5000,
null);
}
接下来就可以通过dde的回调函数来获取数据了。
hddedata callback ddecallback(uint utype,uint ufmt,hconv
hconv,hsz hsz1,hsz hsz2,hddedata hdata,
dword dwdata1,dword dwdata2)
{
switch( utype )
{
case xtyp_advdata: //处理dde数据
if( ufmt != cf_text )
return dde_fnotprocessed;
memset(szbuffer,0,64); //初始化缓冲区
datalen=ddegetdata(hdata,null,64,0);//获取数据的长度
ddegetdata(hdata,(unsigned char* )szbuffer,datalen,0);//获取数据
if( hsz1==hsztopic4 hsz2 == hszwidth ) //判断数据对应于那个数据项,并作出具体处理
{
_atoflt(fltval,szbuffer); //dde的数据以字符串形式创送过来的,这里将它转换成数值
ptele1101->msgblock1.stripwidth=fltval.f; //将数字存入缓冲区
}
return ( hddedata )dde_fack;
}
return 0;
}
本例中dde回调函数要处理的dde项目不止一个,任意一个dde项目的值发生变化时,回调函数都会被自动调用一次,具体实现时只需要用if语句对hsz1和hsz2进行逐一比较即可处理所有的项目。缓冲区ptele1101用于存储通过以太网发送到板型仪的数据,下文中将详细介绍。
上面介绍的方法用于从dde服务器中获取mb+网上的数据,那么如何将数据写入到mb+网呢,同样还是使用ddeml库中提供的方法,具体如下:
ddepoke(idinst,hconv4,szwidth,text(“1020”));
//写数据到mb+,设置宽度为1020mm
ddepoke为自定义函数,具体实现为:
void ddepoke(dword idinst, hconv hconv, tchar* szitem, tchar*
szdata)
{
hsz hszitem=ddecreatestringhandlew(idinst,szitem,cp_winunicode);
ddeclienttransaction((lpbyte)unicodetoansi(szdata),(dword)(lstrlenw(szdata)+1),hconv,
hszitem,cf_text,xtyp_poke,3000,null);
ddefreestringhandle(idinst,hszitem);
}
(3) 与以太网交换数据,这里使用的是socket协议。前面提到了缓冲区ptele1101,这里存储的是要传送到板型仪的数据。这是一个结构指针,定义如下:
typedef struct
{
teleheader msgheader; //消息头
tele1101block1 msgblock1; //消息第一部分
tele1101block2 msgblock2; //消息第二部分
tele1101block3 msgblock3; //消息第三部分
} tele1101, *ptele1101;
ptele1101 ptele1101;
这其中teleheader、tele1101block1、tele1101block2和tele1101block3也分别是一个结构,这里就不详述了。
本实例中使用另外一个线程来处理以太网的数据交换,这样不会中断处理dde数据的过程。
dword dwthreadid;
thread=createthread(null,0,(lpthread_start_routine )
sockthread,null,0,dwthreadid);
sockthread为线程的过程函数,具体实现如下:
void sockthread()
{
int i=0;
tchar buf[256];
initwinsock();//初始化socket
//创建并设置协议类型,地址和端口
socket socksrv=socket(af_inet,sock_stream,0);
sockaddr_in addrsrv;
addrsrv.sin_addr.s_un.s_addr=htonl(inaddr_any);
addrsrv.sin_family=af_inet;
addrsrv.sin_port=htons(5001);
//绑定并监听端口
bind(socksrv,(sockaddr*)addrsrv,sizeof(sockaddr));
listen(socksrv,5);
sockaddr_in addrclient;
int len=sizeof(sockaddr);
while (1) //程序正常运行时,始终接收连接请求
{
sockconn=accept(socksrv,(sockaddr*)addrclient,len);
zeromemory(buf,sizeof(buf));
__try
{
while (1) //连接建立后每50秒交换一次数据
{
len=send(sockconn,(char *)ptele1101,sizeof(tele1101),0);
len=recv(sockconn,(char *)ptele1102,sizeof(tele1102),0);
if (0==len || socket_error==len)
{
len=wsagetlasterror();
raiseexception(1,0,0,null);
}
sleep(50);
}
}
__except(exception_execute_handler)
{
closesocket(sockconn);
}
}
closesocket(socksrv);
wsacleanup();
}
这里ptele1102为接收数据的缓冲区,也是一个结构,定义与ptele1101类似,此处不详述。
从mb+网来的数据在使用dde协议获取后存入缓冲区ptele1101,发送到板型仪,从板型仪来的数据存入缓冲区ptele1102,相关数据再使用dde协议写回到mb+网,这样就实现了mb+网和以太网的数据交换。
4 结束语
本文介绍的数据交换的方法编程实现起来比较容易,代码量较少,能很好的解决异种网络间的数据交换的需求,并在单机架平整机板型控制系统中得到了成功的应用,取得了满意的效果。文中介绍的使用dde协议和socket协议处理数据的方式有较好的通用性,经过简单修改既可以用于其他的系统。另外通过简单的扩展,即可实现数据采集和分析的功能。可以广泛应用于工业控制的各个领域。
DDE Modbus Plus Ethernet 数据交换 相关文章:
- Windows Embedded CE 6.0开发初体验(04-26)
- Qt Embedded4.6.2与tslib1.4移植到arm平台(11-09)
- Windows Embedded开发者更新可供下载(09-12)
- Qt图形编程基础之:Qt/Embedded开发入门(09-13)
- 嵌入式电子地图数据分块组织研究(12-14)
- EmbeddedICE目标系统中的调试功能扩展部件(11-22)