简介

  Modbus 是由美国MODICON公司于1979年开发,是一种工业现场总线协议标准。1997年施耐德公司推出给予以太网TCP/IP的modbus协议————ModbusTCP.

ModubsTCP数据帧

  ModbusTCP的数据帧可以分为两部分:MBAP + PDU.
  (Modbus Application Protocol——报文头)
  (Protocol Data Unit——协议数据单元)

特别说明:在ModbusTCP中,由从站作服务端,主站作客户端,保证主动权在主站手中

报文头MBAP

  MBAP为报文头,长度为7字节,组成如下:


  事物处理标识:可以理解为报文的序列号,一般每次通信之后就要加1以区别不同的通信数据报文。
  协议标识符 :00 00 表示ModbusTCP协议。
  长度:表示接下来的数据长度,单位为字节。
  单元标识符:可以理解为设备地址。
  其中以上四项中,对 长度 做额外举例如下:
    00 01 00 00 00 06 01 03 00 00 00 03
  上面是一条读取保持寄存器的指令,划横线部份是MBAP。红色字体为长度数据,表示从当前之后的数据总长度。
(注:并不是指PDU的数据长度)

帧结构PDU

  PUD由 功能码 + 数据 组成。功能码为1字节,数据长度不定,由具体功能决定。

功能码

  modbus的操作对象有四种:线圈、离散输入、输入寄存器、保持寄存器。

  • 线圈:PLC的输出位,开关量,在modbus中可读可写。(可以理解为可读可惜的bit)
  • 离散量:PCL的输入为,开关量,在modbus中只读。(可以理解为只读的bit)
  • 输入寄存器:PLC中只能从模拟量输入端改变的寄存器,在modbus中只读。(可以理解为只读寄存器,一个寄存器占用2个字节)
  • 保持寄存器:PLC中用于输出模拟量信号的寄存器,在modbus中可读可写。(可以理解为可读写寄存器,一个寄存器占用2个字节)

根据操作对象/操作内容不同,modbus功能码分为以下几种:

  • 0x01:读线圈
  • 0x05:写单个线圈
  • 0x0F:写多个线圈
  • 0x02:读离散量
  • 0x04:读输入寄存器
  • 0x03:读保持寄存器
  • 0x06:写单个保持寄存器
  • 0x10:写多个保持寄存器

PDU详细结构

(根据不同功能码,PDU的结构有所变化)
0x01:读线圈
在从站中读取1~8个连续线圈状态,其中ON=1,OFF=0

  • 请求数据:MBAP + 功能码 + 起始地址H(高8位) + 起始地址L(低8位) + 数量H(高8位) + 数量L(低8位)

  • 如: 在从站0x01中,读取开始地址为0x0001的线圈数据,读0x0008位
        00 01 00 00 00 06 01 01 00 01 00 08

    ​ (事务处理标识) (协议标识) (长度)(设备标识)(功能码) (起始地址) (读取数量)

  • 响应数据:MBAP + 功能码 + 数据长度 + 数据

  • 如: 数据长度为0x01字节(8位),数据值为0x03,第一个和第二个线圈为ON,其余为OFF
      00 01 00 00 00 04 01 01 03

    (事务处理标识) (协议标识) (长度)(设备标识)(数据长度) (数据值)

0x05:写单个线圈
将从站中的一个输出写成ON或OFF,0xFF00表示将目标位写为ON,0x0000表示将目标位写为OFF

  • 请求数据:MBAP + 功能码 + 目标地址H(高8位) + 目标地址L(低8位) + 数据值H(高8位) + 数据值L(低8位)
  • 如: 在从站0x01中,将地址为0x0001的线圈数据设置为ON
      00 01 00 00 00 06 01 05 00 01 FF 00
  • 响应数据:MBAP + 功能码 + 目标地址H(高8位) + 目标地址L(低8位) + 数据值H(高8位) + 数据值L(低8位)
  • 如: 写入成功
      00 01 00 00 00 06 01 05 00 01 FF 00

