基于MFC的计算机与PLC以太网通讯软件开发

2018-12-06 02:26燕科帆朱厚耀林贺邦李嘉龙
机电工程技术 2018年10期
关键词:寄存器字节以太网

燕科帆,朱厚耀,林贺邦,李嘉龙

(广州大学机械与电气工程学院,广东广州 510006)

0 引言

在整个上位机软件的开发过程里面,最重要的部分是上位机对于下位机的数据监测,这就要解决二者之间的通信问题,实现稳定的通信才能稳定地进行数据监测和数据交换。传统的通信方法是采用RS-232C或者RS-485串行方式,但是随着对于传输数据量、设备之间的传输距离以及通信的实时性要求越来越高,传统的串行通信方式慢慢的不能满足大部分企业的要求[1]。同时,由于国际上现场总线的标准非常多,导致难以实现控制系统集成的统一。所以国际上大部分厂商开始将生产的PLC与以太网技术进行结合,PLC控制器与基于TCP∕IP的以太网结合,可以实现开放、分散的工业控制系统,按照相关的协议就可以进行PLC与计算机的通讯[2]。

1 ABB AC500系列PLC通讯功能

1.1 概述

AC500系列是ABB公司新一代的模块式可编程控制器,是一款可升级的,灵活的自动化控制系统。系统的构建采用底板组合模块的结构。硬件上可选用的模块有CPU模块和底板、I∕O模块和底板、FBP总线适配器和底板以及通讯模块等,以上的各种模块均有许多型号,每种型号对应的配置都不一样,可以根据实际的需求选型。不同的CPU模块插在CPU底板上,不同的I∕O模块插在I∕O底板上,直接拼接在CPU底板的右侧,通过I∕O总线进行数据交换,其他的模块也是采用拼接的方法插在底板上,示例如图1所示。通讯模块有四种型号,分别是CM572-DP:PROFIBUSDP主站通讯模块、CM575-DN:DeviceNet主站通讯模块、CM577-ETH:以太网通讯模块、CM578-CN:CANopen主站通讯模块。

以太网通讯模块支持的协议包括TCP∕IP、UDP∕IP和Modbus TCP。其中本文的通讯采用基于Modbus TCP协议的以太网通讯,AC500的以太网通讯模块集成了“MOD⁃BUSon TCP∕IP”协议,所以可以通过Ethernet(以太网)进行MODBUS通讯[3]。

图1 AC500系列PLC硬件组成

1.2 Modbus/TCP协议简介

Modbus通信协议是全球最早用于工业现场的总线规约,由Modicon公司在1979年发明。由于免费发布,并且采用主从通信模式(Master∕Slave通信模式),在分散控制方面应用广泛,从而在全球得到了广泛的应用。Modbus通信协议具有串口和以太网多种版本,其中比较著名的是Modbus RTU、Modbus ASCII和 Modbus∕TCP 三种。其中Modbus∕TCP协议是通过一种简单的方式将Modbus帧嵌入到TCP帧中而形成的,由于TCP是基于可靠连接的服务,所以在Modbus TCP协议中没有CRC校验码,从而简化了协议的内容。

Modbus∕TCP数据帧的组成简单分成三个部分,分别是报文头、功能代码和数据。如图2所示。

图2 Modbus∕TCP数据帧

MBAP报文头分为四个域,一共七个字节。1、2字节是传输标志,标志某个Modbus询问∕应答的传输;3、4字节是协议标志,表示协议的种类;5、6字节是长度,表示后续字节的长度计数;7字节是单元标志。

功能代码共有三种类型,分别是公共功能代码、用户自定义功能代码和保留的功能代码。本文所用到的为公共功能代码,分别是十进制的03(读多个寄存器)和十进制的16(写多个寄存器)。其余的常见公共功能代码见表1所示[4]。

2 MFC CSocket类简介和通讯流程

2.1 MFC CSocket简介

MFC(Microsoft Foundation Classes)是微软基础类库,是一个C++的类库,封装了大部分windows API函数。它提供了两个类,这两个类都封装了socket,分别是CAsync⁃Socket和CSocket,CSocket是CAsyncSocket子类,二者的区别在于CAsyncSocket是异步套接字,而CSocket是同步套接字。

使用MFC的socket类可以从这两个socket类中继承出自己的socket类,再根据需求增加所继承的socket类功能。如果需要使用这两个socket类,一定要从这两个类中继承出自己的socket类,通过修改虚函数来实现特定基本功能。有了这两个类就可以方便的处理同步与异步问题。

本文采用的是CSocket类,需要实现的功能是读写数据,因此需要用到的虚函数为OnReceive(),需要对该虚函数进行重载。当有一个socket向CSocket继承类发送数据的时候,CSocket继承类的OnReceive()虚函数会被自动执行,因此接收数据可以在OnReceive()虚函数里通过定义的Receive()函数来实现。

2.2 通讯流程

Socket通信采用的模式为客户端和服务器,本文开发的软件为客户端,PLC为服务器。通过服务器的IP地址和ModbusTCP固定的502端口,就能进行客户端和服务器端的连接,连接后就能进行以太网数据通讯。因此按照socket通信流程,利用CSocket类的成员函数实现通信流程中的各个步骤就能进行通讯[5]。Socket通信流程如图3所示。

3 ABB PLC以太网通讯配置

当需要进行上位机与PLC以太网通讯时,需要先进行PLC的硬件系统配置。本系统选用的CPU型号为PM583,串口型号为DC532。该CPU自带以太网通讯口。系统配置的步骤如下。

(1)打开ABB配套的系统组态软件Control builder Plus,新建AC500工程,按照硬件系统的配置在软件中对应进行添加,比如串口模块,通信模块等等,如图4所示。

