郑 轶,杨明超
(武汉船用电力推进装置研究所,武汉 430064)
随着舰船设备的不断更新换代,对舰船的操作与控制也在逐步向集中式的方向靠拢。艇员依靠集中控制室的计算机便可观测舰船各设备的状态,并可通过计算机向各设备发送指令。舰船设备的状态参数的获取与指令的发送,需要船用通信系统的良好支持。目前应用于舰船的通信方式主要包括CAN通信及以太网通信,其中,以太网通信速率较快,数据传输稳定,不易受到外部干扰,适合大量数据参数的循环上传。
MODBUS协议由Modicon在1979年发明,是OSI模型第7层上的应用层报文传输协议,它定义了一个与基础通信层无关的协议数据单元(PDU),即PDU=MODBUS功能码+数据域。在某些特定总线或网络上,MODBUS协议能够映射在应用数据单元(ADU)上,即ADU=地址域+PDU+校验码,其通用帧格式如图1所示。
图1 MODBUS通用帧格式
目前MODBUS协议主要应用于以太网通信(MODBUS TCP)、串口通信(MODBUS RTU)及高速令牌传递网络(MODBUS PLUS)。在不同类别的网络中,对ADU的封装也存在差异,以MODBUS TCP/IP为例,其ADU的组成如图2所示。
图2 MODBUSTCP/IP帧格式
可以看出,在MODBUS TCP协议中,ADU=MBAP+PDU。MBAP是TCP/IP协议上使用的一种专用报文头,用以识别ADU。MBAP报文头由7个字节组成,其格式如下表1所示。
表1 MBAP报文头组成
从表格中可以看到,由于MBAP中含有长度信息,接收者能够清晰的识别报文的边界,因此在MODBUS TCP协议中,其ADU不再含有校验码。
MODBUS TCP通信系统模型一般基于客户机/服务器模型搭建,如图3所示。
图3 MODBUS TCP通信系统客户机/服务器模型
客户机/服务器模型基于4种类型的报文:请求、指示、响应和证实。客户机向服务器发送请求指令(MODBUS请求),服务器接收到来自客户机的指令(MODBUS指示)后,对该指令进行响应(MODBUS响应),即按照约定的协议内容向客户机发送数据,并由客户机对发送的数据进行辨识和处理(MODBUS证实)。
MODBUS TCP通信系统可以包括多个MODBUS客户机和服务器,其他互联设备也可通过客户机或服务器TCP/IP网关接入该通信系统,如图4所示。
图4 MODBUS TCP通信系统示意图
目前广泛使用的船用以太网通信系统多采用“一主多从”的构建思路,即由集中控制室的计算机担任主机,依次向各设备轮询数据,如图5所示。
图5 船用以太网通信系统结构示意图
采用集中式轮询方式的好处在于可以分时段向各设备发送数据请求,一来可以有效利用集控室计算机的系统资源,二来可以避免各设备同时返回数据造成通信线路堵塞。
图6 船用MODBUS TCP通信系统结构
结合图3、图4和图5可以看出,船用以太网通信系统可以按照MODBUS TCP通信系统结构进行搭建,如图6所示。
将集控室计算机作为客户机,各设备作为服务器,由集控室计算机向各设备发送轮询请求,并接收返回数据。以客户机与其中一台服务器为例,其信息交换示意图如图7所示。
图中,socket()函数用于创建套接字,bind()函数用来绑定一个端口号到该套接字,并在套接字与所指定的端口号之间建立一个连接。socket初始化完成后,服务器端需要使用listen()函数将状态置为侦听,才能够接收到来自客户机的连接请求。此时,若客户机需要与服务器进行数据交换,则需要使用connect()函数来指定套接字号、服务器IP地址和端口号,服务器在接收到客户机的连接请求后,需要使用accept()函数指定之前在listen()函数中所指定的套接字号,用以确定当前访问的客户机。在连接完成后,客户机可以使用send()函数向服务器发送MODBUS请求,服务器需要使用recv()函数进行接收,再使用send()函数向客户机发送MODBUS响应。值得注意的是,客户机在发送一个MODBUS请求后,无需等待服务器端的响应便可以继续发送下一个MODBUS请求。
图7 MODBUS TCP通信系统信息交换示意图
MODBUS服务器端的主要处理流程如图8所示。
程序在初始化完成后即进入等待,在接收到来自客户机的请求PDU后,对该PDU进行检验,根据检验情况决定生成MODBUS应答或是MODBUS异常,并将该应答或者异常作为响应发送给客户机,其详细设计分述如下:
图8 MODBUS服务器端信息处理流程图
1)初始化
与其他基于TCP/IP协议的设备类似,作为服务器端程序,MODBUS服务器端首先需要进行初始化,其核心内容是设置并绑定自身IP。建立服务器函数CreateServer()的核心代码如下:
接下来需要将服务器置于侦听状态。MODBUS服务器端应支持多个并发的客户机同时连接。在设计时,采用多线程策略可以实现该项功能,即每当侦听到新的连接请求时,便建立一个新的线程来进行操作。侦听函数TcpListen()的核心代码如下:
2)生成MODBUS应答/异常
对于并发的连接,在接收到来自客户机的请求时,服务器端将在对应的线程内对请求进行处理。根据MODBUS协议的MBAP报文头判断请求类别,再按照约定的协议内容向客户机返回数据。响应函数ClientService()的核心代码如下:
MODBUS客户端的主要处理流程如图9所示。
图9 MODBUS客户端信息处理流程图
程序在初始化完成后即进入等待,根据需求发送请求PDU,同时监测是否收到响应PDU,根据检验情况决定生成MODBUS肯定证实或是MODBUS否定证实,并将该证实发送给用户应用,其详细设计分述如下:
1)初始化
MODBUS客户端初始化的主要内容是建立客户机与服务器端的连接。使用Socket类中的Connect函数可以完成这一目标。连接函数TcpConnect()的核心代码如下:
2)发送MODBUS请求
可采用多种策略发送MODBUS请求,最为常用的是使用timer定时器作为触发,定时发送。发送函数timersend_Tick()的核心代码如下:
3)处理数据并生成肯定/否定证实
与服务器端的处理方式类似,接收函数根据MODBUS协议的MBAP报文头判断数据类别,再按照约定的协议内容解析数据。接收函数ReceiveMsg()的核心代码如下:
根据第二章的内容,采用C#编写MODBUS服务器端测试程序,使用0x03功能码进行测试,起始地址为40101,大端模式。其主界面如图10所示。
测试时使用TCP/UDP调试工具模拟MODBUS客户端。运行MODBUS服务器端测试程序,单击程序中的“开启服务器”按钮,并在TCP/UDP调试工具中设置本机IP为192.168.163.1,端口为9000,连接类型为TCP,单击“连接”按钮。此时调试工具已与本机连接。按照MODBUS协议,其MODBUS请求格式及数值如表2所示。
图10 MODBUS服务器端测试程序
单击TCP/UDP调试工具中“发送”按钮,可在接收栏中看到数据序列如图11所示。
将该数据序列进行解析,如表3所示。
可见调试工具接收到的报文信息完整、正确,通信正常。
表2 MODBUS请求格式及数值
根据第二章的内容,采用C#编写MODBUS客户端测试程序,使用0x03功能码进行测试,起始地址为40101,大端模式,采用定时器触发方式向服务器发送MODBUS请求。使用Modbus Slave调试工具模拟MODBUS服务器端,设置如图12所示。
图11 TCP/UDP调试工具结果
表3 调试结果解析
图12 Modbus Slave调试工具设置
运行MODBUS客户端测试程序,单击“连接服务器”按钮,得到的结果如图13所示。
图13 MODBUS客户端测试程序结果
对比图12和图13可以看出,客户端收到服务器端数据,且数据完整、正确,通信正常。
本文结合MODBUS TCP通信系统与船用以太网通信系统的结构特征,设计了基于MODBUS TCP协议的船用以太网通信系统,采用C#开发环境对通信系统的服务器端和客户端进行了编程设计并进行了通信测试。测试结果表明,该编程设计正确,能够有效进行数据交互。
参考文献:
[1] 张小川.Modbus设备嵌入式网页控制方法的研究与实现[J].科技风,2014,(20):26-27.
[2] 黄波.虚拟仪器技术在电力谐波分析系统中的应用[D].华中科技大学,2014.
[3] 史妍.基于Modbus的人防工程能源监控系统研究[D].哈尔滨工业大学,2012.
[4] 张芳.网络控制系统时延分析、控制器设计及仿真研究[D].北京交通大学,2007.
[5] 郝晓弘,祖守圆,徐维涛.基于VC的Modbus/TCP协议模型通信测试软件的实现[J].微计算机信息,2006,(07):64-67.