文章目录 报文模型 功能代码 读线圈 (0x01 0x02) 读寄存器 (0x03 0x04) 写单个线圈 (0x05) 写单个寄存器 (0x06 0x41) 写多个线圈(0x0F) 写多个寄存器(0x10 0x43) 错误代码
Modbus协议 ,首先从字面理解它包括
Mod 和
Bus 两部分,首先它是一种bus,即总线协议,和
I2C、
SPI类似,总线就意味着有主机,有从机,这些设备在同一条总线上。
Modbus支持单主机,多个从机,最多支持247个从机设备。关于Mod,因为这种协议最早被用在PLC控制器中,准确的说是Modicon 公司的PLC控制器,这也是Mod-Bus 名称的由来。
后来Modicon被施耐德(Schneider)收购,Modbus协议广泛应用在工业控制器、HMI和传感器上,逐渐被其他厂商接受,成为一种主流的通讯协议,用于和外围设备进行通讯。
报文模型
一个报文就是一帧数据:一串完整的指令数据。 Modbus采用 "Big Endian"编码方式,先发送高位字节,然后是低位字节。
设备地址 功能代码 数据 校验 1* 8bit 1* 8bit N * 8bit 2 * 8bit
功能代码
功能码 功能码名称 可操作元件类型 注释 0x01 读线圈 Y、X、M、SM、S、T、C 读一个或多个位 0x02 读离散量输入 X 读一个或多个位 0x03 读寄存器 D、SD、Z、T、C 读一个或多个字 0x05 写单个线圈 Y、M、SM、S、T、C 写一个位 0x06、0x41 写一个寄存器 D、SD、Z、T、C 写一个字 0x0F 写多个线圈 Y、M、SM、S、T、C 写多个位 0x10、0x43 写多个寄存器 D、SD、Z、T、C 写多个字
读线圈 (0x01 0x02)
请求帧
设备地址 功能码(01H) 起始地址 读取个数 校验码 H L H L
响应帧 如果读取的地址不是8的倍数,剩下的位由0填充(由高位开始填充)。
设备地址 功能码(01H) 读取的个数n (字节数) 读取的数据No.1 ...... 读取的数据No.n 校验码
3. 举例
请求 响应 字段名 16进制 字段名 16进制 功能码 01 功能码 01 起始地址 Hi 00 字节计数 03 起始地址 Lo 13 输出状态27~20 CD 输出数量 Hi 00 输出状态35~28 6B 输出数量 Lo 13 输出状态38~36 05
输出27~20的状态表示为十六进制字节值CD,或二进制1100 1101.输出27是这个字节的MSB(最高有效位),输出20是LSB(最低有效位)
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 1 1 0 0 1 1 0 1 27 26 25 24 23 22 21 20
在最后的数据字节中,将输出38~36的状态表示为十六进制字节值05,或二进制 0000 0101。用零填充5个剩余高位。
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 0 0 0 0 0 1 0 1 38 37 36
读寄存器 (0x03 0x04)
请求帧
设备地址 功能码(03H) 起始地址 读取个数 (N) 校验码 H L H L
响应帧
设备地址 功能码(03H) 读取的个数2*N 读取的数据No.1 ...... 读取的数据No.n 校验码 H L H L
3. 举例 请求读取寄存器108~110的示例。
请求 响应 字段名 16进制 字段名 16进制 功能码 03 功能码 03 起始地址 Hi 00 字节计数 06 起始地址 Lo 6B 寄存器值 Hi(108) 02 寄存器数量 Hi 00 寄存器值 Lo(108) 2B 寄存器数量 Lo 03 寄存器数量 Hi (109) 00 寄存器值 Lo(109) 00 寄存器值 Hi(110) 00 寄存器值 Lo(110) 64
结果为:
寄存器 内容值 (十六进制) 内容值 (十进制) 寄存器 108 02 2B 555 寄存器 109 00 00 0 寄存器 110 00 64 100
写单个线圈 (0x05)
请求帧
设备地址 功能码(05H) 起始地址 写入的值 校验码 H L H L
注:写入的元件的值为0xFF00(ON,1)或者(0x0000)(OFF,0)。
响应帧 响应帧是请求帧的重复。
设备地址 功能码(05H) 起始地址 写入的值 校验码 H L H L
3. 举例
请求 响应 字段名 16进制 字段名 16进制 功能码 05 功能码 05 起始地址 Hi 00 起始地址 Hi 00 起始地址 Lo AC 起始地址 Lo AC 输出值 Hi FF 输出值 Hi FF 输出值 Lo 00 输出值 Lo 00
写单个寄存器 (0x06 0x41)
请求帧
设备地址 功能码(06H) 起始地址 写入的值 校验码 H L H L
响应帧 响应帧是请求帧的重复。
设备地址 功能码(06H) 起始地址 写入的值 校验码 H L H L
3. 举例 将一个十六进制 00 03写入寄存器2的示例
请求 响应 字段名 16进制 字段名 16进制 功能码 06 功能码 06 起始地址 Hi 00 起始地址 Hi 00 起始地址 Lo 02 起始地址 Lo 02 寄存器值 Hi 00 输出值 Hi 00 寄存器值 Lo 03 输出值 Lo 03
写多个线圈(0x0F)
请求帧
设备地址 功能码(0FH) 起始地址 元件个数 字节数 (N) 写入的值No.1 ...... 写入的值No.N 校验码 H L H L
N = 元件个数/8,如果余数不等于0,那么N=N+1。
响应帧
设备地址 功能码(0FH) 起始地址 元件个数 校验码 H L H L
3. 举例
从线圈20开始写10个线圈的示例。请求的数据内容为2个字节:十六进制CD 01(二进制 1100 1101 0000 0001)。二进制安如下对应于输出。
位: 1 1 0 0 1 1 0 1 0 0 0 0 0 0 0 1 输出: 27 26 25 24 23 22 21 20 -- -- -- -- -- -- 29 28
请求 响应 字段名 16进制 字段名 16进制 功能码 0F 功能码 0F 起始地址 Hi 00 起始地址 Hi 00 起始地址 Lo 13 起始地址 Lo 13 输出数量 Hi 00 输出数量 Hi 00 输出数量 Lo 0A 输出数量 Lo 0A 字节计数 02 输出值 Hi CD 输出值 Lo 01
写多个寄存器(0x10 0x43)
请求帧
设备地址 功能码(10H) 起始地址 元件个数 (N) 字节数 (2*N) 写入的值No.1 ...... 写入的值No.N 校验码 H L H L H L H L
响应帧
设备地址 功能码(10H) 起始地址 元件个数 校验码 H L H L
3. 举例
将十六进制00 0A和01 02写入以第2个寄存器开始的两个寄存器的示例。
请求 响应 字段名 16进制 字段名 16进制 功能码 10 功能码 10 起始地址 Hi 00 起始地址 Hi 00 起始地址 Lo 01 起始地址 Lo 01 寄存器数量 Hi 00 寄存器数量 Hi 00 寄存器数量 Lo 02 寄存器数量 Lo 02 字节计数 04 寄存器值 Hi 00 寄存器值 Lo 0A 寄存器值 Hi 01 寄存器值 Lo 02
错误代码