0 简介
Modbus,作为一种串行通信协议,由施耐德电气(前身为Modicon公司)在1979年发布,旨在支持可编程逻辑控制器(PLC)之间的通信。自那时起,Modbus已经成为工业界通信协议的标杆,并且如今广泛应用于各种工业电子设备间的连接。
关于这一重要的工业通信协议,网络上关于其优缺点的分析文章比比皆是。在此我仅谈谈我自己的一些看法:
- Modbus协议兼顾了数据链路层与应用层的双层结构,结构简单清晰,且标准化程度强,极易进行标准化建模。
- 数据链路层颇显简单,用于进行校验帧完整性的只有数据长度与CRC校验码,在干扰环境比较大的情况下容易出现粘包或丢包等现象。
- Modbus的回复帧是不能自解析的,也即是只能与发送帧相结合才能得知回复帧内数据的意义。这就决定了当从机端的多帧处理机制,即只能处理最后一帧,而必须忽略其他帧
1 总线网
Modbus协议通过主从方式的实现通信,即非同步,总线上每次只有一个数据进行传输,即主机发送、从机应答、主机不发送、总线上就没有数据通信。
例如,一个总线上有一个主机,多个从机,主机查询其中一个从机,首先用户要为从机分配地址,且每个地址必须唯一,以便对应。分配好地址后,主机要查询并下发数据,从机得到主机发送的数据,然后对应地址的从机回复,主机得到从机数据。这就是一个主机到从机的通信过程。
Modbus可以细分为Modbus ASCII、Modbus RTU和Modbus TCP,而在工业领域里使用最多的是Modbus-RTU协议。其原因可能在于工业现场网络环境的限制和对传输效率的要求。
Modbus-RTU协议可以通过不同的物理层传输介质进行通信,包括串行线缆和以太网,使用最多的应该还是RS485。
RS485具有如下显著特点
- 接口电平低,不易损坏芯片。RS485的电气特性:逻辑“1”以两线间的电压差为+(2–6)V表示;逻辑“0”以两线间的电压差为-(2–6)V表示。接口信号电平比RS232降低了,不易损坏接口电路的芯片。
- 传输速率高。10米时,RS485的数据最高传输速率可达35Mbps,在1200m时,传输速度可达100kbps。
- 抗干扰能力强。RS485接口是采用平衡驱动器和差分接收器的组合,抗共模干扰能力增强,即抗噪声干扰性好。
- 传输距离远,支持节点多。RS485总线最长可以传输1200m以上(速率≤100kbps)一般最大支持32个节点,如果使用特制的485芯片,可以达到128个或者256个节点,最大的可以支持到400个节点。
这些特点决定了RS485在工业领域得到广泛的应用
2 数据流
Modbus-ASCII有开始字符(和结束字符(CR LF),可以作为一帧数据开始和结束的标志,而Modbus-RTU没有这样的标志,需要用时间间隔来判断一帧报文的开始和结束,协议规定的时间为3.5个字符周期,就是说一帧报文开始前,必须有大于3.5个字符周期的空闲时间,一帧报文结束后,也必须要有3.5个字符周期的空闲时间否则就会出现粘包的情况。
针对3.5个字符周期,其实是一个具体时间,但是这个时间跟波特率相关。在串口通信中,1个字符包括1位起始位、8位数据位(一般情况)、1位校验位(或者没有)、1位停止位(一般情况下),因此1个字符包括11个位,那么3.5个字符就是38.5个位,波特率表示的含义是每秒传输的二进制位的个位,因此如果是9600波特率,3.5个字符周期=/960038.5=0.00401s1000=4.01ms
注:在应用程序中,尤其是在Windows系统并不是实时操作系统,很难区分ms级别的时间粒度,因此很少会认真对待这3.5个字符周期。这也是Modbus-RTU协议容易出现粘包现象的原因。
所谓粘包就是连续给对端发送两个或者两个以上的数据包,对端在一次收取中收到的数据包数量可能大于1个。
3 帧格式
地址码 | 功能码 | 数据区 | 校验码 |
---|---|---|---|
1字节 | 1字节 | … | 2字节 |
1、地址码:单个设备的地址范围是1...247。主设备通过将要联络的从设备的地址放入消息中的地 址域来选通从设备。当从设备发送回应消息时,它把自己的地址放入回应的地址域中,以便主设备知道是哪一个设备作出回应。
地址0是用作广播地址,以使所有的从设备都能认识。当Modbus协议用于更高水准的网络,广播可能不允许或以其它方式代替。
需要特别指出:在很多实际的应用中是使用地址255作为广播地址
2、功能码:
- · 0x01:读线圈
- · 0x05:写单个线圈
- · 0x0F:写多个线圈
- · 0x02:读离散量输入
- · 0x04:读输入寄存器
- · 0x03:读保持寄存器
- · 0x06:写单个保持寄存器
- · 0x10:写多个保持寄存器
如何区分输入寄存器、保持寄存器呢,如下所述
- 保持寄存器(Holding Register):
- 定义:保持寄存器用于存储可读可写的数值数据,通常是设备的设置或控制参数。
- 用途:用于控制或设置设备的参数(如设定温度、控制阈值等),或存储设备的状态信息。
- 存储方式:数据可修改,用户可以通过Modbus协议来读取或写入这些寄存器。
- 输入寄存器(Input Register):
- 定义:输入寄存器用于存储只读的数值数据,通常由外部设备(如传感器)提供。
- 用途:用于读取设备的实时测量数据(如温度、湿度、压力等),这些数据不能被修改。
- 存储方式:数据通常是只读的,不能通过Modbus协议直接修改。
在实际应用中,使用最多的是0x03、0x04、0x06、0x10,在很多情况下,用户会忽视保持寄存器、输入寄存器的区别,统一采用保持寄存器代之。
3、校验码 :采用的是CRC16/X.25 ,详见本人博客
4、数据区:Modbus通讯协议本身不指定数据字节的顺序(大端或小端),这是由使用Modbus的设备自行决定的。
大端字节顺序是指数据的高位字节存储在低地址处,而低位字节存储在高地址处。小端字节顺序则恰好相反,低位字节存储在低地址处,高位字节存储在高地址处。
在Modbus协议中,通常推荐使用大端模式。以下是几个原因:
1、一致性与兼容性:大多数Modbus设备是基于大端模式设计和制造的;使用大端模式可以确保与这些设备的良好兼容性。
2、人类可读性:大端模式符合人类阅读习惯,高位在前,低位在后,使得数据更易于理解和处理。
3、标准规范:在一些Modbus标准文档中,虽然没有强制规定,但大端模式被广泛接受为默认选择。
4 功能码
- 0x04 读输入寄存器
查询帧规定了要读寄存器的起始地址及寄存器的数量,
地址 | 功能码 | 寄存器起始地址H | 寄存器起始地址L | 寄存器数量H | 寄存器数量L | CRC16H | CRC16L |
11H | 04H | 00H | 08H | 00H | 02H | XXH | XXH |
响应帧中的寄存器数据为每个寄存器分别对应2个字节,第一个字节为高位字节,第二个字节为低位字节
地址 | 功能码 | 字节数 | 数据H | 数据L | …… | CRC16H | CRC16L |
11H | 04H | 04H | 00 | 0AH | XXH XXH | XXH | XXH |
- 2. 0x03 读保持寄存器
查询帧规定了要读寄存器的起始地址及寄存器的数量,
地址 | 功能码 | 寄存器起始地址H | 寄存器起始地址L | 寄存器数量H | 寄存器数量L | CRC16H | CRC16L |
11H | 03H | 00H | 08H | 00H | 02H | XXH | XXH |
响应帧中的寄存器数据为每个寄存器分别对应2个字节,第一个字节为高位字节,第二个字节为低位字节
地址 | 功能码 | 字节数 | 数据H | 数据L | …… | CRC16H | CRC16L |
11H | 03H | 04H | 00 | 0AH | XXH XXH | XXH | XXH |
3. 0x06 写单个保持寄存器
设置帧规定了要设置寄存器的地址及设置值,
地址 | 功能码 | 寄存器地址H | 寄存器地址L | 寄存器数值H | 寄存器数值L | CRC16H | CRC16L |
11H | 06H | 00H | 40H | 0AH | 9DH | XXH | XXH |
正常的响应帧是将寄存器值改变后将接收到的数据传送回去
地址 | 功能码 | 寄存器地址H | 寄存器地址L | 寄存器数值H | 寄存器数值L | CRC16H | CRC16L |
11H | 06H | 00H | 40H | 0AH | 9DH | XXH | XXH |
4. 0x10 写多个保持寄存器
设置帧规定了要设置寄存器的地址及设置值,设置值依然是高字节在前
地址 | 功能码 | 寄存器起始地址H | 寄存器起始地址L | 寄存器数量H | 寄存器数量L | 字节数 | 设置值 | CRC16H | CRC16L |
11H | 10H | 00H | 40H | 00H | 02H | 04H | XXH | XXH |
响应帧是在设置帧的基础上去除字节数与写入值
地址 | 功能码 | 寄存器起始地址H | 寄存器起始地址L | 寄存器数量H | 寄存器数量L | CRC16H | CRC16L |
11H | 10H | 00H | 40H | 00H | 02H | XXH | XXH |
5. 错误响应
Modbus设备接收到不能处理的请求或请求无效时,它会返回一个错误响应。错误响应的功能码是原请求的功能码加上80(十六进制)。错误响应还包含一个异常码,说明错误的类型。
地址 | 错误功能码 | 异常码 | CRC16H | CRC16L |
---|---|---|---|---|
11H | 10H | 00H | XXH | XXH |
通过这些响应格式,你可以设计和调试Modbus网络通信,确保数据的正确传输和设备的正确响应。
Modbus RTU异常码通常指的是在Modbus通讯过程中,从机返回的错误响应。这些错误响应包括以下几种:
- 异常码 0x01 - 非法功能
- 异常码 0x02 - 非法数据地址
- 异常码 0x03 - 非法数据值
- 异常码 0x04 - 服务器故障