西门子PLC的通信协议主要是PPI、MPI、Profibus、CP243/CP343/CP443 网络协议,prodave是早期完成的程序接口,除了网络协议外其它的主要协议都支持,SoftNet是西门子最新推出的通信协议接口,稳定,并且大而全,目前西门子所有主流的协议都支持(我的blog文章:西门子Softnet驱动的成功开发已经做了简单介绍),由于好多朋友对prodave都比较关注,所以我这里专门写篇blog来简单介绍一下。
我所知道的最新的Prodave的版本是V5.5,完整版的要45兆左右,由于出的比较早,所以动态库“W95_s7.dll”的名称保留至今,我最早接触是在01~02年,不过当时版本好像不到V5.5,与S7-200通信很不稳定,并且访问周期比较长。给我的感觉Prodave好像专门为S7-300制作的(从库函数的声明可以看出),连S7-300相对而言比较顺利。
组态王、力控好多主流工控软件访问西门子PLC都是通过Prodave或Softnet的,可以在驱动程序中看到熟悉的W95_s7.dll,所以通信能力大家还是应该放心的。
题外话,对嵌入式系统,如WinCE,由于不能直接使用Prodave和Softnet,所以要实现与西门子PLC通信,一般只有破解了(西门子的通信协议都是保密的,并且也是加密的,一般不公开给客户),目前实现的较好的主要有PPI,MPI(需要MPI适配器,不同适配器通信协议有一定区别),CP243,CP343/CP443。
下面是我在开发相关西门子通信程序时,做的一个VC测试程序,仅供参考(Prodave简版驱动和相关测试代码,我已经上传,文章后面附下载连接)。
void
CTestDlg::OnProdave()
{
int
iRes;
CStringmyStr;
signed
char
Buffer[
2048
];
WORD
*
Buffer_int
=
(WORD
*
)Buffer;
unsigned
char
*
Buffer_byte
=
(unsigned
char
*
)Buffer;
//
WORDwValue;
//
m_field_readMB200
iRes
=
m_field_read(
200
,
1
,Buffer);
if
(iRes
==
0
)
{
m_Dis.SetSel(
100000
,
100000
);
m_Dis.ReplaceSel(
"
"
);
myStr.Format(
"
MB200=%3d
"
,Buffer_byte[
0
]);
m_Dis.ReplaceSel(myStr);
UpdateData(
false
);
}
else
{
//
myStr.Format("m_field_readerrorno:%d",iRes);
AfxMessageBox(ErrString(iRes));
}
//
m_field_read
iRes
=
m_field_read(
100
,
1
,Buffer);
if
(iRes
==
0
)
{
m_Dis.SetSel(
100000
,
100000
);
m_Dis.ReplaceSel(
"
"
);
myStr.Format(
"
MB100=%3d
"
,Buffer_byte[
0
]);
m_Dis.ReplaceSel(myStr);
UpdateData(
false
);
}
else
{
AfxMessageBox(ErrString(iRes));
}
//
m_field_read
iRes
=
a_field_read(
0
,
1
,Buffer);
if
(iRes
==
0
)
{
m_Dis.SetSel(
100000
,
100000
);
m_Dis.ReplaceSel(
"
"
);
myStr.Format(
"
QB0=%3d
"
,Buffer_byte[
0
]);
m_Dis.ReplaceSel(myStr);
UpdateData(
false
);
}
else
{
AfxMessageBox(ErrString(iRes));
}
//
写数据MB110
unsigned
long
value;
value
=
100
;
memcpy(Buffer,
&
value,
4
);
iRes
=
m_field_write(
111
,
1
,Buffer);
if
(iRes
==
0
)
{
m_Dis.SetSel(
100000
,
100000
);
m_Dis.ReplaceSel(
"
"
);
myStr.Format(
"
MB110=%3d
"
,Buffer[
0
]);
m_Dis.ReplaceSel(myStr);
UpdateData(
false
);
}
else
{
AfxMessageBox(ErrString(iRes));
}
//
写数据MB4
BYTEvalue1;
value1
=
33
;
memcpy(Buffer,
&
value,
1
);
iRes
=
m_field_write(
4
,
1
,Buffer);
if
(iRes
==
0
)
{
m_Dis.SetSel(
100000
,
100000
);
m_Dis.ReplaceSel(
"
"
);
myStr.Format(
"
MD4=%3d
"
,Buffer[
0
]);
m_Dis.ReplaceSel(myStr);
UpdateData(
false
);
}
else
{
AfxMessageBox(ErrString(iRes));
}
}
void
CTestDlg::OnLoad()
{
adr_table_typemyTable[
2
];
myTable[
0
].adr
=
3
;
myTable[
0
].segmentid
=
0
;
myTable[
0
].slotno
=
2
;
myTable[
0
].rackno
=
0
;
myTable[
1
].adr
=
0
;
myTable[
1
].segmentid
=
0
;
myTable[
1
].slotno
=
2
;
myTable[
1
].rackno
=
0
;
int
iRes;
CStringmyStr;
//
初始化ProDave300
iRes
=
load_tool(
1
,
"
S7ONLINE
"
,myTable);
if
(iRes
==
0
)
{
m_Dis.SetSel(
30000
,
30000
);
m_Dis.ReplaceSel(
"
"
);
m_Dis.ReplaceSel(
"
load_toolok!
"
);
UpdateData(
false
);
}
else
{
AfxMessageBox(ErrString(iRes));
unload_tool();
return
;
}
}
void
CTestDlg::OnUnloadtool()
{
int
iRes;
CStringmyStr;
iRes
=
unload_tool();
if
(iRes
==
0
)
{
m_Dis.SetSel(
30000
,
30000
);
m_Dis.ReplaceSel(
"
"
);
m_Dis.ReplaceSel(
"
unload_toolok!
"
);
m_Dis.ReplaceSel(
"
"
);
UpdateData(
false
);
}
else
{
AfxMessageBox(ErrString(iRes));
}
}
void
CTestDlg::OnStatus()
{
int
iRes;
CStringmyStr;
char
myInfo[
512
];
iRes
=
ag_zustand(myInfo);
if
(iRes
==
0
)
{
m_Dis.SetSel(
30000
,
30000
);
m_Dis.ReplaceSel(
"
"
);
m_Dis.ReplaceSel(
"
ag_zustandok!
"
);
UpdateData(
false
);
if
(myInfo[
0
]
==
0
)
{
m_Dis.ReplaceSel(
"
"
);
m_Dis.ReplaceSel(
"
RUN
"
);
}
else
{
m_Dis.ReplaceSel(
"
"
);
m_Dis.ReplaceSel(
"
STOP
"
);
}
UpdateData(
false
);
}
else
{
AfxMessageBox(ErrString(iRes));
}
}
LPSTRCTestDlg::ErrString(WORDwErrCode)
{
LPSTRmyStr1;
switch
(wErrCode)
{
case
517
:
{
return
"
PRODAVEnotinitialized.
"
;
break
;
}
case
787
:
{
return
"
Incorrectrate/Interruptvector.
"
;
break
;
}
case
789
:
{
return
"
MPIAddresserror.
"
;
break
;
}
case
800
:
case
818
:
{
return
"
hardwarefault.
"
;
break
;
}
case
820
:
{
return
"
comnotavaliable.
"
;
break
;
}
case
898
:
case
900
:
{
return
"
nodriverordevicefound.
"
;
break
;
}
case
16386
:
{
return
"
Connectionnotestablished.
"
;
break
;
}
default
:
{
CStringmyStr;
myStr.Format(
"
%d
"
,wErrCode);
myStr1
=
myStr.GetBuffer(
0
);
myStr.ReleaseBuffer();
return
myStr1;
}
}
}
void
CTestDlg::OnNewss()
{
//
激活连接
int
iRes;
iRes
=
new_ss(
1
);
if
(iRes
==
0
)
{
m_Dis.SetSel(
100000
,
100000
);
m_Dis.ReplaceSel(
"
"
);
m_Dis.ReplaceSel(
"
new_ssok!
"
);
UpdateData(
false
);
}
else
{
AfxMessageBox(ErrString(iRes));
unload_tool();
return
;
}
}
void
CTestDlg::OnAginfo()
{
//
读PLC信息
int
iRes;
char
myInfo[
512
];
iRes
=
ag_info(
&
myInfo[
0
]);
if
(iRes
==
0
)
{
m_Dis.SetSel(
100000
,
100000
);
m_Dis.ReplaceSel(
"
"
);
m_Dis.ReplaceSel(
"
ag_infook!
"
);
UpdateData(
false
);
m_Dis.ReplaceSel(
"
"
);
m_Dis.ReplaceSel(
&
myInfo[
4
]);
UpdateData(
false
);
}
else
{
AfxMessageBox(ErrString(iRes));
unload_tool();
return
;
}
}
prodave 测试程序:http://download.csdn.net/source/228758
Prodave简版驱动:http://download.csdn.net/source/228765