最近做上位机开发,需要与plc通讯。以前不知道以为要与plc程序配合写通讯程序,后来联系西门子客服才知道这个问题早被解决了。网上《opc_client_在vc环境下编程.doc》比较适合我(适合你的是最好的),表示感谢作者。在这篇的基础上我添加了一下自己的东西。具体的demo在http://download.csdn.net/detail/yuanhaosh/8098867下载
在这之前需要添加几个opc相关的文件 opccomn_i.c ,opccomn.h, opcda.h, opcda_i.c, opcerror.h,已经包含在demo中了
这部分是初始化opc的部分。
bool copcdemodlg::initopcserver()
{
clsid clsid;
hresult hr = s_ok;
cstring strserver = s7200.opcserver; //opc.simaticnet s7200.opcserver
/*初始化com库*/
if (failed(::coinitialize(null)))
{
afxmessagebox(error during coinitialize, mb_ok );
return false;
}
/*查找opc服务*/
hr = clsidfromprogid( strserver.allocsysstring(), &clsid );
if( failed(hr))
{
afxmessagebox(error during clsidfromprogid, mb_ok);
return false;
}
/*创建opc服务器对象*/
lpunknown punkn = null;
hr = cocreateinstance(clsid, null, clsctx_local_server , iid_iopcserver, (void**)&m_iopcserver); //clsctx_local_server clsctx_all
if( failed(hr) || m_iopcserver == null)
{
afxmessagebox(error during cocreateinstance, mb_ok);
return false;
}
/*添加组到opc服务器*/
float percentdeadband = 0.0;
dword revisedupdaterate;
hr = m_iopcserver->addgroup(
lgroup, //[in] 组名
true, //[in] 活动状态
500, //[in] 向服务器发送请求的刷新率
1, //[in] 客户端的操作句柄
null, //[in] 与标准时间的校正值
&percentdeadband, //[in] 要舍弃的数据
0, //[in] 服务器使用的语言
&m_grpsrvhandle, //[out] 添加组以后服务器返回的组句柄
&revisedupdaterate, //[out] 服务器的数据刷新率
iid_iopcitemmgt, //[in] 添加组的接口类型
(lpunknown*)&m_iopcitemmgt); //[out] 服务器返回的接口对象指针
if( failed(hr) )
{
lpwstr perrstring;
afxmessagebox(error during addgroup, mb_ok);
hr = m_iopcserver->geterrorstring(hr, locale_system_default, &perrstring);
if(succeeded(hr))
{
//输出错误信息
}
else
{
//添加组失败;
}
m_iopcserver->release();
m_iopcserver=null;
couninitialize();
return false;
}
item* pcitem ;
opcitemdef *m_items = new opcitemdef[count]; //项的存取路径, 定义和被请求的数据类等
for(int i = 0; i {
pcitem = new item;
pcitem->quality = qual_bad;
//pcitem->name = _t( + tablestr[i]); //设置opc节点 microwin.newplc.group.
pcitem->name = _t(microwin.newplc.group.newitem1); //这里的字符串填写你的item就行
m_items[i].szitemid = pcitem->name.allocsysstring();
m_items[i].dwblobsize = 0;
m_items[i].pblob = null;
m_items[i].bactive = true;
m_items[i].hclient = (opchandle)pcitem;
m_items[i].szaccesspath = pcitem->caccesspath.allocsysstring();; //pcitem->caccesspath.allocsysstring();
m_items[i].vtrequesteddatatype = vt_empty; //vt_empty;
}
/*添加项目*/
opcitemresult *popcresults = null;
hresult *popcerrors = null;
hr = m_iopcitemmgt->additems(count,
m_items,
&popcresults,
&popcerrors);
if(failed(hr))
{
lpwstr perrstring;
afxmessagebox(error during addgroup, mb_ok);
hr = m_iopcserver->geterrorstring(hr, locale_system_default, &perrstring);
if(succeeded(hr))
{
//输出错误信息
}
else
{
//perrstring = 添加组失败.;
}
m_iopcserver->release();
m_iopcserver=null;
couninitialize();
return false;
}
/*保存item对应的服务句柄*/
pdwserverhandles = new dword[count];
for(i = 0; i {
pdwserverhandles[i] = popcresults[i].hserver;
if(popcerrors[i]= s_ok)
{
pdwserverhandles[i] = popcresults[i].hserver;
}
}
/*获取同步io口*/
hr = m_iopcitemmgt->queryinterface(iid_iopcsyncio, (void**)&m_iopcsyncio);
if(failed(hr))
{
lpwstr perrstring;
afxmessagebox(获取io口失败, mb_ok);
hr = m_iopcserver->geterrorstring(hr, locale_system_default, &perrstring);
if(succeeded(hr))
{
//输出错误信息
}
else
{
//perrstring = 获取io口失败.;
}
m_iopcserver->release();
m_iopcserver=null;
couninitialize();
return false;
}
// delete[] pdwserverhandles; 会出现异常报错请使用者再次检查原因,防止内存泄露
// delete[] m_items;
// delete pcitem;
return true; //初始化完成,可以开始查询.
}
/**************************************************************************************************
* 读取opc服务器中的状态信息
* phserve: 读取项的句柄
* dwsource: 状态获取来源,缓存、内存
***************************************************************************************************
*/
bool copcdemodlg::readopcserve(opcitemstate **pvalues, opchandle *phserve, opcdatasource dwsource)
{
hresult hr = s_ok;
opchandle *phserve = phserve;
lpwstr perrstring; //记录错误信息字符串
hresult *perrors= new hresult;
try
{
hr = m_iopcsyncio->read(
dwsource, // opc_ds_cache, source (device or cache)
1, // item count
(opchandle*)phserve,// array of server handles for items
pvalues, // array of values
&perrors); // array of errors
if(failed(hr))
{
afxmessagebox(error during readopc, mb_ok);
hr = m_iopcserver->geterrorstring(hr, locale_system_default, &perrstring);
if(succeeded(hr))
{
//perrstring输出错误信息
}
else
{
//perrstring = 读取失败.;
}
m_iopcserver->release();
m_iopcserver=null;
couninitialize();
return false;
}
}
catch(...)
{
}
//delete perrors; 会出现异常报错请使用者再次检查原因,防止内存泄露
return true;
}
/*****************************************************************************************
* 写入opc服务器中的状态信息
* 后续需要再写 opcitemstate **pvalues, opchandle *phserve, opcdatasource dwsource
******************************************************************************************/
bool copcdemodlg::writeopcserve(opchandle *phserve, byte values)
{
hresult hr = s_ok;
variant *pitemvalues = new variant;
opchandle *phserve = phserve;
hresult *perrors= new hresult;
lpwstr perrstring;
variantclear(pitemvalues);
memset(pitemvalues, 0, sizeof(variant));
pitemvalues->vt = vt_i2;
short value = values;
pitemvalues->bval = value;
try
{
hr = m_iopcsyncio->write(1,
phserve,
pitemvalues,
&perrors);
if(failed(hr))
{
hr = m_iopcserver->geterrorstring(hr, locale_system_default, &perrstring);
if(succeeded(hr))
{
//perrstring输出错误信息
}
else
{
//perrstring = 写入失败.;
}
m_iopcserver->release();
m_iopcserver=null;
couninitialize();
return false;
}
}
catch(...)
{}
//delete perrors; 会出现异常报错请使用者再次检查原因,防止内存泄露
return true;
}
