[Visual Studio C++] [ 倍福 TwinCAT3 ] “ADS通讯工程实例"讲解

摘要(ABSTRACY)

         本博客在具体的工程中,实现 Visual Studio(简称“上位机”) 与 TwinCAT(简称“下位机”) 之间的 ADS通讯。通过ADS通讯完成上位机与下位机之间的数据传输功能。


摘要(ABSTRACY)

目录:

第一章  绪论

   1.1 ADS通讯定义

   1.2 ADS通讯实现

第二章  ADS通讯技术研究

    2.1 引言

    2.2 Visual Studio (上位机)

   2.2.1 MFC

   2.2.2 ADS_C_ProgramDlg.h

   2.2.3 ADS_C_ProgramDlg.cpp

 2.3 TwinCAT (下位机)

  2.3.1定义变量

  2.3.2编写程序

第三章  总结

附件


 

第一章  绪论

   1.1 ADS通讯定义

     ADS(Advanced Design System)即先进设计系统,它为设备之间的通讯提供路由。在TwinCAT PC 和Beckhoff 的CX、BX、BC 系列控制器中都包含TwinCAT 信息路由器。因此各个ADS 设备之间都能够交换数据和信息。

   1.2 ADS通讯实现

    ADS通讯的实现思想并无难处,你可以简单理解两步:

  • 上位机把数据传给句柄
  • 句柄将数据赋值给下位机

     有一种“A传B, B传C”的感觉。理解这个理论后,你就已经掌握ADS通讯的80%了。ADS通讯需要上位机程序与下位机程序在同一台电脑中运行,并且所有的执行过程都在上位机中编写。

第二章  ADS通讯技术研究

    2.1 引言

      这里将编写两部分工程文件,分别是 Visual Studio(上位机) 和 TwinCAT(下位机) 。

    2.2 Visual Studio (上位机)

      首先,在 Visual C++ 模板下建立一个名为:ADS_C_Program 的 MFC应用程序文件。

      然后,分别对下面三个文件进行编程

  • MFC
  • ADS_C_ProgramDlg.h
  • ADS_C_ProgramDlg.cpp

    2.2.1 MFC

      在做工程之前,需要明白两件事:我要做的什么?怎么实现?

      第一个问题可以在MFC文件中解决,本工程要求两机实现变量、数组和结构体的传输。所以设定界面如下图所示:

  [Visual Studio C++] [ 倍福 TwinCAT3 ] “ADS通讯工程实例

 

    2.2.2 ADS_C_ProgramDlg.h

       将 ADS_C_ProgramDlg.h 文件的编程分成分成三个模块

  • 头文件
  • 全局变量
  • 消息映射函数

      1.头文件

       在添加头文件之前,我们需要添加链接库,以便实现通讯中用到的各种函数的直接调用。我们在左侧找到我们所建立的项目处,点击右键—>Properties 开始添加链接库,如下图所示:

                             [Visual Studio C++] [ 倍福 TwinCAT3 ] “ADS通讯工程实例

        选择 Configuration Properties ->  Linker -> General -> Additional Library Directories,点击右边的按钮进入Additional Library Directories界面。如下图所示,添加我们的程序的所在目录( C:\TwinCAT\ADS Api\TcAdsDll\Lib ),点击确定。(本路径是以安装TWINCAT时的默认路径配置的,若用户在安装时选择自定义路径,则请用户自行修改)  。

[Visual Studio C++] [ 倍福 TwinCAT3 ] “ADS通讯工程实例

       再选择Linker->input->Additional Dependencies,点击右边的按钮进入Additional Dependencies界面。如下图所示添加我们的.Lib文件的文件名(TcAdsDll.lib),点击确定。再次点击确定,链接库添加完成。如下图所示:

                  [Visual Studio C++] [ 倍福 TwinCAT3 ] “ADS通讯工程实例

       这里共引入五个头文件,如下所示:

#include		//标准的输入输出流头文件
#include		//控制台输入输出头文件
#include		//windowsAPI的函数声明和宏
#include"TcAdsDef.h"	//ADS函数的声明
#include"TcAdsAPI.h"	//结构体和常量的声明

         1)#include           是:     标准的输入输出流头文件
         2)#include             是:     控制台输入输出头文件
         3)#include        是:     windowsAPI的函数声明和宏
         4)#include"TcAdsDef.h"        是:     ADS函数的声明
         5)#include"TcAdsAPI.h"        是:     结构体和常量的声明

         TcAdsDef.h 和 TcAdsAPI.h 需要研究员自行添加。方法:在 TwinCAT 文件夹中全局搜索这两个文件名,复制到你所做的工程下。然后,在解决方案的头文件文件夹中将添加两文件。最后,在程序中引用。

        2.全局变量

