上位机使用C++通过ADS协议与倍福PLC通信例程-布尔变量的读取

背景知识介绍

ADS通信协议介绍

所谓通信协议,就是通信双方约定的一种数据识别规范,例如,你讲汉语,我也讲汉语,那么我们之间沟通的“通信协议”就是汉语,汉语中的汉字,发音,语法结构等等你也清楚,我也清楚,所以我们可以正确了解对方的意思,类似于通信协议中规定的传输媒介,信号编码规范,数据帧各部分的含义一样,不用把它想得特别深奥,就是机器设备之间的“语言”。
ADS全称是Automation Device Specification(汉译:自动化设备规范),在倍福TwinCAT的设计理念中,每一个软件模块都视为一个“设备”,这些“设备”相互独立,彼此之间通过ADS通信协议交换数据,ADS是一个应用层的协议,它架构在TCP/IP协议之上(ADS负责应用层,TCP负责传输层,IP负责网络层,还有一个数据链路层),ADS协议由德国倍福开发,且作为对外开放的通信接口来方便用户访问TwinCAT系统中各个软件模块的参数(配置参数,过程参数,运动参数等等)
有关ADS更为详细的信息介绍可以参考倍福官方网站的介绍:
链接ADS introduction

基于VS2019的控制台上位机程序

定位官方库函数

注意,该程序使用了倍福官方提供的库函数,如果你是安装在C盘默认路径的话,那么官方的库函数在这个目录中
函数库的安装目录
如果是基于X86的架构,那么使用include和lib文件夹中的内容即可,如果是基于X64的架构,那么lib就要用x64这个文件下的内容,这个配置会在VS2019的项目设置过程中用到,要留意一下。

建立工程

建立控制台应用程序
点击下一步,为了方便,直接使用默认的名称
创建工程
点击创建,就建立起一个“HelloWorld”工程,要特别注意图中画红色框的部分,后续配置库函数要注意和这里匹配
HelloWorld工程
右键项目名称,在弹出的右键菜单下选择属性,弹出如下对话框
配置C++附加包含目录
在附加包含目录右侧的小箭头,选择<编辑…>,打开倍福官方库提供的头文件目录位置,注意图里最上面的配置也是Debug,平台也是Win32。
头文件包含设置
使用同样的方法配置链接器的选项
附加库目录配置
附件依赖项的配置方法如下
附件依赖项的配置
配置好以后保存一下工程,关闭VS2019,重新打开,以使配置生效。此时包含头文件后,进行一下编译,会提示编译已通过
编译头文件进行测试
若编译过程中提示未定义的标识符等错误,重点检查以上配置内容,配置好以后一定要保存后,再重新打开软件,导入刚才的工程,即可使配置内容生效。
将以下程序拷贝到main()主函数所在的文件中

#include <iostream>
#include<conio.h>
#include <stdio.h>
#include<Windows.h>
#include "TcAdsDef.h" //结构体和常量的声明
#include "TcAdsAPI.h" // ADS函数的声明
int main()
{
	long      nErr, nPort;		//定义端口变量
	AmsAddr   LocalAddr;				//定义上位机AMS地址变量
	PAmsAddr  LocalpAddr = &LocalAddr;	//定义上位机ADS端口地址变量(上位机用来进行ADS通信的端口)

	AmsAddr   Tc3Addr;				//定义安装有TwinCAT3的下位机AMS地址变量(由于是本机测试,上位机和下位机的AMS地址是一样的)
	PAmsAddr  Tc3pAddr = &Tc3Addr;	//定义下位机端口地址变量(这里是读取PLC程序中变量,所以该端口固定为851)
	unsigned long IndexGroup=0x4020;   //要读取的对象的索引编号
	unsigned long IndexOffset=0x5E010; // 要读取对象的偏移量编号
	unsigned long Length=1;            //要读取对象的大小,计量单位为byte
	bool Data;                         //该变量用来存放读上来的值,变量类型要和待读取的值匹配
	//建立接口通讯连接
	nPort = AdsPortOpen();		//打开ADS通讯端口
	nErr = AdsGetLocalAddress(LocalpAddr); //自动获取本地地址
	if (nErr) 
		std::cerr << "Error: AdsGetLocalAddress: " << nErr << '\n';
	else
	{
		std::cout << "LocalAdsAddress is: " ;
		printf("%d.",LocalpAddr->netId.b[0]);
		printf("%d.", LocalpAddr->netId.b[1]);
		printf("%d.", LocalpAddr->netId.b[2]);
		printf("%d.", LocalpAddr->netId.b[3]);
		printf("%d.", LocalpAddr->netId.b[4]);
		printf("%d.", LocalpAddr->netId.b[5]);
		std::cout << std::endl;
		std::cout << "LocalAdsPort Assigned is:" << LocalpAddr->port << std::endl;
	}
	if (nPort == LocalpAddr->port)
	{
		std::cout << "LocalAdsPort: " << nPort << " opened!" << std::endl;
	}
	else
	{
		std::cout << "LocalAdsPort open failed!" << std::endl;
	}
	Tc3pAddr = LocalpAddr; //上位机和下位机都是同一台电脑,故AMS地址是一样的
	Tc3pAddr->port = 851; //把下位机的TC3 PLC的通讯端口设为851,这是倍福官方规定的,固定为851,TC2中为801,增加几个PLC,就依次增加为852,853...
	std::cout << "TC3 PLC ADS Communication Port is:" << Tc3pAddr->port << std::endl;
	while (1)
	{
		nErr = AdsSyncReadReq(Tc3pAddr, IndexGroup, IndexOffset, Length, &Data);
		if (nErr)
			std::cerr << "ReadFailed! The Error Code is: " << nErr << '\n';
		else
		{
			std::cout << "Operation Succeed!" << std::endl;
			std::cout << "The Value Read is:" << Data << std::endl;
		}
		Sleep(500);//每500ms刷新一次值
	}
	
}

重新生成解决方案
重新编译
此时按F5运行程序,会出现以下提示,能够正确读取本机的ADS的AmsNetID,以及本机分配到的ADS端口号(这个端口号是ADS router分配的)但是因为没有开启PLC,所以读不到PLC中变量的值。
读取本机的AmsNetID
接下来编写PLC部分的程序,关于PLC程序的编写,因为比较简单,这里不再赘述,编写一个bool量,该bool量每100ms反转一次值,点击激活按钮,将程序下载到PLC中
PLC程序编写
点击Login登入
登入程序

点击scope,Target browser,从这里查看PLC中变量的ADS信息,如图中红色圈所示,这几个值要和程序中的变量对应上才可以正确读取。
在这里插入图片描述
点击Start(或者F5)运行PLC程序,可以观察到PLC中的变量开始每100ms变化一次
PLC程序已运行
此时切回到上位机的程序中,按F5运行,可以看到已读取到PLC当中的变量,且该变量值在变化,因为我们的读取周期(500ms)和plc更新变量的周期(100ms)不一致,故存在“不同步”的情况。
在这里插入图片描述
对应的上位机工程文件包可从这里下载:
链接: 上位机工程文件
对应的下位机工程文件包可从这里下载:
链接: 下位机工程文件
TwinCAT3中工程文件的导入方法可参考下图所示
在这里插入图片描述

  • 5
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值