MODBUS TCP/IP(三)中文版-(完)

   
A. 客户机和服务器应用指南
 
本部分的注释不应当作与客户机和服务器的任何特殊的应用捆绑起来。但是,当应用多厂商系统和网关去安装MODBUS设备,遵从这些内容将大大减小综合的“疑难”。
     下面的软件结构假设在熟悉BSD Sockets 服务器接口基础上, 正如用于UNIX and Windows NT。
                              
A.1 客户机设计
                               
   ODBUS/TCP的设计使客户机的设计尽可能简化。软件的例子在别处有,但是处理事务的基本过程如下所给:
u     使用CONNECT()建立到所需服务器端口502的连接。
u     准备一个MODBUS请求,用前面介绍的方法编码。
u     提交MODBUS请求,包括其6字节的MODBUS/TCP前缀,作为单一的缓冲用SEND()传输。
u     在同一TCP连接上等待响应出现。如果希望所考虑的通讯比TCP正常报告的快,用选择()在这一步随意的运行超时指令。
u     用RECV()读取响应的前6个字节,它将指出响应消息的实际长度。
u     用RECV()读取响应的剩余字节。
    如果接下来没有可能的连接到这个特别的目标,就关闭TCP连接以使服务器的资源可以在间歇期为其它客户机服务。允许向客户机开放连接的最大时间是1秒。
在超时等待响应的事件中,发布单方面关闭连接指令,打开新的一个连接,重新提交请求。此技术允许客户机控制适时重试,这优于TCP默认(设置)所能提供的功能。它也允许可靠备用策略,例如在基干网失效时,用一个总体上独立的通讯网络提交请求给一个备用的IP地址。
 
 
A.2 服务器设计
                              
    MODBUS/TCP服务器应设计的可以支持多个并发的客户机,甚至在计划内用户只有单一客户时也要能响应(并发)。这就允许客户机高速的顺序关闭和重开连接以对无发送的响应作出快速反应。
    如果使用了传统的TCP协议组,减小接收和发送缓冲区的尺寸可以节省内存资源。一个采用UNIX或NT的TCP服务器通常分配每个连接8K字节或更多的接收缓存以鼓励从如文件服务器等设备“流畅的”传送数据。这样的缓冲器空间在MODBUS/TCP中没有价值,因为请求和发送的最大尺寸小于300字节。通常为附加的连接资源交换存储空间是可行的。
或者多线程或者单线程的模型能用于处理多个连接。在后续章节叙述。
 
A.2.1 多线程服务器
                              
    操作系统或鼓励多线程应用的语言,如JAVA,能用多线程策略,叙述如下:
                              
    用LISTEN()等待引入到端口502的TCP连接。
    当收到新的连接请求时,用ACCEPT()接受它并产生新的线程来进行连接操作
    在新的线程期间,无限循环的做以下工作:
    为6字节的MODBUS/TCP头部发布一个RECV(6)请求。不要在此设置超时,而要等待直到一个请求到达或是连接关闭。两种情况都能自动激起线程。
    分析这头部。如果频繁出现,如协议字段非0或消息长度超过256字节,那么单方面关闭连接。这是服务器对隐含TCP编码出错的情况的正常反应。
    为消息剩下的已知长度的字节发布一个RECV()。特别注意发布一个带有这样长度限制的RECV()将允许坚持“流水线操作”请求的客户机。任何这样的流水线操作请求将保留在服务器或是客户端的TCP缓冲区,并在当前的的请求得到完全服务后选取。
    现在处理引入的MODBUS消息,如果必要,挂起当前的线程直到正确的响应计算出来。最终,你或者拥有了一个有效的MODBUS消息,或者作为响应的异常消息。
                              
    为响应产生MODBUS/TCP前缀,从请求的字节0和1复制“事件标识符”字段,并重新计算长度字段。
    提交包括MODBUS/TCP前缀的响应,当作连接上的单一传送缓冲器,用SEND()。
    Go back and wait for the next 6 byte prefix record.
                              
    最后,当客户端选择关闭连接,6字节前缀的RECV()将失效。有序的关闭通常会使RECV()字节数回0。强制关闭可能会产生从RECV()返回的错误。在任一情形下,关闭连接并取消当前的线程。
                              
A.2.2 单线程服务器
                               
    一些嵌入式的系统和较老的操作系统如UNIX和MS-DOS鼓励多连接的处理,采用“SELECT”访套接字界面。在这样的系统中,不是在它们的线程处理各自并发的请求,而是在一个普通的处理器上作为多态计算机来处理请求。
                              
