Qt 通过ADS实现Beckhoff倍福TwinCAT通信
ADS通信分为两种:同步方式和异步方式。
同步方式
ADS 客户端向ADS 服务器发送ADS 请求,在通信过程中客户端程序停止执行,直到获得ADS 服务器返回的响应
又可分为变量名方式和地址方式
异步方式
ADS 客户端向ADS 服务器发送ADS 请求,同时客户端继续自己的工作。ADS 服务器处理请求后,把响应以Callback 函数方式发给客户端。
变量名方式
在TwinCAT PLC程序中每个变量都有一个句柄(Handle)。在对变量进行操作之前,首先我们要通过相关路径得到变量的句柄,然后进行读写操作,操作完毕后对句柄进行释放。
地址方式
在TwinCAT PLC中一个变量的地址由两部分组成,即GroupIndex和OffsetIndex, GroupIndex为该变量所在的寄存器类型,为一常量; OffsetIndex为该变量在寄存器中得地址偏移量,为一变量。
PLC 变量地址与ADS 地址之间的对应关系:
可以在项目中查看偏移地址:
基本配置
在.pro文件中添加头文件路径和lib文件
1 INCLUDEPATH += $$PWD/include 2 LIBS += $$PWD/lib/TcAdsDll.lib在.h中添加头文件
1 #include <Windows.h> 2 #include "TcAdsDef.h" 3 #include "TcAdsAPI.h"声明全局变量
1 AmsAddr Addr;//定义AMS地址变量 2 PAmsAddr pAddr;//定义端口地址变量 3 long nErr; 4 USHORT nAdsState; //PLC状态信息 5 USHORT nDeviceState;打开/关闭ADS通信
1 long nPort; 2 pAddr = &Addr; 3 4 nPort = AdsPortOpen();//打开ADS通信端口 5 nErr = AdsGetLocalAddress(pAddr);//自动获取本地地址 6 if (nErr) 7 10 else 11 14 pAddr>port = 851;//TC3通信使用的为851端口1 //关闭端口通信 2 nErr = AdsPortClose(); 3 if (nErr) 4
读取/控制PLC状态
1 //向PLC读取PLC的状态信息 2 nErr = AdsSyncReadStateReq(pAddr, &nAdsState, &nDeviceState); 3 if (nErr) 4 7 else 81 nAdsState = ADSSTATE_RUN; 2 void *pData = nullptr; 3 nErr = AdsSyncWriteControlReq(pAddr, nAdsState, nDeviceState, 0, pData); 4 if (nErr) 5
1 nAdsState = ADSSTATE_STOP; 2 void *pData = nullptr; 3 nErr = AdsSyncWriteControlReq(pAddr, nAdsState, nDeviceState, 0, pData); 4 if (nErr) 5
读/写Bool量
1 bool BOOL1; //定义布尔量 2 nErr = AdsSyncReadReq(pAddr, 0x4020, 0x0, 0x1, &BOOL1); //从ADS服务器同步读取数据,pAddr:ADS设备的地址,0x4020:段地址,0x0偏移地址,0x1:数据长度,&BOOL1:接收数据的缓存 3 if (nErr) 4 7 else 8 13 else 14 17 }1 bool BOOL1; //定义布尔量 2 BOOL1=ui>line_Write>text().toInt(); 3 nErr = AdsSyncWriteReq( pAddr, 0x4020, 0x0, 0x1, &BOOL1 ); //同步写数据到ADS设备,pAddr:ADS设备的地址,0x4020:段地址,0x0偏移地址,0x1:数据长度,@BOOL1:接收数据的缓存 4 if (nErr) 5
读/写Int、float等变量
以Int数据类型为例:
1 int INT1; //定义整型量 2 nErr = AdsSyncReadReq(pAddr, 0x4020, 0x8, 0x4, &INT1); 3 if (nErr) 4 7 else 81 //向PLC写入整型量 2 int INT1; 3 INT1=ui>line_Write>text().toInt(); 4 nErr = AdsSyncWriteReq( pAddr, 0x4020, 0x8, 0x4, &INT1); 5 if (nErr) 6
读/写String量
1 unsigned long lHdlVar; //创建句柄 2 char String[]=; //定义字符串 3 char szVar []=; 4 5 // 同步写数据到ADS服务器并从ADS设备接收数据,pAddr:ADS设备的地址 0x0:偏移地址 sizeof(lHdlVar):由ADS设备返回的句柄大小 &lHdlVar:由ADS设备返回的数据缓存 sizeof(szVar):写入ADS设备的数据大小 szVar:写入ADS设备的数据缓存 6 nErr = AdsSyncReadWriteReq(pAddr, ADSIGRP_SYM_HNDBYNAME, 0x0, sizeof(lHdlVar), &lHdlVar, sizeof(szVar), szVar); 7 if (nErr) 8 11 nErr = AdsSyncReadReq(pAddr, ADSIGRP_SYM_VALBYHND, lHdlVar, sizeof(String), &String); //从ADS服务器同步读取数据 12 if (nErr) 13 16 else 171 //向PLC写入字符串 2 unsigned long lHdlVar; //创建句柄 3 4 QByteArray ba; 5 char* temp; 6 char String[10]; 7 QString str = ui>line_Write>text(); 8 ba = str.toLatin1(); 9 temp = ba.data(); 10 strncpy_s(String,temp,10); 11 12 char szVar []=; 13 14 nErr = AdsSyncReadWriteReq(pAddr, ADSIGRP_SYM_HNDBYNAME, 0x0, sizeof(lHdlVar), &lHdlVar, sizeof(szVar), szVar); 15 if (nErr) 16 19 nErr = AdsSyncWriteReq(pAddr, ADSIGRP_SYM_VALBYHND, lHdlVar, sizeof(String), &String); //同步写数据到ADS设备 20 if (nErr) 21
读/写数组
1 unsigned long lHdlVar2; //创建句柄 2 short Array[5]; //定义数组 3 char szVar2[]=; 4 5 nErr = AdsSyncReadWriteReq(pAddr, ADSIGRP_SYM_HNDBYNAME, 0x0, sizeof(lHdlVar2), &lHdlVar2, sizeof(szVar2), szVar2); 6 if (nErr) 7 10 nErr = AdsSyncReadReq(pAddr, ADSIGRP_SYM_VALBYHND, lHdlVar2, sizeof(Array), & Array[0]); 11 if (nErr) 12 15 else 161 unsigned long lHdlVar2; //创建句柄 2 short Array[5]; //定义数组 3 char szVar2[]=; 4 5 Array[0] = ui>line_ArrayWrite_1>text().toShort(); 6 Array[1] = ui>line_ArrayWrite_2>text().toShort(); 7 Array[2] = ui>line_ArrayWrite_3>text().toShort(); 8 Array[3] = ui>line_ArrayWrite_4>text().toShort(); 9 Array[4] = ui>line_ArrayWrite_5>text().toShort(); 10 11 //得到Array1的句柄 12 nErr = AdsSyncReadWriteReq(pAddr, ADSIGRP_SYM_HNDBYNAME, 0x0, sizeof(lHdlVar2), &lHdlVar2, sizeof(szVar2), szVar2); 13 if (nErr) 14 17 //通过句柄向PLC写入数组 18 nErr = AdsSyncWriteReq(pAddr, ADSIGRP_SYM_VALBYHND, lHdlVar2, sizeof(Array), & Array[0]); 19 if (nErr) 20
读/写结构体
1 struct PlcVarstruct //定义结构体 2 PlcVar; 7 unsigned long lHdlVar3; 8 char szVar3[] = ; 9 10 //从PLC中读取结构体 11 //获取结构体的句柄 12 nErr = AdsSyncReadWriteReq(pAddr, ADSIGRP_SYM_HNDBYNAME, 0x0, sizeof(lHdlVar3), &lHdlVar3, sizeof(szVar3), szVar3); 13 if (nErr) 14 17 //通过句柄获取所需结构体的数值 18 nErr = AdsSyncReadReq(pAddr, ADSIGRP_SYM_VALBYHND, lHdlVar3, sizeof(PlcVar), &PlcVar); 19 if (nErr) 20 23 //输出结构体中各个变量的数值 24 ui>line_StructRead_1>setText(QString::number(PlcVar.intVal,10)); 25 ui>line_StructRead_2>setText(QString("%1").arg(PlcVar.floatVal)); 26 if(PlcVar.boolVal == true) 27 30 else 311 //向PLC写入结构体 2 //输入结构体的数值 3 struct PlcVarstruct //定义结构体 4 PlcVar; 9 unsigned long lHdlVar3; 10 char szVar3[] = ; 11 12 PlcVar.intVal = ui>line_StructWrite_1>text().toInt(); 13 PlcVar.floatVal = ui>line_StructWrite_2>text().toFloat(); 14 if(ui>line_StructWrite_3>text().trimmed() == "1") 15 18 else 19 22 23 //得到PlcVar的句柄 24 nErr = AdsSyncReadWriteReq(pAddr, ADSIGRP_SYM_HNDBYNAME, 0x0, sizeof(lHdlVar3), &lHdlVar3, sizeof(szVar3), &szVar3); 25 if (nErr) 26 29 //通过之前获取的句柄向PLC写入结构体 30 AdsSyncWriteReq(pAddr, ADSIGRP_SYM_VALBYHND, lHdlVar3, sizeof(PlcVar), &PlcVar); 31 if (nErr) 32
事件通知
1 void MainWindow::on_pushButton_NotifyOpen_clicked() 2 ; 6 7 // set the attributes of the notification 8 adsNotificationAttribbLength = 4; 9 adsNotificationAttrib.nTransMode = ADSTRANS_SERVERONCHA; 10 adsNotificationAttrib.nMaxDelay = 0; 11 adsNotificationAttrib.nCycleTime = 10000000; // 1sec 12 13 // get handle 14 nErr = AdsSyncReadWriteReq(pAddr, ADSIGRP_SYM_HNDBYNAME, 0x0, sizeof(hUser), &hUser, sizeof(szVar), szVar); 15 if (nErr) 16 19 20 // initiate the transmission of the PLCvariable 21 nErr = AdsSyncAddDeviceNotificationReq(pAddr, ADSIGRP_SYM_VALBYHND, hUser, &adsNotificationAttrib, Callback, hUser, &hNotification); 22 if (nErr) 23 26 } 27 28 29 // Callbackfunction 30 void __stdcall CALLBACK MainWindow::Callback(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser) 31static void __stdcall CALLBACK Callback(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser);
上一篇:Qt Q_GLOBAL_STATIC创建全局静态对象
Qt 倍福(Beckhoff)
pla文件怎么看,pla文件用什么打开?
pl1文件怎么看,pl1文件用什么打开?
pl文件怎么看,pl文件用什么打开?
pl0文件怎么看,pl0文件用什么打开?
pkt文件怎么看,pkt文件用什么打开?
pkm文件怎么看,pkm文件用什么打开?
pks文件怎么看,pks文件用什么打开?
pka文件怎么看,pka文件用什么打开?
pkh文件怎么看,pkh文件用什么打开?
pkg文件怎么看,pkg文件用什么打开?