Modbus简介
Modbus 是一种串行通信协议,是 Modicon 于 1979 年,为使用可编程逻辑控制器(PLC)而发表的。Modbus 是工业领域通信协议的业界标准,并且现在是工业电子设备之间相当常用的连接方式。
格式总览
从机地址 | 功能码 | 数据 | CRC校验 |
---|---|---|---|
1字节 | 1字节 | 0~252字节 | 2字节 |
- 举例: 01 03 00 00 00 0A C5 CD
从机地址
地址 | 说明 |
---|---|
广播地址:0 | 主机向地址0发送命令报文,全部从机收到报文后执行,但不发送回应报文。 |
1-247 | |
保留:248-255 |
功能码和寄存器
PLC地址和Modbus协议地址
PLC地址
PLC 的地址,是指控制器中的寄存器地址,这些控制器可以是 PLC,也可以是触摸屏,或是文本显示器。
PLC 地址一般采用 10 进制描述,共有 5 位,其中第一位代码,如 0、3,标明寄存器类型。第一位开头数字和寄存器类型的对应关系如常用公共功能码所示。
PLC 地址例如40001、30002 等。
Modbus协议地址
协议地址指,通信时使用的地址,例如 PLC 地址 40001 对应寻址地址 0x0000,40002对应寻址地址 0x0001,40016 对应 0x000F,通讯寻址地址一般使用 16 进制描述。
再如,PLC 地址 40003 对应协议地址 0002,PLC 地址 30003 也对应协议地址 0002,虽然访问这两个 PLC 地址 40003、30003,通信时使用相同的协议地址 0002,但是需要使用不同的命令访问(PLC 地址开头的 0、1、3、4,决定了访问它们需要不同的功能码,命令的第二字节即功能码),所以访问时不存在冲突。
地址的转换
PLC 地址和通讯协议地址十分相似,PLC 地址由开头的 0、1、3、4 指示是哪种类型的变量,后面加 4 位数字来表示偏移量。
不同的是,PLC 的起始地址(偏移量)是 0001 开始,而 Modbus 协议的偏移量是从 0000开始,另外,PLC 地址是十进制表示,而协议地址是十六进制表示。
:::info
一般来说,PLC 的起始地址 = Modbus 协议地址(先换成十进制)+ 1
:::
功能码总览
常用公共功能码
操作单位 | 寄存器种类 | PLC地址 (10进制) |
功能码 | |
---|---|---|---|---|
单个比特 (位操作) |
线圈状态 - Coil Status> 数字量输出 - DO |
例:继电器输出、LED
| 00001 - 09999> 可读可写
| 0x01 | 读单个或多个线圈 | | | | | 0x05 | 写单个线圈 | | | | | 0x0F | 写多个线圈 | | | 离散输入状态 - Input Status> 数字量输入 - DI
例:拨码开关 、接近开关
| 10001 - 19999> 只读
| 0x02 | 读单个或多个离散输入 |
| 16比特
(字操作) | 输入寄存器 - Input Register> 模拟量输入 - AI
例:模拟量输入
| 30001 - 39999> 只读
| 0x04 | 读一个或多个输入寄存器 | | | 保持寄存器 - HoldingRegister> 模拟量输出 - AO
例:温度传感器
| 40001 - 49999> 可读可写
| 0x03 | 读一个或多个保持寄存器 | | | | | 0x06 | 写单个保持寄存器 | | | | | 0x10 | 写多个保持寄存器 |
有人(cloud.usr.cn)扩展功能码
功能码 | 功能 | 通信数据格式 |
---|---|---|
0x45 | 从机主动上报多个线圈 | 格式与 0x0F 写多个线圈 相同 |
0x42 | 从机主动上报多个离散输入 | |
0x46 | 从机主动上报多个保持寄存器 | 格式与 0x10 写多个保持寄存器 相同 |
0x44 | 从机主动上报多个输入寄存器 |
Modbus功能码分类
功能码(十进制) | 功能码(十六进制) | 分类 |
---|---|---|
1 ~ 64 | 0x01 ~ 0x40 | 公共功能码 |
65 ~ 72 | 0x41 ~ 0x48 | 用户自定义功能码 |
73 ~ 119 | 0x49 ~ 0x77 | 非法功能 |
120 ~ 127 | 0x78 ~ 0x7F | 保留。留作内部使用 |
128 ~ 255 | 0x80 ~ 0xFF | 保留。用作异常应答 |
0x01 读单个或多个线圈
请求 | - 读取0x0001到0x000A单元的开关状态 |
||||
---|---|---|---|---|---|
从机地址 | 功能码 | 寄存器起始地址 | 寄存器单元长度 | CRC校验 | |
id | 01 | 00 00 | 00 0A | CrcL CrcH |
应答 | - 1表示ON,0表示OFF - 现场状态为全开(即全1) :1111 1111 0000 0011 -> FF 03 |
||||
---|---|---|---|---|---|
从机地址 | 功能码 | 字节数 | 数据 | CRC校验 | |
id | 01 | 02 | FF 03 | CrcL CrcH |
0x02 读单个或多个离散输入
- 同 0x01 读单个或多个线圈
| 请求 |
- 读取0x0001到0x000A单元的开关状态
| | | | | | —- | —- | —- | —- | —- | —- | | | 从机地址 | 功能码 | 寄存器起始地址 | 寄存器单元长度 | CRC校验 | | | id | 02 | 00 00 | 00 0A | CrcL CrcH |
应答 | - 1表示ON,0表示OFF - 现场状态为全开(即全1) :1111 1111 0000 0011 -> FF 03 |
||||
---|---|---|---|---|---|
从机地址 | 功能码 | 字节数 | 数据 | CRC校验 | |
id | 02 | 02 | FF 03 | CrcL CrcH |
0x05 写单个线圈
请求 | - 将0x00AD单元状态置为ON - FF 00 表示ON,00 00 表示OFF |
||||
---|---|---|---|---|---|
从机地址 | 功能码 | 寄存器起始地址 | 线圈状态 | CRC校验 | |
id | 05 | 00 AC | FF 00 | CrcL CrcH |
应答 | - 应答跟请求相同 |
||||
---|---|---|---|---|---|
从机地址 | 功能码 | 寄存器起始地址 | 线圈状态 | CRC校验 | |
id | 05 | 00 AC | FF 00 | CrcL CrcH |
0x0F 写多个线圈
请求 | - 1表示ON,0表示OFF - 从0x0014开始写入10个状态值,数据内容为2个字节:十六进制CD 01(二进制 1100 1101 0000 0001,用不到的位补0) |
||||||
---|---|---|---|---|---|---|---|
从机地址 | 功能码 | 寄存器起始地址 | 寄存器单元长度 | 字节数 | 数据 | CRC校验 | |
id | 0F | 00 13 | 00 0A | 02 | CD 01 | CrcL CrcH |
应答 | |||||
---|---|---|---|---|---|
从机地址 | 功能码 | 寄存器起始地址 | 寄存器单元长度 | CRC校验 | |
id | 0F | 00 13 | 00 0A | CrcL CrcH |
0x04 读一个或多个输入寄存器
请求 | - 读取寄存器108—110的值 |
||||
---|---|---|---|---|---|
从机地址 | 功能码 | 寄存器起始地址 | 寄存器单元长度 | CRC校验 | |
id | 04 | 00 6B | 00 03 | CrcL CrcH |
应答 | - 108的内容为0x022B(即555),109的内容为0x0000(即0),110的内容为0x0064(即100) |
||||
---|---|---|---|---|---|
从机地址 | 功能码 | 字节数 | 数据 | CRC校验 | |
id | 04 | 06 | 02 2B 00 00 00 64 | CrcL CrcH |
0x03 读一个或多个保持寄存器
- 同 0x04 读一个或多个输入寄存器
| 请求 |
- 读取寄存器108—110的值
| | | | | | —- | —- | —- | —- | —- | —- | | | 从机地址 | 功能码 | 寄存器起始地址 | 寄存器单元长度 | CRC校验 | | | id | 03 | 00 6B | 00 03 | CrcL CrcH |
应答 | - 108的内容为0x022B(即555),109的内容为0x0000(即0),110的内容为0x0064(即100) |
||||
---|---|---|---|---|---|
从机地址 | 功能码 | 字节数 | 数据 | CRC校验 | |
id | 03 | 06 | 02 2B 00 00 00 64 | CrcL CrcH |
0x06 写单个保持寄存器
请求 | - 将数据0x0003写入寄存器单元0x0002 |
||||
---|---|---|---|---|---|
从机地址 | 功能码 | 寄存器起始地址 | 数据 | CRC校验 | |
id | 06 | 00 01 | 00 03 | CrcL CrcH |
应答 | - 应答跟请求相同 |
||||
---|---|---|---|---|---|
从机地址 | 功能码 | 寄存器起始地址 | 数据 | CRC校验 | |
id | 06 | 00 01 | 00 03 | CrcL CrcH |
0x10 写多个保持寄存器
请求 | - 将数据0x000A和0x0102写入从0x0002开始的两个寄存器单元 |
||||||
---|---|---|---|---|---|---|---|
从机地址 | 功能码 | 寄存器起始地址 | 寄存器单元长度 | 字节数 | 数据 | CRC校验 | |
id | 10 | 00 01 | 00 02 | 04 | 00 0A 01 02 | CrcL CrcH |
应答 | |||||
---|---|---|---|---|---|
从机地址 | 功能码 | 寄存器起始地址 | 寄存器单元长度 | CRC校验 | |
id | 10 | 00 01 | 00 02 | CrcL CrcH |
附 学习资料
- 闫越老师的总结
- 有人扩展指令(本扩展指令非Modbus RTU标准,仅适用于设备与透传云/有人云网络通讯的规则)
有人扩展指令ModbusRTU V1.1.0.xlsx
有人扩展指令ModbusRTU V1.1.0.xlsx
附 调试工具
- ModeBusRTU调试工具