最近做上位机开发,需要与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_ALLif( 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 {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 itemspValues, // 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;}登录后复制
09-10 07:06