//ADS通信变量
	long nErr;
	long nPort;
	AmsAddr Addr;
	PAmsAddr pAddr;

//全局变量
//bool 变量
	bool writebool;
	bool readbool;
//Int
	short writeint;
	short readint;
//long
	long writelong;
	long readlong;
//single
	float writesingle;
	float readsingle;
//double
	double writedouble;
	double readdouble;
//string
	char writestring;
	char readstring;
//struct 涉及到占位问题,因此添加几个Dummy占位,没有具体意义。
	typedef struct teststruct
	{
		bool test1;	//1
		bool dummy1;
		bool dummy2;
		bool dummy3;
		short test2;	//2
		short dummy4;
		long test3;		
		float test4;	
		double test5;	
	};
	teststruct writestruct;
	teststruct readstruct;

	short writearray[5];
	short readarray[5];

    3.消息映射函数

       消息映射函数几乎都是由添加MFC工具时自动生成,也有一些为用户自行定义函数。本工程消息映射函数列表如下所示:

protected:
	HICON m_hIcon;
	
	ULONG testlHdlVar; 
	char testszVar;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedButton1();
	afx_msg void OnBnClickedButton2();
	afx_msg void OnDestroy();     
	afx_msg void OnBnClickedButton3();
	afx_msg void OnBnClickedButton4();
	afx_msg void OnBnClickedButton5();
	afx_msg void OnBnClickedButton6();
	afx_msg void OnBnClickedButton7();
	afx_msg void OnBnClickedButton8();
	afx_msg void OnBnClickedButton9();
	afx_msg void OnBnClickedButton10();
	afx_msg void OnBnClickedButton11();
	afx_msg void OnBnClickedButton12();
	afx_msg void OnBnClickedButton15();
	afx_msg void OnBnClickedButton16();
	afx_msg void OnBnClickedButton13();
	afx_msg void OnBnClickedButton14();
	afx_msg void OnBnClickedButton17();
	afx_msg void OnBnClickedButton18();
	afx_msg void OnBnClickedopenthread();
	afx_msg void OnBnClickedclosethread();
	virtual void Run(void);

   2.2.3 ADS_C_ProgramDlg.cpp

        将 ADS_C_ProgramDlg.cpp 文件的编程分成分成两个模块

  • 数据初始化
  • ADS通讯

        1.数据初始化

           数据初始化包括:建立路由、获取NetID、设置PLC端口号、确定端口号、全局变量初始化。

           本工程设定数据如下:

//建立路由、获取NetID、设置PLC端口号
	pAddr = &Addr;
	nPort = AdsPortOpen();
	nErr = AdsGetLocalAddress(pAddr);

//确定端口号
	pAddr->port =851;

//全局变量初始化
//bool 变量
	writebool = 0;
	readbool = 0;
//Int
	writeint = 0;
	readint = 0;
//long
	writelong = 0;
	readlong = 0;
//single
	writesingle = 0;
	readsingle = 0;
//double
	writedouble = 0;
	readdouble = 0;
	writestruct.test1 = 0;
	writestruct.dummy1 = 0;
	writestruct.dummy2 = 0;
	writestruct.dummy3 = 0;
	writestruct.test2 = 0;
	writestruct.dummy4 = 0;
	writestruct.test3 = 0;
	writestruct.test4 = 0;
	writestruct.test5 = 0;
//数组初始化
	int i;
	for (i=0;i<5;i++)
	{
		writearray[i]=0;
		readarray[i]=0;
	}

      2.ADS通讯

         本工程的ADS通讯部分涉及两个内容,数据写入和数据读取。这里以Int型数据传输为例。

        1)使用语句

             ①.定义句柄

        ULONG lHdlVar;

              ②.获取下位机变量

	char szVar[]={"MAIN.IntTest"};

              ③. 获得句柄         

	nErr = AdsSyncReadWriteReq(pAddr,ADSIGRP_SYM_HNDBYNAME,0x0,sizeof(lHdlVar),&lHdlVar,sizeof(szVar),szVar);

               ③. 写入值

	nErr = AdsSyncWriteReq(pAddr,ADSIGRP_SYM_VALBYHND,lHdlVar,2,&writeint);

               ④. 读出值

	nErr = AdsSyncReadReq(pAddr,ADSIGRP_SYM_VALBYHND,lHdlVar,2,&readint);

               ⑤. 释放句柄

	nErr = AdsSyncWriteReq(pAddr,ADSIGRP_SYM_RELEASEHND,0,sizeof(lHdlVar),&lHdlVar);

         2)完整代码

