在qt中使用c++实现与Twincat3 PLC变量通信
这是一个只针对新手的教程,下载安装就不说了,我下的是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/