win10系统下TwinCAT3与VS2019之间的ADS通信

@WIN10, TwinCAT3, VS2019, ADS
转博后第一次出差,来到了UnitedImaging,这次的任务是负责在ros系统和TwinCAT3之间的 ADS 通信。
作为本次第一篇博客,先跑通win10系统下TwinCAT3与VS2019之间的ads通信。
本文在PLC中设置一个BOOL量,通过c++控制台来读取和写入该值,从而实现第一步的通信读写。

TwinCAT3 TcXaeShell程序编写

  1. 首先安装TwinCAT3 ,倍福的网站:

     https://tr.beckhoff.com.cn/course/view.php?id=136
    

这里面有完整的介绍。

  1. 选择一个简单的实例,这里我跑了一下倍福的教程通过c++程序读取/写入PLC程序中的布尔量,该任务实现分为两部分:1)在TwinCAT程序下编写PLC的程序;2)在vs2019下编写c++程序。

TwinCAT PLC 程序编写

首先进行PLC程序的编写,本节分为三部分1)如何新建一个项目;2)程序代码的介绍和编写;3)如何调试。

如何新建项目

1.新建project
打开下载好的TwinCAT3 TcXaeShell,点击文件->新建->项目,如下图所示,选择TwinCAT Projects下的TwinCAT XAE Project,设置好项目名称和路径,注意路径中不要出现中文
新建项目

添加新项

在项目中找到PLC,(如下图所示)右键添加新项,选择Standard PLC Project,命名成PLC_TEST1,点击添加,这样我们的项目就建好了。outline
在这里插入图片描述

  1. 编写第一个程序
    在左侧解决方案资源管理器中PLC->PLC_TEST1->PLC_TEST1 Project->POUs,里面已经有了主程序MIAN(PRG)
    双击点开可以发现有上下两块,分别代表变量声明区程序代码区

在变量声明区(上面的区域)定义一个名称为BOOL1的BOOL型变量,并赋予其地址“AT %MD0”,

PROGRAM MAIN
VAR
BOOL1 AT %MD0 : BOOL;
END_VAR

在程序代码区中输入一个“;”(相当于return)

;

在这里插入图片描述
3. 程序调试
在调试前先以管理员身份运行C:\TwinCAT\3.1\System下面的 win8settick.bat,上方有三个小图标,左边楼梯一样的代表激活,中间绿色方框代表run,右边蓝色代表退出run。
首先把鼠标选择到PLC_TEST1 Project右键点击生成,这样就Build了代码,然后点击楼梯一样的小图标activate项目,最后点击绿色图标程序就开始运行了。

在这里插入图片描述
然后点击登录到(这个绿色的箭头),表示你的程序接入了通信网络
在这里插入图片描述

在这里插入图片描述
到这里我们的PLC程序编写以及运行已经OK了,接下来就进行C++的编写。

Vs 2019程序环境配置

首先要保证TwinCAT3和Vs2019 同属于一个平台 x86或者x64,这里选择x64, 在给定的API里面有3个文件:TcAdsAPI.h,TcAdsDef.h和TcAdsDll.lib

  1. 配置环境
    包含目录:包含.h文件的路径
    库目录:包含.lib
    在这里插入图片描述链接器
    库目录:lib文件目录
    在这里插入图片描述
    输入:TcAdsDll.lib
    在这里插入图片描述
  2. 编写程序
    首先新建控制台项目,如下图所示,新建项目PLCConsole

在这里插入图片描述

  1. 编写程序
    主程序中输入如下代码

#include //标准的输入输出流头文件
#include <conio.h> //控制台输入输出头文件
#include <windows.h> //windowsAPI的函数声明和宏
#include “TcAdsDef.h” //结构体和常量的声明
#include “TcAdsAPI.h” // ADS函数的声明
#include <conio.h>
#include <stdio.h>
using namespace std;
int main()
{
long nErr, nPort; //定义端口变量
AmsAddr Addr; //定义AMS地址变量
PAmsAddr pAddr = &Addr; //定义端口地址变量
bool BOOL1; //定义布尔量
nPort = AdsPortOpen(); //打开ADS通讯端口
nErr = AdsGetLocalAddress(pAddr); //得到本地端口地址
if (nErr) std::cerr << "Error: AdsGetLocalAddress: " << nErr << ‘\n’; //检查获取地址的操作是否执行成功
pAddr->port = 851; //将指针指向851端口
do
{
//向PLC中读取BOOL量
nErr = AdsSyncReadReq(pAddr, 0x4020, 0x0, 0x1, &BOOL1); //从ADS服务器同步读取数据,pAddr:ADS设备的地址,0x4020:段地址,0x0偏移地址,0x1:数据长度,@BOOL1:接收数据的缓存
if (nErr) std::cerr << "Error: AdsSyncReadReq: " << nErr << ‘\n’; //检查获取地址的操作是否执行成功
cout << BOOL1 << ‘\n’; //输出”BOOL1”的值
//在控制台上输出BOOL:
cin >> BOOL1; //为BOOL1赋值
nErr = AdsSyncWriteReq(pAddr, 0x4020, 0x0, 0x1, &BOOL1); //同步写数据到ADS设备,pAddr:ADS设备的地址,0x4020:段地址,0x0偏移地址,0x1:数据长度,@BOOL1:接收数据的缓存
if (nErr) cerr << "Error: AdsSyncWriteReq: " << nErr << ‘\n’; //检查获取地址的操作是否执行成功
} while (_getch() == ‘\r’); //用do-while语句来实现循环读取
nErr = AdsPortClose(); //关闭ADS通讯端口
if (nErr) std::cerr << "Error: AdsPortClose: " << nErr << ‘\n’; //检查关闭通讯端口的操作是否执行成功
return 1;
}

  1. 编译程序并运行
    编译程序并运行,首先观察PLC程序中BOOL1的值是FALSE
    在这里插入图片描述
    运行PLCConsole,显示值为0,说明成果读取BOOL1的值是FALSE(也就是0)
    在这里插入图片描述

接下来在控制台中输入1并回车
在这里插入图片描述
这个时候已经把BOOL1的值写入给了PLC程序,进入PLC程序去看看吧~
在这里插入图片描述
果然被改成了TRUE,通信成功!

猜你喜欢

转载自blog.csdn.net/hujiawei_SJTU/article/details/108796242