Modbus通信协议是由Modicon公司开发的应用在PLC或其他工业控制器上的一种通用语言。通过此协议,各控制器之间可以实现串行通信,Modbus通信协议定义了一个控制器能识别使用的消息结构,描述了主控制器访问从站设备的过程,例如规定从站怎样做出应答响应,检查和报告传输错误等。Modbus协议的通信方式为主从方式。主站首先向从站设备发送通信请求指令,从节点根据请求指令中的功能码向主站发回回答数据。网络中的每个从站设备都必须分配给一个唯一的地址,最多可达31个从站设备。通过多达24种总线命令实现主控制器与从站设备之间的信息交换。从站设备只执行发给自己的指令,对于其它从站地址开头的报文不作应答。这种一问一答的通信模式,大大提高了通信的正确率。因其具有操作简单、高效、通信可靠等优点,Modbus协议已成为一个国际通信标准,得到了国际上大多数工控产品生产厂家的支持。该通信协议已广泛应用于机械、水利、电力、环保等行业设备中。
B.1 Modbus 协议数据格式
Modbus 协议有 ASCII(美国标准信息交换代码)和 RTU(远程终端单元)两种数据传输方式可由用户选择,但在一个 Modbus 网络上的所有设备都必须选择相同的传输模式和串口参数。其中 RTU 模式信息帧中的 8 位数据包括两个 4 位 16 进
制字符,相对于 ASCII 模式表达相同的信息只需较少的位数,在相同的速率下较ASCII 模式具有更大的数据流量。因此,在通常情况下较多使用 RTU 模式。GCAN-204 设备也采用 RTU 模式。
RTU 模式消息发送至少以 3.5 个字符间隔时间(如表 B.1 的 T1-T2-T3-T4)标志开始和结束,信息帧由地址域、功能域、数据域和 CRC 校验域构成,所有字符位由 16 进制 0-9、A-F 组成。整个消息帧必须作为一连续的流传输。如果在帧完成之前有超过 1.5 个字符时间的停顿时间,接受设备将刷新不完整的消息并假定下一个字节是一个新消息的地址域。同样的,如果一个新消息在小于 3.5 个字符时间内接着前个消息开始,接收的设备将认为它是前一消息的延续。这将导致一个错误,因为在最后的 CRC 域的值不可能是正确的。

表 B.1 RTU 消息帧格式
(1)地址域
指定报文的目的地址,包括 8bit。单个设备的地址范围是 1~247。主设备通过将要联络的从设备的地址放入消息中的地址域来选通从设备。当从设备发送回应消息时,它把自己的地址放入回应的地址域中,以便主设备知道是哪一个设备作出回应。地址 0 用作广播地址,以使所有的从设备都能认识。
(2)功能域
当消息从主设备发往从设备时,功能代码域将告之从设备需要执行哪些行为。例如去读取输入的开关状态,读一组寄存器的数据内容,读从设备的诊断状态,允许调入、记录、校验在从设备中的程序等。当从设备回应时,它使用功能代码域来指示是正常回应(无误)还是有某种错误发生(称作异议回应)。对正常回应,从设备仅回应相应的功能代码。主设备应用程序得到异议的回应后,典型的处理过程是重发消息,或者诊断发给从设备的消息并报告给操作员。
(3)数据域
数据域是由两个十六进制数集合构成的,范围 00~FF。从主设备发给从设备消息的数据域包含从机执行主机功能代码中所需的参数,如处理对象的寄存器地址,要处理项的数目,域中实际数据字节数。举例说明,如果主设备需要从设备读取一组保持寄存器(功能代码 03),数据域指定了起始寄存器以及要读的寄存器数量。如果主设备写一组从设备的寄存器(功能代码 16,即 10H),数据域则指明了要写的起始寄存器以及要写的寄存器数量,数据域的数据字节数,要写入寄存器的数据。如果没有错误发生,从设备返回的数据域包含请求的数据。如果有错误发生,此域包含一异议代码,主设备应用程序可以用来判断采取下一步行动。在某种消息中数据域可以是不存在的(0 长度)。例如,主设备要求从设备回应通信事件记录(功能代码 0B H),从设备不需任何附加的信息。
当传送一个 2 个字节的数据时,高字节(MSB)将被首先传送,然后传送低字节(LSB)。这与 DeviceNet 的传送方式刚好相反。
(4)CRC 校验域
CRC 域检测整个消息的内容,包括两个字节,包含一个 16 位的二进制值。它由传输设备计算后加入到消息中。接收设备将重新计算收到消息的 CRC,并与接收到的 CRC 域中的值进行比较。如果两值不同,则有误。CRC 添加到消息中时,低字节先加入,然后是高字节。
B.2 Modbus 常用功能码
在 Modbus 消息帧的功能码中较常使用的是 01、02、03、04、06 和 16 功能码,使用它们即可实现对从机的数字量和模拟量的读写操作。下面以在 RTU 传输模式下通讯为例,对这些功能码进行详细介绍。

下面是 2 个 Modbus 命令的主从机收发的数据包格式,其余的命令可参照其格式。
(1)功能码:03H
代码功能:读保持寄存器
说明:读从机保持寄存器的二进制数据,不支持广播。
查询:查询信息规定了要读的寄存器起始地址及寄存器的数量,寄存器寻址起始地址为 0000,寄存器 1-16 所对应的地址分别为 0-15。

响应:响应信息中的寄存器数据为二进制数据,每个寄存器分别对应 2 个字节,第一个字节为高位值数据,第二个字节为低位数据。

(2)功能码:10H(十进制为 16)
代码功能:预置多个寄存器
说明:把数据按顺序预置到各(4x 类型)寄存器中,广播时该功能代码可把数据预置到全部从机中的相同类型的寄存器中。需要注意的是该功能代码可越过控制器的内存保护,在寄存器中的预置值一直保持有效,只能由控制器的下一个逻辑来处理寄存器的内容,控制逻辑中无该寄存器程序时,则寄存器中的值保持不变。
查询:信息中规定了要预置的寄存器类型,寄存器寻址的起始地址为 0。查询数据区中指定了寄存器的预置值,M84 和 484 型控制器使用 10 位二进制数据,2 个字节,剩余的高 6 位置 0。而其他类型的控制器使用一个 16 位二进制数据,每个寄存器 2 个字节。

响应:正常响应返回从机地址、功能代码、起始地址和预置寄存器数。
