上位机使用C++通过ADS协议与倍福PLC通信例程-通过变量名方式读写浮点数

前言

建议初学者先看这一章节内容,里面包括一些基础的环境配置和项目建立流程,以后开发项目这些流程是通用的,务必掌握并熟练。
链接: 上位机使用C++通过ADS协议与倍福PLC通信例程-布尔变量的读取

ADS读写TwinCAT中变量的方式

ADS读写TwinCAT中变量的方式有两种,一种通过IndexGroup和IndexOffset信息访问变量,另一种方式是通过变量名的形式访问变量。

通过IndexGroup和IndexOffset访问变量

在这里插入图片描述
如上图所示,PLCVar1的IndexGroup和IndexOffset分别是4040和5DFE8,这样在使用倍福提供的库函数时,只需要填写以上信息就可以。例如使用ADS的读取函数,当读取PLCVar1时,若在上位机上声明一个变量 PLCVar1Get来存放读取上来的值,那么nLength=4(按字节计量变量的大小,在函数的形参中通常以sizeof(PLCVar1Get)出现,编程人员应该自己检查确保计算的结果是4bytes),

float PLCVar1Get;

那么pData就是指向PLCVar1Get的指针,一般在形参中以“&PLCVar1Get”出现。

LONG AdsSyncReadReq(
     PAmsAddr  pAddr,
     ULONG  nIndexGroup,
     ULONG  nIndexOffset,
     ULONG  nLength,
     PVOID  pData);  

pAddr结构体包含PLC中的AMS地址和ADS端口号,可参考文章开头部分提供的例程理解,此处不再赘述。
通过IndexGroup和IndexOffset读写有什么劣势呢?
在实际编程中,如果变量名起的不合理,或者类型需要更改时,IndexOffset就有可能变动,导致程序更改麻烦且困难,极容易漏掉一些忘记更改的程序行导致出错,下面以更改变量名字为例,看一下更改后的情况,把PLCVar1更改为PLCVar1_1后,IndexOffset的值由5DEF8变为了608D0,此时就需要把程序中用的5DEF8的地方更改为608D0,程序较大时就显得繁琐低效。
在这里插入图片描述

通过变量名的方式访问变量

倍福的官方文档中是推荐用户优先使用通过变量名方式来访问变量,通过变量名的方式访问变量的本质是先通过变量名获取该变量的句柄,之后对该变量的操作均以句柄进行,这里的句柄是指windows中的句柄,不能简单等同于变量的指针(嵌入式中有此种叫法),详细解释可参阅百度百科的说明
链接: 句柄
例如,我们要通过变量名的方式访问变量PLCVar1,通过上位机来读写PLCVar1,下面给出了上位机中的程序,如果需要更改变量的名字,那么只需要更改szVar[]数组内的字符串即可。
变量名的全称即为上图中的Full-Name栏的内容

#include <iostream>
#include <windows.h>
#include <conio.h>



// ADS headers for TwinCAT 3
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h"
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsAPI.h"

using namespace std;
int main()
{
	long nErr, nPort;
	AmsAddr Addr;
	PAmsAddr pAddr = &Addr;
	ULONG lHdlVar;//用来存放MAIN.PLCVar1变量的句柄
	float PLCVar1Get;//该变量存放要写入PLC中的值
	char szVar[] = { "MAIN.PLCVar1" };//需要读写的PLC中的变量名的全称

	// Open communication port on the ADS router
	nPort = AdsPortOpen();
	nErr = AdsGetLocalAddress(pAddr);
	if (nErr) cerr << "Error: AdsGetLocalAddress: " << nErr << '\n';

	// TwinCAT 3 PLC1 = 851
	pAddr->port = 851;

	// 获取MAIN.PLCVar1变量的句柄
	nErr = AdsSyncReadWriteReq(pAddr, ADSIGRP_SYM_HNDBYNAME, 0x0, sizeof(lHdlVar), &lHdlVar, sizeof(szVar), szVar);
	cout << "HandleNum Of Variable:"<<lHdlVar << endl;
	if (nErr) cerr << "Error: AdsSyncReadWriteReq: " << nErr << '\n';
	while(1)
	{
		// Read value of a PLC variable (by handle)
		nErr = AdsSyncReadReq(pAddr, ADSIGRP_SYM_VALBYHND, lHdlVar, sizeof(PLCVar1Get), &PLCVar1Get);
		if (nErr)
			cerr << "Fehler: AdsSyncReadReq: " << nErr << '\n';
		else
			cout << "MAIN.PLCVar1: " << PLCVar1Get << '\n';
		cout.flush();
		cin >> PLCVar1Get;
			nErr = AdsSyncWriteReq(pAddr, ADSIGRP_SYM_VALBYHND, lHdlVar, sizeof(PLCVar1Get), &PLCVar1Get);
			if (nErr) cerr << "Error: AdsSyncWriteReq: " << nErr << '\n';
	} 

/*

	//Release handle of plc variable
	nErr = AdsSyncWriteReq(pAddr, ADSIGRP_SYM_RELEASEHND, 0, sizeof(lHdlVar), &lHdlVar);
	if (nErr) cerr << "Error: AdsSyncWriteReq: " << nErr << '\n';

	// Close communication port
	nErr = AdsPortClose();
	if (nErr) cerr << "Error: AdsPortClose: " << nErr << '\n';
	return 0;
*/
}

下面给出PLC中的程序

PROGRAM MAIN
VAR
	PLCVar1:REAL;
	PLCVar2:BOOL;
	PLCVar3:INT;
END_VAR

运行结果如下图所示,PLC中的变量初始值我们设为30.22,运行上位机程序后可以读到变量是30.22
在这里插入图片描述
在这里插入图片描述
把变量更改为50.1478,可以看到PLC中的变量已经变为50.1478
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值