1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 上位机使用C++通过ADS协议与倍福PLC通信例程-字符串变量读取

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

时间:2018-12-23 19:53:02

相关推荐

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

前言

建议初学者先看这一章节内容,里面包括一些基础的环境配置和项目建立流程,以后开发项目这些流程是通用的,务必掌握并熟练。

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

字符串知识

C/C++对字符串的处理

字符串是字符按一定顺序排列的结果,大部分情况下就是由字母组成的单词和句子,在C/C++中,字符串不是一个基本变量类型,基本变量类型是指char,int,float等这种变量类型,C/C++把字符串储存在字符数组中,即char类型的数组中,并在数组的末尾添加“\0”空字符来表示字符串的结束,可以理解为这是一个结束标记,这样处理以后,实际字符串占的存储单元就多了1个字节,如果声明一个char[20]的数组,那它最多能存储19个字符,如果直接声明一个例如string类型的变量,例如下面这个

// string类型的变量std::string VarString1 = "Trump is back";

那么 VarString1将占用14个字节(空格也要占用一个字节)

TwinCAT对字符串的处理

在TwinCAT中,如果使用的是ST编程语言(IEC61131-3中规定的PLC编程语言中的一种),它是提供string类型的变量的,但其存储方式与C/C++对字符串的处理是一样的,同样用字符数组来存储,如果不指定大小,系统默认会分配一个80个字符的空间留给用户使用,在存储单元中则占据81个字节(因为要存储\0结束符号),如下图所示,我们实际赋值的时候,不要超过80个字符就可以了。

上位机程序实现

在上位机中,声明一个char Data1[81]的数组用来存放从PLC中读取上来的字符串值,这里的81即和PLC中string声明出来的变量所占空间匹配的结果。

#include <iostream>#include<conio.h>#include <stdio.h>#include<iomanip>#include<Windows.h>#include "TcAdsDef.h" //结构体和常量的声明#include "TcAdsAPI.h" // ADS函数的声明longnErr, nPort;//定义端口变量AmsAddr LocalAddr;//定义上位机AMS地址变量PAmsAddr LocalpAddr = &LocalAddr;//定义上位机ADS端口地址变量(上位机用来进行ADS通信的端口)AmsAddr Tc3Addr;//定义安装有TwinCAT3的下位机AMS地址变量(由于是本机测试,上位机和下位机的AMS地址是一样的)PAmsAddr Tc3pAddr = &Tc3Addr;//定义下位机端口地址变量(这里是读取PLC程序中变量,所以该端口固定为851)/* 读取bool量的配置信息 */unsigned long IndexGroup = 0xF020; //要读取的对象的索引编号unsigned long IndexOffset = 0x5DE93; // 要读取对象的偏移量编号unsigned long Length = 1; //要读取对象的大小,计量单位为bytebool Data;//该变量用来存放读上来的值,变量类型要和待读取的值匹配/* 读取字符串变量的配置信息 */unsigned long IndexGroup1 = 0x4040;//要读取的对象的索引编号unsigned long IndexOffset1 = 0x6CF40; // 要读取对象的偏移量编号unsigned long Length1 = 81; //要读取对象的大小,计量单位为bytechar Data1[81]; //该变量用来存放读上来的值,变量类型要和待读取的值匹配void ReadBoolen(void);void ReadString(void);int main(){//建立接口通讯连接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->netId.b[0] = 5; //填入下位机的地址,即远程PLC的AmsNetIDTc3pAddr->netId.b[1] = 19;Tc3pAddr->netId.b[2] = 218;Tc3pAddr->netId.b[3] = 60;Tc3pAddr->netId.b[4] = 1;Tc3pAddr->netId.b[5] = 1;Tc3pAddr->port = 851; //填入下位机的TC3 PLC的通讯端口(851),这是倍福官方规定的,固定为851,TC2中为801,增加几个PLC,就依次增加为852,853...std::cout << "The Remote PLC AmsNetID is: ";printf("%d.", Tc3pAddr->netId.b[0]);printf("%d.", Tc3pAddr->netId.b[1]);printf("%d.", Tc3pAddr->netId.b[2]);printf("%d.", Tc3pAddr->netId.b[3]);printf("%d.", Tc3pAddr->netId.b[4]);printf("%d.", Tc3pAddr->netId.b[5]);std::cout << std::endl;std::cout << "The Remote PLC ADS ComunicationPort is : "<<Tc3pAddr->port<<std::endl;while (1){Sleep(500);ReadBoolen();ReadString();}}void ReadBoolen(void){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刷新一次值}void ReadString(void){nErr = AdsSyncReadReq(Tc3pAddr, IndexGroup1, IndexOffset1, Length1, &Data1);if (nErr)std::cerr << "ReadFailed! The Error Code is: " << nErr << '\n';else{std::cout << "Operation Succeed!" << std::endl;std::cout << "The Value Read is:" << Data1 << std::endl;}Sleep(500);//每500ms刷新一次值}

下位机程序实现

变量声明区的内容

PROGRAM MAINVARbVarOut1 AT%Q*:BOOL;bVarIn1 AT%I*:BOOL;sString:STRING;END_VAR

程序区的内容

bVarOut1 := bVarIn1;sString :='Trump is back!';

运行上位机程序和远程PLC(切换到运行状态下),可以看见能成功读取到PLC中声明的string类型变量

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。