這是一個只針對新手的教程,下載安裝就不說了,我下的是TC31-Full-Setup.3.1.4024.66.exe是這個版本,其他版本應該問題不大。
先創建一個項目
選中SYSTEM,在右側點擊Choose Target(接下來界面跟我不一樣沒關系,因為是從已有的項目上截的圖,像plc可能你們沒有文件,后面會講),選擇Search,進去再選擇Broadcast Search,選擇你要的那個,你們可能沒有那個“x”,“x”代表連接成功,接下來點擊Add Route,取消勾選Secure ADS(本次用不到),輸入密碼(查了下,默認密碼應該是1或者沒有),點擊ok,接下來應該就有“x”了,代表連接成功了,點擊close,記住你設備對應地址,接下來在c++會用到,點擊ok(說一下跳出什么提示都點是,后面也是)。
接下來編寫pcl代碼,右鍵PLC添加新項,選擇Standard PLC Project,點擊添加,這樣plc下就會出來一堆文件,找到POUS文件,點擊里面的MAIN,這樣就可以編寫plc程序了。
我這邊定義了a,b,c,sum如圖所示(我也是第一次寫plc程序,稍微查了一下,這邊上下兩部分,上面是初始化變量區域,下面是邏輯運算區域),自己寫入a,b,c的值,最后相加得到sum,右鍵點擊你的plc文件名,再點擊生成,編譯完之后點擊上方activate configuration,跳出提示框一直點ok/是,進入run mode,這里應該能看見你設備上的TC燈變成綠色,這樣Twincat端的基本已經完成,現在寫c++程序。
我這邊使用qt編寫c++程序(其他應該也可以),先創建一個c++程序,在.pro中添加ads的庫與頭文件的路徑,路徑按自己實際情況改。添加頭文件#include <windows.h>,#include <TcAdsDef.h>
#include <TcAdsAPI.h>,嚴格根據這個順序來,不然可能會報錯,定義端口變量,AMS地址變量,端口地址變量,以及對應的用來接收你在pcl中定義變量的值的變量(這里我用short定義是因為pcl中int只有2字節,為了對應,c++中使用short定義),使用AdsPortOpen()函數打開ads端口通信,設置端口為851(默認端口),手動填寫目標設備的AMSNETID,即上面讓你們記得的那個地址(這里手動填寫是因為我不知道啥原因自動填寫有問題,感興趣可以試試,就我注釋掉那一部分)。
TEMPLATE = app
CONFIG += console c++17
CONFIG -= app_bundle
CONFIG -= qtSOURCES += \
? ? ? ? main.cpp
INCLUDEPATH += $$quote(C:/TwinCAT/AdsApi/TcAdsDll/Include)LIBS += $$quote(C:/TwinCAT/AdsApi/TcAdsDll/x64/lib/TcAdsDll.lib)
?
? ? long ? ? ? ?nErr, nPort;//定義端口變量
? ? AmsAddr ? ? Addr;//定義AMS地址變量
? ? PAmsAddr ? ?pAddr = &Addr;//定義端口地址變量
? ? short ? ? ? a,b,c;
? ? short ? ? ? sum;? ? nPort = AdsPortOpen();//打開ADS通訊端口
? ? // nErr = AdsGetLocalAddress(pAddr);
? ? // if (nErr) cerr << "Error:AdsGetLocalAddress:" << nErr << '\n';
? ? pAddr->port = 851;//TC3通訊使用的為851端口
? ? pAddr->netId.b[0] = 169; //手動填寫目標設備的AMSNETID
? ? pAddr->netId.b[1] = 254;
? ? pAddr->netId.b[2] = 100;
? ? pAddr->netId.b[3] = 116;
? ? pAddr->netId.b[4] = 1;
? ? pAddr->netId.b[5] = 1;
通過AdsSyncWriteReq?函數,自行寫入a,b,c的值,在Twincat中按下ctrl+q進入查找功能,輸入browser,選擇第一個就可以跳到Target Browser界面,可以查看變量的段地址和偏移地址,按圖中寫入代碼,循環讀取a,b,c,sum的值(看自己要求要不要循環讀取),最后記得用AdsPortClose()函數關閉ads通信端口。
//寫入a的值cout << "a = ";cin >> a;nErr = AdsSyncWriteReq(pAddr,0x4020,0x8,0x2,&a);if (nErr) cerr << "Error : AdsSyncWriteReq:" << nErr << '\n';//寫入b的值cout << "b = ";cin >> b;nErr = AdsSyncWriteReq(pAddr,0x4020,0x10,0x2,&b);if (nErr) cerr << "Error : AdsSyncWriteReq:" << nErr << '\n';//寫入c的值cout << "c = ";cin >> c;nErr = AdsSyncWriteReq(pAddr,0x4020,0x18,0x2,&c);if (nErr) cerr << "Error : AdsSyncWriteReq:" << nErr << '\n';
do{//讀取a的值nErr = AdsSyncReadReq(pAddr,0x4020,0x8,0x2,&a);if (nErr) cerr << "Error : AdsSyncReadReq:" << nErr << '\n';cout << a << endl;//讀取b的值nErr = AdsSyncReadReq(pAddr,0x4020,0x10,0x2, &b);if (nErr) cerr << "Error : AdsSyncReadReq:" << nErr << '\n';cout << b << endl;//讀取c的值nErr = AdsSyncReadReq(pAddr,0x4020,0x18,0x2,&c);if (nErr) cerr << "Error : AdsSyncReadReq:" << nErr << '\n';cout << c << endl;//讀取sum的值nErr = AdsSyncReadReq(pAddr,0x4020,0x20,0x2,&sum);if (nErr) cerr << "Error : AdsSyncReadReq:" << nErr << '\n';cout << "sum = " << sum << '\n';cout << "--------------" << endl;cout << endl;Sleep(200);}while(1);
????nErr = AdsPortClose();
? ? if (nErr) cerr << "Error:AdsPortClose:" << nErr << '\n';
?回到plc端點擊loin按鈕,我是直接運行的,有些版本可能還要點在一下三角圖案來運行,運行之后會自動跳出一個MAIN[Online]界面,可以看到初始值都為0,在qt中勾選上在終端中運行,接下來運行c++程序,可以看到我給a,b,c分別賦值1,2,3,最終得到sum為6,同時Twincat中的a,b,c,sum也跟著變化了(其實如果只有讀取可以不按login也能成功,但如果你要寫入一定要點login才能成功改變值)。
這是全部的源代碼
#include <iostream>
//#include <conio.h>
#include <windows.h>
#include <TcAdsDef.h>
#include <TcAdsAPI.h>using namespace std;int main()
{long nErr, nPort;//定義端口變量AmsAddr Addr;//定義AMS地址變量PAmsAddr pAddr = &Addr;//定義端口地址變量short a,b,c;short sum;nPort = AdsPortOpen();//打開ADS通訊端口// nErr = AdsGetLocalAddress(pAddr);// if (nErr) cerr << "Error:AdsGetLocalAddress:" << nErr << '\n';pAddr->port = 851;//TC3通訊使用的為851端口pAddr->netId.b[0] = 169; //手動填寫目標設備的AMSNETIDpAddr->netId.b[1] = 254;pAddr->netId.b[2] = 100;pAddr->netId.b[3] = 116;pAddr->netId.b[4] = 1;pAddr->netId.b[5] = 1;//寫入a的值cout << "a = ";cin >> a;nErr = AdsSyncWriteReq(pAddr,0x4020,0x8,0x2,&a);if (nErr) cerr << "Error : AdsSyncWriteReq:" << nErr << '\n';//寫入b的值cout << "b = ";cin >> b;nErr = AdsSyncWriteReq(pAddr,0x4020,0x10,0x2,&b);if (nErr) cerr << "Error : AdsSyncWriteReq:" << nErr << '\n';//寫入c的值cout << "c = ";cin >> c;nErr = AdsSyncWriteReq(pAddr,0x4020,0x18,0x2,&c);if (nErr) cerr << "Error : AdsSyncWriteReq:" << nErr << '\n';do{//讀取a的值nErr = AdsSyncReadReq(pAddr,0x4020,0x8,0x2,&a);if (nErr) cerr << "Error : AdsSyncReadReq:" << nErr << '\n';cout << a << endl;//讀取b的值nErr = AdsSyncReadReq(pAddr,0x4020,0x10,0x2, &b);if (nErr) cerr << "Error : AdsSyncReadReq:" << nErr << '\n';cout << b << endl;//讀取c的值nErr = AdsSyncReadReq(pAddr,0x4020,0x18,0x2,&c);if (nErr) cerr << "Error : AdsSyncReadReq:" << nErr << '\n';cout << c << endl;//讀取sum的值nErr = AdsSyncReadReq(pAddr,0x4020,0x20,0x2,&sum);if (nErr) cerr << "Error : AdsSyncReadReq:" << nErr << '\n';cout << "sum = " << sum << '\n';cout << "--------------" << endl;cout << endl;Sleep(200);}while(1);nErr = AdsPortClose();if (nErr) cerr << "Error:AdsPortClose:" << nErr << '\n';
}
?
以上就是在qt中使用c++實現與Twincat3 PLC變量通信全過程,本人也是第一次接觸也是摸索了很久,希望能幫到大家。
如果要長時間接觸倍福可以虛擬倍福學園自己學習一下https://tr.beckhoff.com.cn/