问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

VC++ MFC组态王opc服务器

发布网友 发布时间:2022-04-14 20:18

我来回答

2个回答

懂视网 时间:2022-04-15 00:39

最近做上位机开发,需要与PLC 通讯 。以前不知道以为要与PLC程序配合写 通讯 程序,后来联系西门子客服才知道这个问题早被解决了。网上《OPC_client_在VC环境下编程.doc》比较适合我(适合你的是最好的),表示感谢作者。在这篇的基础上我添加了一下自己的东

最近做上位机开发,需要与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(
L"group", //[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 < COUNT; 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 < COUNT; 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;
}

 




                                        

热心网友 时间:2022-04-14 21:47

你可以参看组态王帮助里面

《组态王与其它应用程序的动态数据交换(DDE)》相关章节部分
里面有组态王与EXCEL,VB等应用程序的通讯和数据交换

VC没搞过,示例程序我用VB6.0调试过,能运行!!

先参照一下,VB的吧!!

VB访问组态王的数据

在本例中,假设VB访问“组态王”的数据,VB作为客户程序向“组态王”请求数据。“组态王”通过OMRON驱动程序从下位机采集数据,VB又向“组态王”请求数据。数据流向如下图所示。

在“组态王”中定义设备
在工程浏览器中,从左边的工程目录显示区中选择“设备”,然后在右边的内容显示区中双击“新建”图标,则弹出“设备配置向导”(设备的配置请参见第六章 I/O设备管理,在这里比如建立了OMRON的PLC),已配置的设备的信息总结列表框如图18.19所示。

图18.19 利用设备安装向导定义设备

定义的连接对象名为OMRON(也就是连接设备名),定义I/O变量时要使用此连接设备。

在“组态王”中定义I/O变量
在工程浏览器左边的工程目录显示区中,选择“数据库\数据词典”,然后在右边的目录内容显示区中用左键双击“新建”图标,弹出“变量属性”对话框,在此对话框中建立一个I/O实型变量。如图18.20所示。

图18.20 组态王定义IO变量

变量名设为FromViewToVB,这个名称由工程人员自己定义。项目名为OMRON.HR001。选择“允许DDE访问”选项。变量名在“组态王”内部使用,项目名是供VB引用的,连接设备为OMRON,用来定义服务器程序的信息,已在前面定义。
创建画面
在组态王画面开发系统中建立画面test1,如图18.21所示。

图18.21 组态王中输出变量

为文本对象“%%%%%”设置“模拟值输出”动画连接如图18.22所示。

图18.22 组态王为变量输出建立动画连接

选择菜单“文件\全部存”,保存画面。选择菜单“数据库\主画面配置”,将画面test1设置为主画面。
运行可视化编程工具Visual Basic
继续使用上一节的例子,设计Form1如图18.23所示。

图18.23 VB中建立窗体和控件

编制Visual Basic程序
双击Form1窗体中任何没有控件的区域,弹出“Form1.frm”窗口,在窗口内书写Form_Load子例程,如图18.24所示。

图18.24 VB中为控件建立与组态王变量的连接

生成可执行文件
在VB中选择菜单“File\Save Project”保存修改结果。选择菜单“File\Make Exe File”生成vbdde.exe可执行文件。激活OMRON驱动程序和“组态王”运行系统TouchVew。在Visual Basic菜单中选择“Run\Start”运行vbdde.exe程序。窗口Form1的文本框Text2中显示出变量的值。如图18.25所示。

图18.25 VB接收组态王的数据

运行可视化编程工具Visual Basic
选择菜单“File\New Project”,显示新窗体Form1。设计Form1,将窗体Form1的LinkMode属性设置为1(source),如图18.13所示。

图18.13 VB中建立窗体和控件

修改VB中窗体和控件的属性:
窗体Form1属性:LinkMode属性设置为1(source);LinkTopic属性设置为FormTopic,这个值将在“组态王”中引用。
文本框Text1属性:Name属性设置为Text_To_View,这个值也将在“组态王”中被引用。

生成vbdde.exe文件
在Visual Basic菜单中选择“File\Save Project”,为工程文件命名为vbdde.vbp,这将使生成的可执行文件默认名是vbdde.exe。选择菜单“File\Make EXE File”,生成可执行文件vbdde.exe。
在“组态王”中定义DDE设备
在工程浏览器中,从左边的工程目录显示区中选择“设备\DDE”,然后在右边的内容显示区中双击“新建”图标,则弹出“设备配置向导”(DDE设备的配置请参见第六章 I/O设备管理),已配置的DDE设备的信息总结列表框如图18.14所示。定义I/O变量时要使用定义的连接对象名VBDDE(也就是连接设备名)。