其结构如下:
将其状态设为“空闲”来初始化多态计算机。
LISTEN()用于引入的到端口502的TCP连接
 
现在,开始无限循环检查“LISTEN”端口和多态计算机如下:
                               
              在收取端口,如果收到一个新的连接请求,用ACCEPT()接收它并且促使其中一个多态计算机从“空闲”转入“新的请求”状态以处理引入的连接。
                              
对每一多态计算机
如果状态是“新的请求”:用SELECT()来看请求是否到达通常设超时为0,既然由于该特殊连接处于休止状态,你不愿意挂起该事务。
    如果SELECT()表明有组出现,象在多线程案例中一样用RECV(6)读取头部。如果头部出错,关闭连接并设多态计算机为空闲。
    如果读取成功且SELECT()表明更多的输入可用,读取余下的请求。
    如果请求是完整的,改变话路状态为“等待响应”。
    如果RECV()返回值表明连接不在使用中,关闭连接并重置多态计算机为“空闲”。
    如果状态是“等待响应”看如果申请响应信息可用,建立响应分组,并用SEND()发送,严格类似于多线程的情况。设状态为“新的请求”。
通过在每循环基础上把多个SELECT()调用结合为一个单一的调用来优化性能而不影响应用程序的函数结构是可能的。
 
A.3 必须的及期望的性能
                              
    这儿没有处理MODBUS或MODBUS/TCP事务所必须的响应时间的规范。
    这是因为MODBUS/TCP被希望用于尽可能最宽的各种通讯情况,从亚毫秒的时延的I/O扫描设备到几秒时延的长距离无线连接。
    此外,MODBUS家族设计用于支持网络间的自动转换,通过“非智能性的”转换网关。这样的设备包括Schneider公司的“ Modbus +网桥以太网”,以及从MODBUS/TCP到MODBUS串行连接的各类设备。这些设备的使用意味着当前MODBUS设备的性能和MODBUS/TCP的使用是一致的。
    一般来说,象PLC’s 这样的设备所展示的“扫描”行为将在一个扫描周期内对引入的请求作出反应, 20该周期将在20毫秒和200毫秒之间变化。
    从客户机的观点,时间必须按照通过网络的预期的传输时延来延长,以确定一个“合理的”响应时间。这个时延对于交换以太网可能是几毫秒,对广域网连接是几百毫秒。
    依次,客户机所用的用来发起新的申请重试的“超时”的时间都应大于预期最大的“合理的”响应时间。否则,将可能导致网络及终端设备的过度拥塞,从而导致更大的错误。这是必须避免的情况。
    因此实际上,用于高性能应用中的客户机超时设定总是有些依赖网络拓扑和客户机的性能。
    通过局域以太网扫描10个I/O设备,将超时设定为30毫秒是合理的,每个设备再1毫秒后响应。另一方面,当通过网关及串行连接管理慢速的PLC’s
    使用1秒的超时设定值可能更合适,这儿正常的扫描序列在300毫秒内完成。
    非时间临近的应用系统经常将超时设定值置为正常的TCP默许值,在主平台几秒钟后报告通讯失败。
客户机被鼓励关闭和重建仅用于数据访问(非PLC程序设计)的MODBUS/TCP连接,而且此处的预期时间在下次使用之前是有意义的,比方说超过1秒。如果客户机遵从这一原则,具有有限连接资源的服务器将能为大批客户机提供服务,也有利于错误校正策略如可选目标IP地址的挑选。应该记得,关闭和重开连接所造成的的额外通讯和CPU负荷比得上单个Modbus事务所造成的。
 
B. 非指令数据的编码
                              
    在MODBUS上传送大批量信息的最有效办法是采用功能代码3(读寄存器),16(写寄存器),或可能的23(读/写寄存器)。
    虽然这些功能根据它们在16位寄存器上的操作来定义,它们能够将任何类型的信息从一台设备转到另一台,只要这些信息能用接近16位指令的区段来描述。
    早期的MODBUS-capable PLC’s专用于使用“big-endian”体系结构的计算机。大多数现代的PLC’s基于采用“little-endian”体系结构的商用微处理器。MODBUS潜在的被用于在这两种体系之间交换数据这一事实引入一些会迷惑粗心者的微妙之处。
    几乎所有不同于原始“离散比特”和“16位寄存器值”的数据类型在引入little-endian微处理器后被提出来。因此MODBUS上数据类型的表示法遵从了little-endian 模式,含义
                              