0x0F:写多个线圈
将一个从站中的一个线圈序列的每个线圈都强制为ON或OFF,数据域中置1的位请求相应输出位ON,置0的位请求响应输出为OFF

  • 请求数据:MBAP + 功能码 + 起始地址H(高8位) + 起始地址L(低8位) + 写数量H(高8位) + 写数量L(低8位) + 输出值H(高8位) + 输出值L(低8位)
  • 如: 在从站0x01中,将地址为0x0001~0X008的线圈数据设置为ON
      00 01 00 00 00 08 01 0F 00 01 00 08 00 FF
  • 响应数据:MBAP + 功能码 + 起始地址H(高8位) + 起始地址L(低8位) + 写数量H(高8位) + 写数量L(低8位)
  • 如: 写入成功
      00 01 00 00 00 06 01 0F 00 01 00 08

0x02:读离散量输入
从一个从站中读1~15个连续的离散量输入状态

  • 请求数据:MBAP + 功能码 + 起始地址H(高8位) + 起始地址L(低8位) + 读数量H(高8位) + 读数量L(低8位)
  • 如: 从地址0x0001开始读15个离散量输入
      00 01 00 00 00 06 01 02 00 01 00 0F
  • 响应数据:MBAP + 功能码 + 数据长度 + 数据
  • 如: 读取成功,数据长度为0x02, 数据为0x05 0x01 ,表示第1个、第9个、第11个离散量的值为ON,其余为OFF
      00 01 00 00 00 05 01 02 02 05 01

0x04:读输入寄存器
从一个远程设备中读1~5个连续输入寄存器

  • 请求数据:MBAP + 功能码 + 起始地址H(高8位) + 起始地址L(低8位) + 寄存器数量H(高8位) + 寄存器数量L(低8位)
  • 如: 从地址0x0001开始读5个输入寄存器
      00 01 00 00 00 06 01 04 00 01 00 05
  • 响应数据:MBAP + 功能码 + 数据长度 + 寄存器数据
  • 如: 读取成功,数据长度为0x0A, 第1个数据为0x00A0, 第2个数据为0xFF00 第3个数据为0x4C4C 第4个数据为0x0000 第5个数据为0xAAAA
      00 01 00 00 00 0D 01 04 0A 00 A0 FF 00 4C 4C 00 00 AA AA

0x03:读保持寄存器
从一个远程设备中读1~3个连续保持寄存器

  • 请求数据:MBAP + 功能码 + 起始地址H(高8位) + 起始地址L(低8位) + 寄存器数量H(高8位) + 寄存器数量L(低8位)
  • 如: 从地址0x0001开始读5个输入寄存器
      00 01 00 00 00 06 01 03 00 01 00 03
  • 响应数据:MBAP + 功能码 + 数据长度 + 寄存器数据
  • 如: 读取成功,数据长度为0x06, 第1个数据为0x00A0, 第2个数据为0x0000 第3个数据为0xAAAA
      00 01 00 00 00 09 01 03 06 00 A0 00 00 AA AA

0x06:写单个保持寄存器
在一个远程设备中写1个保持寄存器

  • 请求数据:MBAP + 功能码 + 寄存器地址H(高8位) + 寄存器地址L(低8位) + 寄存器值H(高8位) + 寄存器值L(低8位)
  • 如: 在地址0x0001写入0x00FF
      00 01 00 00 00 06 01 06 00 01 00 FF
  • 响应数据:MBAP + 功能码 + 寄存器地址H(高8位) + 寄存器地址L(低8位) + 寄存器值H(高8位) + 寄存器值L(低8位)
  • 如: 写入成功
      00 01 00 00 00 06 01 06 00 01 00 FF

