[转]MODBUS协议简介
原文链接:MODBUS三种通讯模式RTU,ASCII,TCP,功能码,RCR校验
MODBUS通信模式#
MODBUS通信模式最主要有三种:RTU模式,ASCII模式和TCP模式。Modbus TCP基于以太网和TCP/IP协议,Modbus RTU和Modbus ASCII则是使用异步串行传输(通常是RS-232/422/485)。
RTU模式#
地址码 | 功能码 | 数据 | 校验码 |
---|---|---|---|
一字节 | 一字节 | n字节 | 两字节(CRC) |
从机都有相应的地址码,便于主机识别,从机地址为0到255,0为广播地址,248-255保留。总线上只能有一个主设备,但可以有一个或者多个(最多247个 ip地址1-247)从设备。
广播模式:主设备向所有的从设备发送请求指令,从设备收到指令后,各自处理,不要求返回应答;这种模式下,请求指令必须是Modbus标准功能中的写指令;比如 0x06,0x10 功能码
其中数据已帧为单位进行数据传输,每帧最长为252字节,最短为0。如果一byte数据的传输时间为T,那么每两帧之间的间隔最小应该要大于3.5T,否则从机不能分辨这是两帧。第二,同一帧连续的两个数据之间的间隔时间不能超过1.5T,否则节点会认为这一帧数据不完整,这说明我们在modbus传输的时候要使能一个定时器的工作。
例子:
发送:09 03 00 04 00 03 XX
主站告诉从站09,我要读取的地址偏移为4、5、6的Holding Register的数值。其中"03"是读Holding Register的功能码,"00 04 00 03"是数据区,"00 04"是寄存器的地址,"00 03"说明要连续读三个寄存器的值。"XX"代表最后的校验位。
接收:09 03 06 02 2B 00 01 00 64 XX
从站回应该地址偏移为4的寄存器值为02 2B,地址偏移为5的寄存器值为00 01,地址偏6的寄存器值为00 64。其中"09 03"是复制了主站发来的地址和功能码,"06"代表接下来的数据共有6个字节。
ASCII模式#
起始 | 地址码 | 功能码 | 数据 | 校验 | 回车换行 |
---|---|---|---|---|---|
字符 ':'(冒号) | 两字节 | 两字节 | 0到2 * 252字节 | 两字节(LRC校验) | 两字节(CR,LF) |
帧的起始一字符 ' : '冒号开始,结束为回车换行,其对应的16进制可以到ASCII表中进行查询。字节间传输的间隔时间不能大于1s,大于1s认为这一帧数据丢失.同样我们可以计算出来ASCII帧的最大长度是513字节。
RTU使用CRC校验,ASCII使用LRC校验。
TCP模式#
主站为client端,主动建立连接;从站为server端,等待连接。
1.报文头MBAP#
MBAP为报文头,长度为7字节,组成如下:
事务处理标识 | 协议标识 | 长度 | 单元标识符 |
---|---|---|---|
2字节 | 2字节 | 2字节 | 1字节 |
- 事务处理标识 :可以理解为报文的序列号,一般每次通信之后就要加1以区别不同的通信数据报文。
- 协议标识符 :00 00表示ModbusTCP协议。
- 长度 :表示接下来的数据长度,单位为字节。
- 单元标识符 :可以理解为设备地址。
2.帧结构PDU#
PDU由功能码+数据组成。功能码为1字节,数据长度不定,由具体功能决定。
例子:
发送:01 c8 00 00 00 06 01 03 00 14 00 0a
序列号:01 c8 ,协议标识符:00 00 ,长度:00 06 ,单元标识符/服务器地址:01,功能码:03,寄存器地址:00 14 ,读取几位数据:00 0a。
接收:01 c8 00 00 00 17 01 03 14 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 03 00 00
序列号:01 c8 ,协议标识符:00 00 ,长度:00 17 ,单元标识符/服务器地址:01 ,功能码:03,数据长度:14 ,数据:就是后面的在第6位和第9位有数据。
下一条数据序,列号就会加一,变为01 c9。
RTU帧格式#
读#
MSB表示高字节;LSB表示低字节。
寄存器数据低地址数据放在前面,高地址数据放在后面
主节点发送帧格式:
序号 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
字段定义 | ADDR | CMD | MSB | LSB | MSB | LSB | LSB | MSB |
解释 | 从机地址 | 命令类型 | 寄存器起始地址(高字节) | 寄存器起始地址(低字节) | 寄存器个数n(高字节) | 寄存器个数n(低字节) | CRC校验 |
从节点正常应答帧格式:
序号 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | … | L+1 | L+2 | L+3 | L+4 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
字段定义 | ADDR | CMD | Length | MSB | LSB | MSB | LSB | … | MSB | LSB | LSB | MSB |
解释 | 从机地址 | 命令类型 | 发送字节数L=n*2 | 第一个寄存器的值(高字节) | 第一个寄存器的值(低字节) | 第二个寄存器的值(高字节) | 第二个寄存器的值(低字节) | … | 最后一个寄存器的值(高字节) | 最后一个寄存器的值(低字节) | CRC校验 |
写单个寄存器#
主节点发送帧格式:
序号 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
字段定义 | ADDR | CMD | MSB | LSB | MSB | LSB | LSB | MSB |
解释 | 从机地址 | 命令类型 | 寄存器地址(高字节) | 寄存器地址(低字节) | 数据(高字节) | 数据(低字节) | CRC校验 (低字节) | CRC校验 (高字节) |
从节点正常应答帧格式:
序号 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
字段定义 | ADDR | CMD | MSB | LSB | MSB | LSB | LSB | MSB |
解释 | 从机地址 | 命令类型 | 寄存器地址(高字节) | 寄存器地址(低字节) | 数据(高字节) | 数据(低字节) | CRC校验(低字节) | CRC校验 (高字节) |
正确的应答格式#
地址码 | 功能码 | 数据码 | 校验 |
---|---|---|---|
从机自己的 | 与发送的保持一致(范围:0x00-0x7f) | 根据功能需求 | 校验码 |
错误应答#
功能码加0x80,原本功能码最高位不会为1,加0x80最高位为1,判断出错,数据位的异常码可以知道大概是什么错误。
地址码 | 功能码 | 数据码 | 校验 |
---|---|---|---|
从机自己的 | 与发送的保持一致(范围:0x00-0x7f) + 0x80 | 异常码 | 校验码 |
异常码#
功能码#
- 0x01: 读线圈寄存器(可读可写线圈)
- 0x02: 读离散输入寄存器(可读不可写线圈)
- 0x03: 读保持寄存器(可读可写寄存器)
- 0x04: 读输入寄存器(可读不可写寄存器)
- 0x05: 写单个线圈寄存器(可写单个线圈不可读)
- 0x06: 写单个保持寄存器(可写单个寄存器不可读)
- 0x0f: 写多个线圈寄存器(可写多个线圈不可读)
- 0x10: 写多个保持寄存器(可写多个寄存器不可读)
01H-->读线圈寄存器#
地址码 | 功能码 | 数据 | 校验 | |
---|---|---|---|---|
发送 | 01 | 01 | 00 20 00 05 | FD C3 |
响应 | 01 | 01 | 01 15 | 90 47 |
发送数据:读取地址:00 20,从0x20处开始读取,00 05 读取5个寄存器。
响应数据:01,只有5个寄存器,小于8,5/8=0,加1,所以为1,假设有9个,则为02,以此类推。15,二进制:00010101,在5个寄存器中有3个处于开的状态。
02H--->读离散输入寄存器#
地址码 | 功能码 | 数据 | 校验 | |
---|---|---|---|---|
发送 | 01 | 02 | 00 20 00 05 | B9 C3 |
响应 | 01 | 02 | 01 02 | 20 49 |
发送数据:读取地址:00 20,从0x20处开始读取,00 05 读取5个寄存器。
响应数据:01,只有5个寄存器,小于8,5/8=0,加1,所以为1,假设有9个,则为02,以此类推。02,二进制:00000010,在5个寄存器中有1个处于开的状态,在此功能下只能读取从机状态。
03-->读保持寄存器#
地址码 | 功能码 | 数据 | 校验 | |
---|---|---|---|---|
发送 | 01 | 03 | 00 14 00 03 | 45 CF |
响应 | 01 | 03 | 06 00 14 00 1E 00 00 | 71 70 |
发送数据:读取地址:00 14,从0x14处开始读取3个寄存器。
响应数据:06,后面有6位,00 14,发送的数据0x14,00 1E发送的数据0x1E,00 00发送的数据0X00。
04--> 读输入寄存器#
地址码 | 功能码 | 数据 | 校验 | |
---|---|---|---|---|
发送 | 01 | 04 | 00 14 00 03 | F0 0F |
响应 | 01 | 04 | 06 00 14 00 1E 00 00 | 30 96 |
发送数据:读取地址:00 20,从0x20处开始读取,00 05 读取3个寄存器。
响应数据:06,后面有6位,00 14,发送的数据0x14,00 1E发送的数据0x1E,00 00发送的数据0X00,在此功能下只能读取从机状态。
05-->写单个线圈寄存器#
地址码 | 功能码 | 数据 | 校验 | |
---|---|---|---|---|
发送 | 01 | 05 | 00 20 00 00 | CC 00 |
响应 | 01 | 05 | 00 20 00 00 | CC 00 |
发送数据:读取地址:00 20,从0x20处开始写入,00 00 写入值。
响应数据:跟发送的一样。
06-->写单个保持寄存器#
地址码 | 功能码 | 数据 | 校验 | |
---|---|---|---|---|
发送 | 01 | 06 | 00 01 00 03 | XX XX |
响应 | 01 | 06 | 00 01 00 03 | XX XX |
发送数据:读取地址:00 01,从0x01处开始写入,00 03 写入值。
响应数据:跟发送的一样。
0F-->写多个线圈寄存器#
地址码 | 功能码 | 数据 | 校验 | |
---|---|---|---|---|
发送 | 01 | 0F | 00 14 00 03 01 00 | CC 00 |
响应 | 01 | 0F | 00 14 00 03 | CC 00 |
发送数据:读取地址:00 14,从0x14处开始写入,00 03 写入3个值, 3小于8,所以为01, 00,写入的3个数据都为0。
响应数据:00 14,写入地址,00 03,3个数据。
10-->写多个保持寄存器#
地址码 | 功能码 | 数据 | 校验 | |
---|---|---|---|---|
发送 | 01 | 10 | 00 34 00 02 04 0C 02 12 45 | XX XX |
响应 | 01 | 10 | 00 34 00 02 | XX XX |
发送数据:读取地址:00 34,从0x34处开始写入,00 02 写入2个值,04后面有4位,0C 02和12 45都为数据。
响应数据:00 14,写入地址,00 02,2个数据。
CRC校验:#
校验码是4位是因为多项式为5位,校验码少一位。
附件#
- 参考网站:https://www.modbus.cn/6756.html
- MODBUS中文文档:提取码: br55
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!