1、引言
modbus plus(以下簡稱mb+)是一種針對工業控制應用的本地局域網系統。以太網是當今現有局域網采用的最通用的通信協議標準。其具有低成本、高可靠性、高速率、開放性好等特點,在工控領域得到了廣泛的應用。
動態數據交換(dde)是windows操作系統一直保持兼容的一種應用程序間的數據通信方式。對于很多直接和硬件打交道的應用程序,尤其是plc編程軟件,是一種較為可靠的通信方式。
本文通過某鋼廠單機架平整機板型改造過程中的實際應用,介紹使用vc2005在windows下實現pc與mb+網的dde通信并通過以太網實現與板型儀plc的數據交換。
2、系統簡要說明
本系統如圖1所示,包括生產控制plc組,mb+網,pc服務器,100m以太網,板型控制系統。通過pc服務器實現互聯。
圖1 單機架平整機板型控制系統
生產控制plc組由mb+網來連接,pc機上使用一塊sa-85的pci卡來連接到mb+,用于訪問各節點上的plc。pc機上另外使用一塊pci接口的以太網卡連接到以太網。板型儀提供了以太網接口,與pc機接入同一個局域網。
pc機上安裝mb+網的dde服務程序,以及本文介紹的自編程序。dde服務程序通過mb+網獲取plc上的數據,自編程序使用dde技術獲得數據,打包后使用tcp協議發送給板型儀。板型儀通過tcp協議將各種測量數據和狀態信號發給pc服務器,相關數據再通過dde協議送dde服務程序,最后通過mb+網送到相應的plc。
3、系統的具體實現
3.1 dde server軟硬件安裝方法
dde基于用戶/服務器原則,通過建立應用程序間的對話連接,根據不同的主題和項目進行數據通信。為了從服務器獲取數據,用戶使用一種固定的3級特殊訪問方式,這3級訪問分別為:服務(service)、主題(topic)和數據項(item)。
不同的硬件平臺所使用的dde數據通信硬件設備也不同,本文介紹的數據通信方法是針對mb+網而言的。pc平臺上使用sa-85的pci卡來連接mb+網。使用前需要配置好sa-85的網絡連接。
軟件上,使用wonderware公司提供的io server組件中的modicon modbus
plus(以下簡稱mbplus)來連接mb+并提供dde的方式來訪問數據的接口。此工具運行后如圖2所示。
圖2 mbplus連接
要使用此工具,還需要對它進行一些配置。從configure菜單中選擇adapter card setting,設置需要連接的適配器,因為我們只安裝了一個mb+的適配器,所以使用默認配置。之后就可以開始配置dde服務了。我們需要給每一個需要訪問的mb+網上的設備按照dde協議定義一個topic。選擇configure菜單下的topic definition,進行topic的配置,如圖3。
圖3、topic配置
這里的topic name 就是之后訪問dde服務的topic需要使用的名稱,每個topic需要定義不同的名稱,本系統共連接5個mb+網上的plc,分別定義為plc1、plc2、plc3、plc4、plc5。slave path 處定義的是不同設備的節點地址。配置好以后就可以使用dde協議來訪問mb+網上的數據了。
3.2 編程實現
在完成了mb+的dde數據通信安裝與設置后,就要在用戶程序中進行編程,建立dde對話,控制數據通信流程。本文介紹vc2005的dde通信方式。事實上,vc2005并不直接與dde server進行dde對話,它是通過windows操作系統提供的ddeml(dde通信管理庫)來管理dde通信具體工作的。該管理庫的使用方法如下:
(1) ddeml的初始化工作
加載頭文件,.#include “ddeml.h” //在工程中引用ddeml庫然后按照dde server提供的3級訪問方式建立vc與ddeserver的對話。此時service為mbplus,topic為plc4。通過選擇不同的item及相應dde函數可以完成接收過程數據、發送控制命令、獲取系統狀態等工作。
使用ddeml后,實際上客戶和服務器之間的多數會話并不是直達對方的,而是經由ddeml中轉,即用回調函數處理dde交易(transaction)。在調用其他ddeml函數前,必須調用ddeinitialize()函數,以獲取實例標識符,注冊dde 回調函數。通過回調函數來處理dde的事務。
本例中使用如下方法來初始化dde連接,dword idinst = 0; //定義dde實例標識的變量ddeinitialize(&idinst,(pfncallback)ddecallback,appclass_standard | appcmd_clientonly,0);這里將ddecallback函數指定為dde的回調函數。實例初始化后得到實例的標識idinst,之后的操作都要使用這個標識。
(2) 通過dde協議的服務名,主題名和項目名來訪問具體某個項目的數據
先定義dde的服務名和主題名
tchar szapp[] = text(“mbplus”); //服務名
tchar sztopic4[]=text(“plc4”); //主題名
tchar szwidth[]=text(“400401”); //項目名
tchar vlwidth[16]; //儲存從dde服務器返回的數據
hsz hszwidth; //項目的dde標識
//項目名的命名規則具體可以查看mbplus程序的說明,這里400401表示的是項目在plc中的地址,這是一個//16位的整形數
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協議處理數據的方式有較好的通用性,經過簡單修改既可以用于其他的系統。另外通過簡單的擴展,即可實現數據采集和分析的功能。可以廣泛應用于工業控制的各個領域。
責任編輯:gt
評論
查看更多