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 8
1 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 8
1 //向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 17
1 //向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 16
1 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 31
1 //向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) 31
static void __stdcall CALLBACK Callback(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser);



上一篇:Qt Q_GLOBAL_STATIC创建全局静态对象

下一篇:Qt QCommandLineOption类


Qt 倍福(Beckhoff)
Copyright © 2002-2019 k262电脑网 www.k262.cn 皖ICP备2020016292号
温馨提示:部分文章图片数据来源与网络,仅供参考!版权归原作者所有,如有侵权请联系删除!QQ:251442993 热门搜索 网站地图