图18.14 组态王中定义DDE设备

在工程浏览器中定义新变量
定义新变量,变量名为FromVBToView,项目名设为服务器程序中提供数据的控件名,此处是文本框Text_To_View,连接设备为VBDDE。“变量属性”对话框如图18.15所示。

图18.15 组态王中定义IO变量

新建组态王画面名为test,如图18.16所示。

图18.16 组态王中输出来自VB的数据

为对象“#####”设置“模拟值输出”的动画连接,如图18.17所示。

图18.17 组态王中为变量输出建立动画连接

设置完成后,选择菜单“文件\全部存”。选择菜单“数据库\主画面配置”,将画面test设置为主画面。DDE连接设置完成。

执行应用程序
在VB中选择菜单“Run\Start”,运行vbdde.exe程序,在文本框中输入数值。运行组态王,得到VB中的数值。如图18.18所示。

图18.18 组态王中为变量输出建立动画连接

如果画面运行异常,选择TouchVew菜单“特殊\重新建立未成功的DDE连接”,连接完成后再试一
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
结核病是什么样的疾病? 曹丕17岁得了肺痨,明知自己命不长久,还要强争王位,是不是很自私呢?_百... 古代小说常出现的病名 急求一篇"生活小窍门"(500字)的作文 至今最有什么小妙招 健康的戒烟方法 笔记本电池锁死是什么原因引起的? 黑龙江债权转让合同纠纷该怎样取证 安徽债权转让合同纠纷应该怎么样取证 房产官司律师费多少 请问牙齿稍微有点松动了怎么办 牙齿轻微松动 淡水鱼活性多肽真的能抗衰老吗??? 大牙松动,怎么办 有人用肽,治疗好癌症的列子吗? 丝肽液是什么 58.com上面的信用度一直删 删到最后是什么样子啊 有没有个人指点一下 如果高中女生1米58,108斤胸围是96,那算不算比较大?因为学校经常有些男生在笑觉得很不舒服 121.201.98.50:50080和121.201.101.5:50220是同一个ip吗 我想在轻松筹求助,请问我要准备什么材料? 腿长90cm,身高1:58-159左右,79斤——80左右,算腿长吗? cs1.6弹道难控制``` 请帮我查一下这个IP(218。58。57。130:63537 Excel中怎样把数字转化为时间,例如输入数字158变成有实际意义的1&#39;58&quot;后续还需要时间加减。 刀剑 双开师徒任务 红心猕猴桃招商 雅安高山红心猕猴桃,好吃得很,你们有喜欢吃雅安红心猕猴桃的吗? 200smart和wincc是怎么通过pc access通信的 资方让去签风控合同了融资成功率有多少 资方让去签风控协议了融资会成功了吗 佳能E618 请问墨盒可以自己加墨水的吗 我们党提出到新中国成立100年时什么实现现代化 到中国共产党成立多少时全面建成小康 到新中国成立多少年时使我国建成社会主义现代化国家 王蓉结婚了吗 跪求重庆饮食文化的详细介绍(最高分求解~~急~~~在线等)200分还有追加... 王蓉的老公老公是谁 用于kindle阅读器的电子书一般在哪比较多啊? 震旦AD455提示C_6102 我的电脑检测出Generic!Artemis,我该怎么办啊? 求,kindle电子书mobi格式下载的免费的网站,资源充足的,谢谢 PCaccess和WinCC通讯问题 美的机械条码在哪里? 我的美的空调室外机身条码和维修卡上的条码为什么不一样? wincc通过PC Access OPC与s7-200通讯,读取速度过慢!如何解决? 所有EDP接口满足EDP-30P1L-030A的信号接口定义的显示屏都可以互用吗? 如何知道自己的笔记本内部硬件和自身显示器的接口是什么类型的?是eDP还是LVDS,异或是其他种类的。 联想S4170的EDP接口有多少针 有人知道HDMI转EDP的芯片用哪一款芯片吗?还有就是DP 20PIN接口转 EDP30Pin接口需要做什么处理吗? 5260开发板eDP接口显示最大的分辨率多少?