第一个寄存器比特 15 - 0 = 数据对象比特 15 - 0
第二个寄存器比特15 - 0 =  数据对象比特 31 - 16
第三个寄存器比特 15 - 0 = 数据对象比特 47 - 32
等等
 
B.1 指令字中的比特数
                               
     Modicon PLC’s 在984 Ladder Language中有预先确定的功能,它将一系列临近的寄存器值转换为相等长度的1-比特“离散”的块。最常用的功能是BLKM (块移动)。
                              
    由于与最初的big-endian体系结构保持一致,该离散值从最大有效位开始编号会带来混乱,所有的编号序列从1开始,而非从0。(本手册中的比特编号总是从作为最小意义位的0开始,以与现代的软件文件保持一致。)
                              
这样一个指令字 (寄存器值)中
离散 1将是 bit 15 (值 0x8000)
离散2 将是 bit 14 (值0x4000)
离散3 将是 bit 13 (值0x2000)
离散4 将是 bit 12值0x1000)
离散5 将是 bit 11 (值0x0800)
离散6 将是 bit 10 (值0x0400)
离散7 将是 bit 9 (值0x0200)
离散8  将是 bit 8 (值 0x0100)
离散 9  将是  bit 7 (值0x0080)
离散10 将是 bit 6 (值0x0040)
离散11 将是 bit 5 (值0x0020)
离散12 将是 bit 4 (值0x0010)
离散13 将是 bit 3 (值0x0008)
离散14 将是 bit 2 (值0x0004)
离散15 将是 bit 1 (值0x0002)
离散16 将是 bit 0 (值0x0001)
 
    当多于16比特时,例如一个32点的离散输入模数,离散1到16将在第一寄存器,离散17到32将在第二寄存器。
    这个编码的约定对于理解在MODBUS/TCP上何时处理离散输入和输出设备,什么地方离散编码和Modicon PLC’s相一致特别重要。
    特别的,注意到指令字中的比特的IEC-1131编码约定是从0(最小意义位)到15(最大意义位),这与离散编码是相反的。
                              
                              B.2 多指令字变量
                              
    原则上,任何能被“投”到16位指令字序列的数据结构都可被传输,并且以同样的数据格式到达设备。
    以下的 PLC数据类型应该注意
B.2.1 984 数据类型
 
984 16-位 无符号整数
正常含义: 整数的位 15 - 0 = 寄存器的位 15 - 0
 
984 16-位 有符号整数
正常含义: 整数的位 15 - 0 = 寄存器的位 15 - 0
 
984 ASCII
尽管 PLC’s 没有这样的电文处理能力,最初的ladder language的编者允许用2个ASCII字符来表示寄存器。第一个字符表示上半字节(比特15-8),第二个字符表示下半字节(比特7-0)。特别注意这与现代PLC’s所用的高级语言如C等的使用是相反的。
                              
984浮点数
Intel 单精度实数
    第一寄存器包含32-位数的15-0位(有效位的15-0位)
    第二寄存器包含32-位数的31-16位(说明部分和有效位的23-16)
                              
984 单精度十进制无符号数
尽管值的范围局限于0-9999,数据表示和16位无符号整数相同。
 
984 双精度十进制无符号数
这个数据格式现在很少用,除了旧格式的4位十进制表示。
值的范围从0到99999999。第一个寄存器包含了最有意义的4位,第二寄存器包含了最无意义的4位,每个用0-9999范围内的二进制值表示。
                              
B.2.2 IEC-1131 数据类型
所有的 IEC-1131 数据类型在Modicon PLC’s以little-endian的形式来表示。例子如下
BYTE  8-位数。
寄存器的7-0位 = BYTE 的 7 - 0 位
DINT  32-位数。
第一寄存器的15-0位 = DINT 的 15 - 0 位
第二寄存器的15-0位 = DINT 的 31-16 位
INT
寄存器的15-0位 = INT 的 15 - 0 位
REAL  32-位 Intel 单精度实数。
第一寄存器的15-0位 = REAL 的 15 - 0 位 (有效位的15-0位)
第二寄存器的15-0位 = REAL 的 31-16 位(说明及有效位的23-16位)
UDINT  32-位数。
第一寄存器的15-0位 = UDINT 的 15 - 0 位
第二寄存器的15-0位 = UDINT 的 31-16 位
UINT
寄存器的15-0位 = UINT 的 15 - 0 位
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值