0x10:写多个保持寄存器
在一个远程设备中写连续3个保持寄存器

  • 请求数据:MBAP + 功能码 + 寄存器起始地址H(高8位) + 寄存器起始地址H(低8位) + 寄存器数量H(高8位) + 寄存器数量L(低8位) + 字节长度 + 寄存器值
  • 如: 从地址0x0001开始写入3个保持寄存器值,0x00FF,0xFF00, 0xF0F0
      00 01 00 00 00 0D 01 10 00 01 00 03 06 00 FF FF 00 F0 F0
  • 响应数据:MBAP + 功能码 + 寄存器起始地址H(高8位) + 寄存器起始地址H(低8位) + 寄存器数量H(高8位) + 寄存器数量L(低8位)
  • 如: 写入成功
      00 01 00 00 00 06 01 10 00 01 00 03

ModbusTCP通信

通信方式

  modbus设备可分为主站(poll)和从站(slave)。主站只有一个,从站有多个,主站向各从站发送请求帧,从站给予相应。在使用TCP通信时,主站为客户端(client),主动建立连接;从站为服务端(server),等待连接。

  • 主站请求:功能码+数据
  • 从站正常响应:请求功能码+响应数据
  • 从站异常响应:异常功能码+异常码,其中异常功能码即将请求功能码的最高有效位置1,异常码指示差错类型
  • 注意:需要超时管理机制,避免无期限的等待可能不出现的应答

异常码

异常功能码即将请求功能码的最高有效位置1

  • 01:非法功能
      对于服务器(或从站)来说,询问中接收到的功能码是不可允许的操作,可能是因为功能码仅适用于新设备而被选单元中不可实现同时,还指出服务器(或从站)在错误状态中处理这种请求,例如:它是未配置的,且要求返回寄存器值。


  • 02:非法数据地址
      对于服务器(或从站)来说,询问中接收的数据地址是不可允许的地址,特别是参考号和传输长度的组合是无效的。对于带有100个寄存器的控制器来说,偏移量96和长度4的请求会成功,而偏移量96和长度5的请求将产生异常码02。


  • 03:非法数据值
      对于服务器(或从站)来说,询问中包括的值是不可允许的值。该值指示了组合请求剩余结构中的故障。例如:隐含长度是不正确的。modbus协议不知道任何特殊寄存器的任何特殊值的重要意义,寄存器中被提交存储的数据项有一个应用程序期望之外的值。


  • 04:从站设备故障
      当服务器(或从站)正在设法执行请求的操作时,产生不可重新获得的差错。


  • 05:确认
      与编程命令一起使用,服务器(或从站)已经接受请求,并且正在处理这个请求,但是需要长持续时间进行这些操作,返回这个响应防止在客户机(或主站)中发生超时错误,客户机(或主机)可以继续发送轮询程序完成报文来确认是否完成处理。


  • 07:从属设备忙
      与编程命令一起使用,服务器(或从站)正在处理长持续时间的程序命令,当服务器(或从站)空闲时,客户机(或主站)应该稍后重新传输报文。


  • 08:存储奇偶性差错
      与功能码20和21以及参考类型6一起使用,指示扩展文件区不能通过一致性校验。服务器(或从站)设备读取记录文件,但在存储器中发现一个奇偶校验错误。客户机(或主机)可重新发送请求,但可以在服务器(或从站)设备上要求服务。


  • 0A:不可用网关路径
      与网关一起使用,指示网关不能为处理请求分配输入端口值输出端口的内部通信路径,通常意味着网关是错误配置的或过载的。


  • 0B:网关目标设备响应失败
      与网关一起使用,指示没有从目标设备中获得响应,通常意味着设备未在网络中。

参考资料:
https://wenku.baidu.com/view/c2a9e1cc376baf1ffd4fad5c.html
https://blog.csdn.net/zwxue251/article/details/24154951
https://blog.csdn.net/lakerszhy/article/details/68927178?locationNum=4&fps=1
https://blog.csdn.net/iknow_nothing/article/details/84292914
http://blog.sina.com.cn/s/blog_91a077e50101ina9.html
https://blog.csdn.net/lushoumin/article/details/89073556