Modbus-RTU协议
RTU ADU如图所示。
除了核心PDU之外,该ADU仅包含两条信息。 首先,地址用于定义PDU对应的从设备。 在大多数网络中,地址0定义的是“广播”地址。 也就是说,主设备可以发送输出命令到地址0,而所有从设备应处理该请求,但是不做出任何响应。 除了这个地址外,CRC还用于确保数据的完整性。
数据包的首尾一对沉默时间(silent time),消息发送至少要以3.5个字节时间的停顿间隔开始,即总线上没有通信的时段。对于9,600的波特率,这个速率大约是4ms。该标准定义了一个最小沉默长度,不论波特率如何,都低于2 ms。在最后一个传输字节之后,一个至少3.5个字节时间的停顿标定了消息的结束。
另外还规定了报文需要连续发送,字节间隔不得超过1.5字节时间。
这存在性能缺陷,因为在处理数据包之前设备必须等待空闲时间结束。 然而,更危险的是串行传输引入了不同技术,并且波特率比标准更快。 例如,使用USB/串口转换器电缆,您无法控制数据的数据包和数据传输。 测试表明,结合NI-VISA驱动程序使用USB转串口电缆会在数据流中引入了尺寸可变的大间隙,而这些间隙 – 沉默期 – 会“诱骗”符合规范的代码相信消息是完整的。 由于消息不完整,通常会导致CRC无效,并导致设备将ADU解释为损坏。
帧结构 = 地址 + 功能码+ 数据 + 校验
地址: 占用一个字节,范围0-255,其中有效范围是1-247,其他有特殊用途,比如0是广播地址(广播地址就是应答所有地址,正常的需要两个设备的地址一样才能进行查询和回复)。
功能码:占用一个字节,功能码的意义就是,知道这个指令是干啥的,比如你可以查询从机的数据,也可以修改数据,所以不同功能码对应不同功能。
数据:根据功能码不同,有不同结构,在下面的实例中有说明。
校验:为了保证数据不错误,增加这个,然后再把前面的数据进行计算看数据是否一致,如果一致,就说明这帧数据是正确的,我再回复;如果不一样,说明你这个数据在传输的时候出了问题,数据不对的,所以就抛弃了。
起始位 设备地址 功能代码 数据 CRC校验 结束符
T1-T2-T3-T4 8Bit 8Bit n个8Bit 16Bit T1-T2-T3-T4
| 地址码 | 功能码 | 数据区 | CRC校验 |
| — | — | — | — |
| 1 Bytes | 1Byte | N Bytes | 2Byte |
| 地址码:1个字节的从机地址码,=0:广播地址,=1-247:从机地址,=248-255:保留 | | | |
| 功能码:常用的就是01、02、03、04、05、06、15、16,具体描述见下图 | | | |
| 数据区:数据区包含这么几部分:起始地址、数量、数据,这三项是大端模式 | | | |
| CRC校验:两个字节,小端模式,校验的数据范围为:地址码+功能码+数据区 | | | |
Modbus-RTU协议一般我们用的最多功能码就是03和06,大部分都是用modbus来查询传感器上的信息用03查询功能码,如果需要修改传感器寄存器的值就用06修改功能码.
发送:从机的地址+功能码+要查的寄存器的地址+要查的寄存器地址的个数+校验码
回复:从机的地址+主机发的功能码+要发送给主机数据的字节数+数据+校验码
现在我是主机,我要查询从机地址为01的数据,查询功能码0x03
- 主机发送: 01 03 00 00 00 01 84 0A
- 从机回复: 01 03 02 19 98 B2 7E
01-地址,也就是你传感器的地址
03-功功能码,03代表查询功能,查询传感器的数据
00 00-代表查询的起始寄存器地址.说明从0x0000开始查询。这里需要说明以下,Modbus把数据存放在寄存器中,通过查询寄存器来得到不同变量的值,一个寄存器地址对应2字节数据
00 01-代表查询了一个寄存器.结合前面的00 00,意思就是查询从0开始的1个寄存器值
84 0A-循环冗余校验,是modbus的校验公式,从首个字节开始到84前面为止;
回复数据解析
01-地址,也就是你传感器的地址
03-功功能码,03代表查询功能,查询传感器的数据。这里要注意的是注意发给从机的功能码是啥,从机就要回复同样的功能码,如果不一样说明这一帧数据有错误
02-代表后面数据的字节数,因为上面说到,一个寄存器有2个字节,所以后面的字节数肯定是2*查询的寄存器个数;
19 98-寄存器的值是19 98,结合发送的数据看出,01这个寄存器的值为19 98
B2 7E-循环冗余校验
功能码01:读线圈状态
示例1:读1个线圈状态,线圈地址为0:
主机发送:01 01 00 00 00 01 FD CA
从机返回:01 01 01 00 51 88
解析主机发送的数据:
| 01 | 01 | 00 00 | 00 01 | FD CA |
| — | — | — | — | — |
| 从机地址 | 功能码 | 要读的线圈起始地址(大端模式) | 要读取的线圈数量(大端模式) | CRC校验码(小端模式) |
解析从机返回的数据,只说数据区:
- 01:后跟的字节数
- 00:线圈状态
示例2:读从线圈0开始的10个线圈状态:
主机发送:01 01 00 00 00 0A BC 0D
从机返回:01 01 02 00 00 b9 fc
解析从机返回的数据,只说数据区:
- 02:后跟的字节数
- 00 00:一个比特代表一个线圈的状态
功能码02:读离散量输入
协议格式同功能码01。
功能码03:读保持寄存器
示例1:读1个保持寄存器,保持寄存器地址为0:
主机发送:01 03 00 00 00 01 84 0A
从机接收:01 03 02 00 00 b8 44
解析主机发送的数据:
| 01 | 03 | 00 00 | 00 01 | 84 0A |
| — | — | — | — | — |
| 从机地址 | 功能码 | 要读取的保持寄存器起始地址(大端模式) | 要读取的保持寄存器数量(大端模式) | CRC校验码(小端模式) |
解析主机返回的数据,只说数据区:
- 02:后跟的字节数
- 00 00:读取到的保持寄存器的值,大端模式
示例2:读10个保持寄存器,保持寄存器起始地址为0:
主机发送:01 03 00 00 00 0A C5 CD
从机返回:01 03 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a3 67
解析主机返回的数据(只说数据区):
- 14:后跟的字节数
- 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00:读取到的保持寄存器的值,大端模式,一个寄存器值用2字节表示。
功能码04:读输入寄存器
协议格式同功能码03。
功能码05:写单个线圈
示例1:写线圈0为0:
主机发送:01 05 00 00 00 00 CD CA
从机返回:01 05 00 00 00 00 cd ca
解析主机发送的数据:
| 01 | 05 | 00 00 | 00 00 | CD CA |
| — | — | — | — | — |
| 从机地址 | 功能码 | 要写的线圈地址(大端模式) | 要写的线圈状态(大端模式) | CRC校验码(小端模式) |
主机发送什么,从机原样返回。
示例2:写线圈0为1:
主机发送:01 05 00 00 FF 00 8C 3A
从机返回:01 05 00 00 ff 00 8c 3a
解析主机发送的数据,只说数据区:
- 00 00:要写的线圈地址,大端模式
- FF 00:要写的线圈状态,FF 00表示将线圈置1
功能码06:写单个寄存器
示例1:写寄存器0为0:
主机发送:01 06 00 00 00 00 89 CA
从机返回;01 06 00 00 00 00 89 CA
解析主机发送的数据:
| 01 | 06 | 00 00 | 00 00 | 89 CA |
| — | — | — | — | — |
| 从机地址 | 功能码 | 要写的寄存器地址(大端模式) | 要写的寄存器(大端模式) | CRC校验码(小端模式) |
主机发送什么,从机原样返回。
示例2:写寄存器0为1:
主机发送:01 06 00 00 00 01 48 0A
从机返回:01 06 00 00 00 01 48 0a
功能码15:写多个线圈
写从线圈编号0开始的10个线圈:0-3线圈写1,4-7线圈写0,8-9线圈写1(0F 03):
主机发送:01 0F 00 00 00 0A 02 0F 03 A0 C9
从机返回:01 0f 00 00 00 0a d5 cc
解析主机发送的数据:
| 01 | 0F | 00 00 | 00 0A | 02 | 0F 03 | A0 C9 |
| — | — | — | — | — | — | — |
| 从机地址 | 功能码 | 要写的线圈起始地址(大端模式) | 要写的线圈数量(大端模式) | 后跟的字节数 | 待写入的线圈状态,小端模式,换成比特由低位到高位就是:1111 0000 11XX XXXX,X表示未用到,一个比特代表一个线圈的状态 | CRC校验码(小端模式) |
解析从机返回的数据,只说数据区:
- 00 00:已写的线圈起始地址,大端模式
- 00 0A:已写的线圈数量,大端模式
功能码16:写多个寄存器
写寄存器编号0开始的10个寄存器:0-3寄存器写1,4-7寄存器写0,8-9寄存器写1:
主机发送:01 10 00 00 00 0A 14 00 01 00 01 00 01 00 01 00 00 00 00 00 00 00 00 00 01 00 01 4F 13
从机返回:01 10 00 00 00 0a 40 0e
解析主机发送的数据:
| 01 | 10 | 00 00 | 00 0A | 14 | 00 01 00 01 00 01 00 01 00 00 00 00 00 00 00 00 00 01 00 01 | 4F 13 |
| — | — | — | — | — | — | — |
| 从机地址 | 功能码 | 要写的寄存器起始地址(大端模式) | 要写的寄存器数量(大端模式) | 后跟的字节数 | 待写入的寄存器值,大端模式,两个字节代表一个寄存器的值 | CRC校验码(小端模式) |
解析从机返回的数据,只说数据区:
- 00 00:已写的寄存器起始地址,大端模式
- 00 0A:已写的寄存器数量,大端模式
评论区