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型變量進行讀寫的簡單實驗。

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