TwinCAT PLC和上位机HMI通讯初探

在PLC的程序中,添加如下变量
     intCount AT %Q*: DINT;        可读
     intVarIn AT  %I* : DINT:=0;   可写
     PLCVar   : DINT:=0;                 可读可写 

上位机HMI程序(参考InfoSys中的例子)

1.声明变量:

//===========================
 long             nErr, nPort;
 AmsAddr    Addr;
 PAmsAddr  pAddr;
 ULONG      lHdlVarR,lHdlVarW;
 int                nData;
 CString         strTmp;
 ULONG      hNotification;
 AdsNotificationAttrib  adsNotificationAttrib;
 //===========================

2.初始化变量和属性

 //========================================================
 pAddr  = &Addr;
 nData  = 0;
 // Open communication port for local PLC (Run-time system 1)
 nPort = AdsPortOpen();
 nErr = AdsGetLocalAddress(pAddr);    //获取本地的AmsNetId 和 Port

if (nErr)
 {
      MessageBox("Error: AdsGetLocalAddress: ");
      return 0;
 }
 pAddr->port = AMSPORT_R0_PLC_RTS1;    //Port为第一个PLC任务

 

 // Specify attributes of the notification
 adsNotificationAttrib.cbLength = 16;                                                            //读取数据长度
 adsNotificationAttrib.nTransMode = ADSTRANS_SERVERONCHA;    //当变化是响应回调函数
 adsNotificationAttrib.nMaxDelay = 1000000;                                             // 100ms
 adsNotificationAttrib.nCycleTime = 1000000;                                             // 100ms

3.获取变量的句柄

 // Fetch handle for an <szVar> PLC variable 

char szVarR[]= {"MAIN.intCount"};        //读
nErr = AdsSyncReadWriteReq(pAddr, ADSIGRP_SYM_HNDBYNAME, 0x0, 

                                                    sizeof(lHdlVarR), &lHdlVarR, sizeof(szVarR), szVarR);

char szVarW[]= {"MAIN.intVarIn"};        //写
nErr = AdsSyncReadWriteReq(pAddr, ADSIGRP_SYM_HNDBYNAME, 0x0, 

                                                    sizeof(lHdlVarW), &lHdlVarW, sizeof(szVarW), szVarW);

4.通过上述的句柄就可以实现对PLC中的数据进行读写 或 设置“事件驱动”的方式获取数据
4.1读数据

 nErr = AdsSyncReadReq( pAddr, ADSIGRP_SYM_VALBYHND, lHdlVarR, sizeof(nData), &nData );
 if (nErr)
       MessageBox("Fehler: AdsSyncReadReq: ");
 else
       strTmp.Format("%d", nData) ;
 m_strSysData="Fehler: AdsSyncReadReq: " + strTmp;

 

4.2写数据

 UpdateData();
 nData=atoi(m_strWriteData);
 nErr = AdsSyncWriteReq(pAddr, ADSIGRP_SYM_VALBYHND, lHdlVarW, sizeof(nData), &nData);
 if (nErr)
      MessageBox("Error: AdsSyncWriteReq:  ");

 

4.3启动“事件驱动”

1)声明回调函数

void __stdcall SymbolChanged(AmsAddr*, AdsNotificationHeader*, unsigned long);

2)启动“事件驱动” 

nErr = AdsSyncAddDeviceNotificationReq(pAddr,  ADSIGRP_SYM_VALBYHND, 
                                                                       lHdlVarR, &adsNotificationAttrib, 
                                                                       SymbolChanged, NULL, &hNotification);
 if (nErr)
 {
     MessageBox("Error: AdsSyncAddDeviceNotificationReq: ");
     return;
 }

//================以下为回调函数部分========================

void __stdcall SymbolChanged(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser)
{
 CString strDataFromNotify,strTmp;

 CEx02Dlg *dlg=(CEx02Dlg *)AfxGetMainWnd();
 strDataFromNotify=""; strTmp="";
 // Output value of the variable
 strTmp.Format("Value:%d/n", *(int *)pNotification->data);        //data中的数据为地址
 strDataFromNotify+=strTmp;
 strTmp.Format("Notification:%d/n",pNotification->hNotification);
 strDataFromNotify+=strTmp;
 strTmp.Format("SampleSize:%d/n",pNotification->cbSampleSize);
 strDataFromNotify+=strTmp;
 strTmp.Format("hUser:%d/n",hUser);
 strDataFromNotify+=strTmp;


 dlg->m_strNtyData=strDataFromNotify;
 dlg->SetDlgItemText(IDC_STATIC_Data2,strDataFromNotify);    //更新CEX02类中的窗体
}

 

4.4关闭“事件驱动”

 nErr = AdsSyncDelDeviceNotificationReq(pAddr, hNotification);
 if (nErr)
 {
      MessageBox("Error: AdsSyncDelDeviceNotificationReq: ");
      return;
 }

5.关闭端口

 nErr = AdsPortClose();
 if (nErr)
     MessageBox("Error: AdsPortClose: ");

以上是对int型变量进行读写的简单实验。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章