//WriteInt
void CADS_C_ProgramDlg::OnBnClickedButton3()
{
	// TODO: 在此添加控件通知处理程序代码
	ULONG lHdlVar;

	char szVar[]={"MAIN.IntTest"};
	
	CString str;
	
	nErr = AdsSyncReadWriteReq(pAddr,ADSIGRP_SYM_HNDBYNAME,0x0,sizeof(lHdlVar),&lHdlVar,sizeof(szVar),szVar);
	
	GetDlgItemText(IDC_EDIT7,str);

	writeint=atoi(str);

	nErr = AdsSyncWriteReq(pAddr,ADSIGRP_SYM_VALBYHND,lHdlVar,2,&writeint);

	nErr = AdsSyncWriteReq(pAddr,ADSIGRP_SYM_RELEASEHND,0,sizeof(lHdlVar),&lHdlVar);

}

//ReadInt
void CADS_C_ProgramDlg::OnBnClickedButton4()
{
	// TODO: 在此添加控件通知处理程序代码
	ULONG lHdlVar;
	char szVar [] = {"MAIN.IntTest"};
	CString str;
	nErr = AdsSyncReadWriteReq(pAddr,ADSIGRP_SYM_HNDBYNAME,0x0,sizeof(lHdlVar),&lHdlVar,sizeof(szVar),&szVar);

	nErr = AdsSyncReadReq(pAddr,ADSIGRP_SYM_VALBYHND,lHdlVar,2,&readint);

	nErr = AdsSyncWriteReq(pAddr,ADSIGRP_SYM_RELEASEHND,0,sizeof(lHdlVar),&lHdlVar);

	str.Format("%d",readint);
	SetDlgItemText(IDC_EDIT8,str);

}

 2.3 TwinCAT (下位机)

     在整个工程中,ADS通讯都是在上位机中编写的,这使得下位机变简单。

     首先,在  TwinCAT Project 模板下建立一个名为:ADS_PLC_Program 的文件。然后,整个程序分成两部分:

  • 定义变量
  • 编写程序

 2.3.1定义变量

     1.在建立一个工程后,我们需要在MAIN(PRG)中的变量区定义变量。代码如下:

PROGRAM MAIN
VAR
	BoolTest : BOOL; 	//布尔值测试
	IntTest : INT;	//整型测试
	LongTest : DINT;	//长整型测试
	SingleTest : REAL;	//单精度测试
	DoubleTest : LREAL;	//双精度测试
	StringTest : STRING;	//字符串测试
	readstringlen : INT;	//数组测试
	plcstruc : plcstructure;	//结构体测试
	
	plcarraytest : ARRAY[1..5] OF INT;	//五个整型
	override : ARRAY[1..10] OF LREAL;  //10个长实型
	
END_VAR

    2.在DUTs建立新的数据单元(plcstructure)声明一个结构体。代码如下:

TYPE plcstructure :
STRUCT
	plcs1 : BOOL;
	dummy1:BOOL;
	dummy2:BOOL;
	dummy3:BOOL;
	
	plcs2:INT;
	dummy4:INT;
	
	plcs3:DINT;
	plcs4:REAL;
	plcs5:LREAL;
	
END_STRUCT
END_TYPE

  2.3.2编写程序

   在本工程中,不需要下位机实现任何功能,所以随意写一句即可,如下图所示:

readstringlen:=LEN(StringTest);

   现在同时运行上位机和下位机,就可以实现ADS的通讯了。

第三章  总结

           ADS通讯并无难点,有固定的编程思维和程序模板。值得注意是,上位机中两个ADS通讯头文件的添加有点复杂。学习完本教程后,最好做到知识与实践相结合。

           小白将上述例程放在附件中,包含上位机、下位机和例程说明三部分,并且涉及到的知识点都做了详细的注释。例程只是辅助,若能通过上面的讲解独自实现功能,可称为学以成。


附件

       例程。链接:https://download.csdn.net/download/robot_starscream/10788998

       功能包括: ADS通讯、多媒体定时器、线程的应用。训练技能以ADS通讯为主。

你可能感兴趣的:(「,C++,」)