图3 CSocket实现Modbus∕TCP通讯流程图

图4 系统组态树状图

(2)按照步骤(1)中添加的模块,分别进行参数配置,例如CPU模块,双击CPU模块进行参数配置,本系统默认参数均能满足要求。同理对I∕O模块进行参数配置。

(3)将电脑和PLC通过网线连接,PLC上电,通过图4中的IP_Settings(IP设置)设置PLC的IP地址。

(4)上位机软件开发好后,将PC机的IP地址设置成和PLC同一个网段,这样就完成整个系统的硬件和软件的配置过程[6]。

4 具体的程序实现

4.1 程序框架搭建

本程序采用VS2013IDE编程环境,创建基于对话框的MFC程序。因为需要用到CSocket类,所以必须在导向中勾选Windows套接字选项。在界面输入服务器地址和端口号就能进行通讯连接。以下是程序的创建步骤和部分代码。

(1)创建基于对话框的MFC程序,勾选Windows套接字选项。

(2)在对话框中加入所需的各种控件,比如IP地址输入框等等,并对各个控件添加变量。

(3)创建一个继承自CSocket类的MFC类,命名My⁃Socket,用来进行socket通信。对MySocket类的虚函数进行重载,在OnReceive()函数体里面调用Receive()函数,从而起到接收数据的作用。

(4)添加两个按钮控件,分别取名为读取数据和修改数据。二者的作用是对PLC进行数据读取和修改,将相关的代码都封装到这两个按钮控件里面。

以下列出部分相关代码。

void CMysocket::OnReceive(int nErrorCode)∕对 MySock⁃et类虚函数进行重载

{

if(pClientdlg)

{

pClientdlg->Receive();∕调用主对话框的 Re⁃ceive方法接收数据

}

CSocket::OnReceive(nErrorCode);

}

以下为通讯连接部分程序代码:

pMysocket=new CMysocket(this);∕创建套接字对象

if(pMysocket->Create()==FALSE)∕创建套接字

{

deletepMysocket;

pMysocket=NULL;

AfxMessageBox(_T("套接字创建失败!"));

return;

}

if(pMysocket->Connect(servername,port)==FALSE)∕连接服务器、connect函数成功则返回1,失败则返回0

{

AfxMessageBox(_T("连接服务器失败!"));

return;

}

4.2 读PLC数据

对PLC进行数据读取需要用到功能码03,首先需要定义一个数组来存放读取数据的数据包:

unsigned char Send[12]={0};∕生成 Modbus∕TCP 格式数据包

读取数据是对PLC的寄存器进行读取,所以对于寄存器的起始地址和寄存器的数量是需要确定的[7]。下面为整个数组的定义:

Send[0]=m_1;

Send[1]=m_2;∕事务元标识符,高字节在前,低字节在后

Send[2]=m_3;

Send[3]=m_4;∕协议标识符,高字节在前,低字节在后

Send[4]=0x00;

Send[5]=0x06;∕后续字节长度,高字节在前,低字节在后

Send[6]=m_5;∕单元标识符

Send[7]=0x03;∕功能码,读多个寄存器

Send[8]=m_register_address_high;∕数据起始地址,高字节在前,低字节在后

Send[9]=m_register_address_low;

Send[10]=m_register_number_high;∕数据长度,高字节在前,低字节在后

Send[11]=m_register_number_low;

int a=pMysocket->Send(Send,12);∕Send 函数返回的是成功发送的字节数

用MySocket类的指针对象调用Send()函数就能数据包发送出去。当包含读取多个寄存器功能码的数据包发送给PLC后,PLC会立即返回对应的数据给通讯软件,这时会触发OnReceive()函数,从而触发接受数据函数Re⁃ceive()。在Receive()函数体里面同样定义一个数组用来存放PLC反馈回来的数据,部分程序如下所示:

unsigned char Receive[200];∕接收反馈的数据

int receive_data_num = pMysocket->Receive(Receive,200);∕Receive()函数的返回值为所接收到的字节数量。

如图5所示为读取数据图。

图5 读取PLC数据

4.3 对PLC写值

对PLC写值和读取PLC数据的内容大致是一样的,只需要修改功能代码并且加入需要写入的值即可。本软件目前固定一次可以写三个寄存器。以下所示为对PLC写值的定义方法。m_value1、m_value2、m_value3为三个需要写入的值,可以从界面输入。

Send[13]=m_value1∕256;

Send[14]=m_value1%256;

Send[15]=m_value2∕256;

SendB16]=m_value2%256;

Send[17]=m_value3∕256;

Send[18]=m_value3%256;

如图6所示为写数据图。

图6 对PLC写数据

5 结束语

本文介绍了ABBAC500系列PLC的构造组成和通讯方式,并且对ModbusTCP通讯协议进行了总结。通过创建基于对话框的MFC程序,利用封装的CSocket类,按照sock⁃et通信的流程创建了以太网通讯的上位机软件。同时按步骤讲述PLC的组态配置过程和程序编写,从而使读者对整个流程有基本的掌握。本软件的框架移植性很高,可以在这个基础上进行各个方面的扩展,利于PLC的推广和发展。

猜你喜欢
寄存器字节以太网
STM32和51单片机寄存器映射原理异同分析
No.8 字节跳动将推出独立出口电商APP
基于1500以太网养猪场的智能饲喂控制系统的设计与实现
Lite寄存器模型的设计与实现
No.10 “字节跳动手机”要来了?
基于MSP430的四旋翼飞行器的S-BUS通信协议的设计与实现
移位寄存器及算术运算应用
谈实时以太网EtherCAT技术在变电站自动化中的应用
浅谈EPON与工业以太网在贵遵高速公路中的应用
万兆以太网在连徐高速公路通信系统改造中的应用