开放型 MODBUSTCP规范(中文版)2

2007年11月22日 14:10:00
导读:
  5.3 等级2指令详述
  5.3.1 强制多点线圈 (FC 15)
  
  请求
  
  Byte 0: FC = 0F (16进制)
  Byte 1-2: 参考数值
  Byte 3-4: 比特数 (1-800)
  Byte 5: 字节数 (B = (比特数 + 7)/8)
  Byte 6-(B+5): 写入的数据 (最小意义位 = 第一个线圈)
  
  响应
  
  Byte 0: FC = 0F (16进制)
  Byte 1-2: 参考数值
  Byte 3-4: 比特数
  
  异常
  
  Byte 0: FC = 8F (16进制)
  Byte 1: 异常代码 = 01 or 02
  
  示例
  
  当参考值为0(在Modicon 984中为00001)时给3线圈写入值0,0,1
  
  0F 00 00 00 03 01 04 => 0F 00 00 00 03
  
  注意到返回的数据的格式和big-endian 体系结构不同。而且此请求如果调用乘法指令字且这些指令不以16位为界排列,那么该请求将在从站得到计算强化。
  
  5.3.2 读一般参考值 (FC 20)
  
  请求
  
  Byte 0: FC = 14 (16进制)
  Byte 1: 请求余项的字节数 (=7 x 组数)
  Byte 2: 第一组的参考值类型 = 适合于 6xxxx 扩展寄存外存储器的06
  Byte 3-6: 第一组的参考数值
  = 适于 6xxxx 外存储器的存储器偏移量
  = 适于 4xxxx 寄存器的32位参考数值
  Byte 7-8: 第一组的指令
  Bytes 9-15: (至于2-8字节,适于第二组)
  . . .
  
  响应
  
  Byte 0: FC = 14 (16进制)
  Byte 1: 响应的全部字节数
  (=组数+ 组的总的字节数)
  Byte 2: 第一组的字节数 (B1=1 + (2 x 指令数))
  Byte 3: 第一组的参考类型
  Byte 4-(B1+2): 第一组的寄存器值
  Byte (B1+3): 第二组的字节数 (B2=1 + (2 x 指令数))
  Byte (B1+4): 第二组的参考类型
  Byte (B1+5)-(B1+B2+2): 第二组的寄存器值
  . . .
  
  异常
  
  Byte 0: FC = 94 (16进制)
  Byte 1: 异常代码 = 01 或 02或03或04
  
  示例
  
  参考值为1时读1扩展寄存器: 2 (在 Modicon 984中外存储器1偏移量2)得到 16进制值1234
  
  14 07 06 00 01 00 02 00 01 => 14 04 03 06 12 34
  
  (将来)
  
  参考值0时读1寄存器返回16进制值1234,参考值5时读2寄存器返回16进制值5678和9abc。
  
  14 0E 04 00 00 00 00 00 01 04 00 00 00 05 00 02 => 14 0A 03 04 12 34 05 04 56 78 9A BC
  
  注意传输尺寸限制很难用数学公式精确定义。概括说来,由于缓冲的大小的限制以及考虑到每个请求和响应数据帧的总长度请求和响应的消息尺寸均限于256个字节。如果从站由于响应太大而拒绝发送此消息将产生异常类型04。
  
  5.3.3 写一般参考值(FC 21)
  
  请求
  
  Byte 0: FC = 15 (16进制)
  Byte 1: 请求余额的字节数
  Byte 2: 第一组的参考值类型= 6xxxx 扩展寄存器存储器的06
  Byte 3-6: 第一组的参考数值
  = 适于 6xxxx 外存储器的存储器偏移量
  = 用于 4xxxx 寄存器的32 位的参考数值
  Byte 7-8: 第一组的指令数 (W1)
  Byte 9-(8 + 2 x W1): 第一组的寄存器数据
  
  (从字节2开始为其它组复制组的数据帧)
  . . .
  
  响应
  
  响应是对询问的直接回应
  
  Byte 0: FC = 15 (16进制)
  Byte 1: 请求余额的字节数
  Byte 2: 第一组的参考值类型 = 6xxxx 扩展寄存器存储器的06
  Byte 3-6: 第一组的参考数值
  = 6xxxx 外存储器的存储器偏移量
  =用于 4xxxx 寄存器的32 位的参考数值
  Byte 7-8: 第一组的指令数 (W1)
  Byte 9-(8 + 2 x W1): 第一组的寄存器数据
  
  (从字节2开始为其它组复制组的数据帧)
  . . .
  
  异常
  
  Byte 0: FC = 95 (16进制)
  Byte 1: 异常代码= 01 或 02或03或04
  
  示例
  
  参考值为1时写1扩展寄存器: 2 (在 Modicon 984中外存储器1偏移量2)得到 16进制值1234
  
  15 09 06 00 01 00 02 00 01 12 34 => 15 09 06 00 01 00 02 00 01 12 34
  
  (将来)
  
  参考值0时写1寄存器返回16进制值1234,参考值5时写2寄存器返回16进制值5678和9abc。
  
  15 14 04 00 00 00 00 00 01 12 34 04 00 00 00 05 00 02 56 78 9A BC
  e 15 14 04 00 00 00 00 00 01 12 34 04 00 00 00 05 00 02 56 78 9A BC
  
  注意传输尺寸限制很难用数学公式精确定义。概括说来,由于缓冲的大小的限制以及考虑到每个请求和响应数据帧的总长度请求和响应的消息尺寸均限于256个字节。如果从站由于响应太大而拒绝发送此消息将产生异常类型04。
  
  5.3.4 掩膜写寄存器 (FC 22)
  
  请求
  
  Byte 0: FC = 16 (16进制)
  Byte 1-2: 参考数值
  Byte 3-4: AND掩膜用于寄存器
  Byte 5-6: OR 掩膜用于寄存器
  
  响应
  
  Byte 0: FC = 16 (16进制)
  Byte 1-2: 参考数值
  Byte 3-4: AND 掩膜用于寄存器
  Byte 5-6: OR 掩膜用于寄存器
  
  异常
  
  Byte 0: FC = 96 (16进制)
  Byte 1: 异常代码 = 01 或 02
  
  示例
  
  在参考值为0(Modicon 984中为40001)时将寄存器的0-3位字段改为16进制值4
  (AND 用 000F, OR用 0004)
  
  16 00 00 00 0F 00 04 => 16 00 00 00 0F 00 04
  5.3.5 读/写寄存器 (FC 23)
  
  请求
  
  Byte 0: FC = 17 (16进制)
  Byte 1-2: 用于读的参考数值
  Byte 3-4: 用于读的指令数 (1-125)
  Byte 5-6: 用于写的参考数值
  Byte 7-8: 用于写的指令数 (1-100)
  Byte 9: 字节数 (B = 2 x 用于写的指令数)
  Byte 10-(B+9): 寄存器值
  
  响应
  
  Byte 0: FC = 17 (16进制)
  Byte 1: 字节数Byte count(B = 2 x 用于读的指令数)
  Byte 2-(B+1) 寄存器值
  
  异常
  
  Byte 0: FC = 97 (16进制)
  Byte 1: 异常代码 = 01 或 02
  
  示例
  
  参考值为3(在Modicon 984中为40004)时写入1寄存器16进制值0123,参考值为0时读2寄存器返回值0004和5678(16进制)
  
  17 00 00 00 02 00 03 00 01 02 01 23 => 17 04 00 04 56 78
  
  注意如果寄存器交替的进行读写操作,结果是不明确的。一部分设备先写后读,另部分则先读后写。
  5.3.6读FIFO队列 (FC 24)
  
  请求
  
  Byte 0: FC = 18 (16进制)
  Byte 1-2: 参考数值
  
  响应
  
  Byte 0: FC = 18 (16进制)
  Byte 1-2: 字节数 (B = 2 + 指令数) (最大64)
  Byte 3-4: 指令数 (FIFO中累积的指令数) (最大 31)
  Byte 5-(B+2): 从 FIFO前开始的寄存器数据
  
  异常
  
  Byte 0: FC = 98 (16进制)
  Byte 1: 异常代码 = 01 或02或 03
  
  示例
  
  读从参考值0005 (Modicon 984中为40006)开始的FIFO区段内容,其中包括2指令的值1234和5678(16进制)
  
  18 00 05 => 18 00 06 00 02 12 34 56 78
  
  注意到执行在984上的该功能在通用性方面非常有限-假定寄存器的该区段包括含有从0到31值的计数器,后面还跟着最大到31指令字的数据。当该功能完成,该计数器指令字不会象经过FIFO操作所期望的回复为0。
  
  一般说来,这可被看作函数16-读乘法寄存器的有限子集,既然后者可用来完成所必须的功能性。
  
  6. 异常代码
  
  在出问题的时候,有一系列定义过的异常代码被从站送回。注意到主站会“投机地”发送指令,利用接收到的成功或异常代码来确定支配设备的哪一个Modbus愿意响应以及从站不同可用数据区的大小。
  
  所有的异常通过添加0x80 到请求的功能代码来标记,跟随此字节的是一个单一的原因字节如下例所示:
  
  03 12 34 00 01 => 83 02
  
  当索引0x1234响应异常类型2-“非法的数据地址”时请求读1寄存器
  
  异常情况列举如下:
  
  01 非法的功能
  
  对从站来说,在询问过程中收到的功能代码是不允许的行为。这可能是由于功能代码只适用于新近的控制器,而不能在所选的单元使用。也可推断出从站处于错误的状态而发出这样的一种请求,例如未经配置而被要求返回寄存器值。
  
  02 非法的数据地址
  
  对从站来说,在询问过程中收到的数据地址不是允许的地址。更明确一点,参考数值和传输长度的结合是无效的。对于一个有100个寄存器的控制器来说,具有偏移96和长度4的请求将能成功,而具有偏移96和长度5的请求将产生异常02。
  
  03 非法的数据值
  
  对从站来说,在询问数据区段所包含的值是不允许的。这推断出在复杂请求余额的结构中的一个错误,例如隐含长度是不正确的。既然MODBUS协议不了解一些特殊寄存器的特殊值的意义,因此这并不意味着寄存器中被提交用于存储的数据对象有一个应用程序期望值之外的值,
  
  04非法的响应长度
  
  指出加外框的请求将产生一个尺寸超出可用MODBUS数据尺寸的响应。仅用于由功能所产生的多部分响应,如功能20和21。
  
  05 确认
  
  专用于关联程序设计指令。
  
  06 从站设备忙
  
  专用于关联程序设计指令。
  
  07 否认
  
  专用于关联程序设计指令。
  
  08 存储器奇偶校验错误
  
  专用于关联功能代码20和21,指出扩展文件区没通过一致性检验。
  
  0A 网关通路不可用
  
  专用于关联Modbus Plus 网关, 指出网关未能分配Modbus Plus 路径以处理请求。通常意味着网关配置错误。
  
  0B 网关目标设备响应失败
  
  专用于关联Modbus Plus网关, 指出从目标设备未能获得响应。通常意味着设备没有连接到网络上。
  
  附录
  A. 客户机和服务器应用指南
  
  本部分的注释不应当作与客户机和服务器的任何特殊的应用捆绑起来。但是,当应用多厂商系统和网关去安装MODBUS设备,遵从这些内容将大大减小综合的“疑难”。
  
  
  下面的软件结构假设在熟悉BSD Sockets 服务器接口基础上, 正如用于UNIX and Windows NT。
  
  A.1客户机设计
  
  MODBUS/TCP 的设计使客户机的设计尽可能简化。软件的例子在别处有,但是处理事务的基本过程如下所给:
  
  使用CONNECT()建立到所需服务器端口502的连接。
  
  准备一个MODBUS请求,用前面介绍的方法编码。
  
  提交MODBUS请求,包括其6字节的MODBUS/TCP前缀,作为单一的缓冲用SEND()传输。
  
  在同一TCP连接上等待响应出现。如果希望所考虑的通讯比TCP正常报告的快,用选择()在这一步随意的运行超时指令。
  
  用RECV()读取响应的前6个字节,它将指出响应消息的实际长度。
  
  用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- 有符号整数
  
  正常 ...
原文地址:https://www.cnblogs.com/feisky/p/1586617.html