一.Modbus简介
Modbus是一种串行通信协议,是Modicon公司(现在的施耐德电气 Schneider Electric)于1979年为使用可编程逻辑控制器(PLC)通信而发表。Modbus已经成为工业领域通信协议的业界标准(De facto),并且现在是工业电子设备之间常用的连接方式。
二.Modbus-Rtu报文格式
设备地址 | 功能码 | 数据区 | CRC校验 |
---|---|---|---|
1个字节 | 1个字节 | N个字节 | 2个字节(16位循环冗余校验码) |
注:1 个字节由 8 位二进制组成,即 8 bits。
2.1设备地址
设备地址是每次通讯信息帧的第一个字节,从0-255。这个字节表明由用户设置为该地址的设备将接收由主站发过来的此条消息,每个设备必须有一个唯一的地址,只有符合这个地址的设备才能响应主站回送信息。当从机回送信息时,回送数据的第一个字节也是这个设备的地址
主站发送的数据当中的设备地址表明将要发送到哪个设备,设备返回的数据当中的设备地址表明此数据来自何处。
2.2功能码
功能码是每次通讯的数据的第二个字节,MODBUS 通讯规约可以定义的功能码的范围为 1 到 127,我们仅采用了其中一部分功能码,具体如下:
功能码 | 定义 | 描述 |
---|---|---|
01 | 读开关 | 读取一路或多路开关的状态 |
03 | 读寄存器 | 读取一个或多个寄存器(模拟量)数据 |
05 | 写单路开关 | 控制一路开关的分或合 |
06 | 写单个寄存器 | 写入一个寄存器(模拟量)数据 |
0F | 写多路开关 | 控制多路开关的分或合 |
10 | 写多个寄存器 | 写入多个寄存器(模拟量)数据 |
2.3数据区
数据区是主站要写给从站的数据和从站回复主站要读的数据
2.4CRC校验
CRC校验是16位循环冗余校验码,主要用来校验传输数据的准确性
/*********************************************************************************************************/
因为本次商量采用读写寄存器的方法来进行控制。所以暂时不考虑读写开关操作。
本次只考虑03、06、10功能码
/*********************************************************************************************************/
三.功能码详解
3.1功能码03:读寄存器
每个寄存器都是两个字节 (16 位二进制数据),高位字节在前,低位字节在后。每个寄存器表示的数据 范围为-32768 到 32767,负数用补码 (two’s complement) 表示。
寄存器的地址编码,可以理解为地址为 0 的寄存器在数据区的第 1 个和第 2 个字节,地址为 1 的寄存 器在数据区的第 3 个和第 4 个字节,地址为 2 的寄存器在数据区的第 5 个和第 6 个字节,以此类推。
主机发送报文格式:
格式 | 长度 | 作用 |
设备地址 | 1个字节 | 设备地址 |
功能码 | 1个字节 | 03:读寄存器 |
起始地址 | 2个字节 | 从哪个地址的寄存器开始读数据 |
寄存器个数 | 2个字节 | 读几个寄存器的数据(字节数=寄存器个数x2) |
CRC校验码 | 2个字节 | 设备地址、功能码、起始地址、寄存器个数的CRC校验码 |
从机返回数据报文格式:
格式 | 长度 | 作用 |
设备地址 | 1个字节 | 设备地址 |
功能码 | 1个字节 | 03:读寄存器 |
数据字节数N | 1个字节 | 数据字节数N=寄存器个数x2 |
寄存器数据 | N个字节 | 寄存器个数=数据字节数÷2 返回的第一个字节和第二个字节是第一个 (起始地址) 的寄存器数据 返回的第三个字节和第四个字节是第二个 (起始地址+1) 的寄存器数据 |
CRC校验码 | 2个字节 | 设备地址、功能码、起始地址、寄存器个数的CRC校验码 |
3.2功能码06:写单个寄存器
主机发送报文格式:
格式 | 长度 | 作用 |
设备地址 | 1个字节 | 设备地址 |
功能码 | 1个字节 | 06:写单个寄存器 |
寄存器地址 | 2个字节 | 把数据写入哪个寄存器 |
写入的数据 | 2个字节 | 写入寄存器的数据 |
CRC校验码 | 2个字节 | 设备地址、功能码、寄存器地址、写入数据的CRC校验码 |
从机返回数据报文格式:
从机返回的报文与主机发送的报文完全相同。
从机返回这个报文,说明装置接受了写入寄存器的命令, 开始执行命令,判断是否成功的执行完成了写入数据,要以读寄存器的数据等于写入的值为准, 即读出的寄存器数据等于写入的寄存器数据,认为写入执行成功的完成了。
3.3功能码10:写多个寄存器
主机发送报文格式:
格式 | 长度 | 作用 |
设备地址 | 1个字节 | 设备地址 |
功能码 | 1个字节 | 10:写多个寄存器 |
起始地址 | 2个字节 | 从哪个地址的寄存器开始写入 |
寄存器个数 | 2个字节 | 对几个寄存器进行写入 |
数据字节N | 1个字节 | 写入寄存器的数据的字节数,即接下来的遥调命令的字节数 |
写入的数据 | N个字节 | 写入的第一个字节和第二个字节是第一个 (起始地址) 的寄存器数据 写入的第三个字节和第四个字节是第二个 (起始地址+1) 的寄存器数据 |
CRC校验码 | 2个字节 | 设备地址、功能码、起始地址、寄存器个数、字节数、数据的 CRC 校验码 |
从机返回数据报文格式:
格式 | 长度 | 作用 |
设备地址 | 1个字节 | 设备地址 |
功能码 | 1个字节 | 10:写多个寄存器 |
起始地址 | 2个字节 | 从哪个地址的寄存器开始写入 |
寄存器个数 | 2个字节 | 对几个寄存器进行写入 |
CRC校验码 | 2个字节 | 设备地址、功能码、起始地址、寄存器个数的 CRC 校验码 |
从机返回这个报文,说明从机接受了遥调命令,开始执行命令,判断是否成功的执行完成了要以读寄存 器的数据等于遥调的目标值为准,即读出的寄存器的数据等于写入寄存器的数据,认为遥调执 行成功的完成了。
/*********************************************************************************************************/
实例部分
/*********************************************************************************************************/
四.实例数据分析
4.1功能码03:读寄存器
查询地址从2到5的4个寄存器数据:
主机发送数据(HEX):08 03 00 02 00 04 E5 50
格式 | 长度 | 数据 | 描述 |
设备地址 | 1个字节 | 08 | 设备地址 |
功能码 | 1个字节 | 03 | 03:读寄存器 |
起始地址 | 2个字节 | 00 02 | 起始地址: 0002,先发高位字节 00,后发低位字节 02 |
寄存器个数 | 2个字节 | 00 04 | 读取 0004 个寄存器的数据,先发高位字节 00,后发低位字节 04 |
CRC校验码 | 2个字节 | E5 50 | 08 03 00 02 00 04 的 CRC 校验码 |
从机返回数据(HEX):08 03 08 00 0A 07 D0 00 C8 00 14 50 DF
格式 | 长度 | 数据 | 作用 |
设备地址 | 1个字节 | 08 | 设备地址 |
功能码 | 1个字节 | 03 | 03:读寄存器 |
数据字节数N | 1个字节 | 08 | 接下来有 8 个字节,即 4 个寄存器的数据 |
寄存器数据 | 8个字节 | 00 0A 07 D0 00 C8 00 14 | 因为查询命令是从地址 2 的寄存器开始查询的, 返回的第一个寄存器的数据就是地址为 2 的寄存器的数据: 00 0A: 地址为 2 的寄存器的数据 = 0x000A,即10 07 D0: 地址为 3 的寄存器的数据 = 0x07D0,即 2000 00 C8: 地址为 4 的寄存器的数据 = 0x00C8,即 200 00 14: 地址为 5 的寄存器的数据 = 0x0014,即 20 |
CRC校验码 | 2个字节 | 50 DF | 08 03 08 00 0A 07 D0 00 C8 00 14 的 CRC 校验码 |
4.2功能码06:写单个寄存器
把数据-30写入地址为8的寄存器:
主机发送数据(HEX):08 06 00 08 FF E2 C9 28
从机返回数据(HEX):08 06 00 08 FF E2 C9 28
格式 | 长度 | 数据 | 作用 |
设备地址 | 1个字节 | 08 | 设备地址 |
功能码 | 1个字节 | 06 | 06:写单个寄存器 |
寄存器地址 | 2个字节 | 00 08 | 寄存器地址:0008,先发高位字节 00,后发低位字节 08 |
写入的数据 | 2个字节 | FF E2 | 入寄存器的数据 -30 的补码为 0xFFE2,先发高位字节 FF,后发低位字节 E2 |
CRC校验码 | 2个字节 | C9 28 | 08 06 00 08 FF E2的 CRC 校验码 |
4.3功能码10:写多个寄存器
把数据 -20 写入地址为 5 的寄存器,把-3000 写入地址为 6 的寄存器,把 -300 写入地址为 7 的寄存器:
主机发送数据(HEX):08 10 00 05 00 03 06 FF EC F4 48 FE D4 9C 9B
格式 | 长度 | 数据 | 作用 |
设备地址 | 1个字节 | 08 | 设备地址 |
功能码 | 1个字节 | 10 | 10:写多个寄存器 |
起始地址 | 2个字节 | 00 05 | 起始地址:0005,先发高位字节 00,后发低位字节 05 |
寄存器个数 | 2个字节 | 00 03 | 写入 3 个寄存器的数据 |
数据字节数 | 1个字节 | 06 | 数据的字节数:6 个字节,包括 3 个寄存器的数据 |
写入的数据 | 6个字节 | FFEC F448 FE D4 | 因为写入命令是从地址 5 的寄存器开始查询的,写入的第一个寄存器的数据就是地址为 5 的寄存器的数据: FF EC: 地址为 5 的寄存器的数据 = 0xFFEC,即 -20 F4 48: 地址为 6 的寄存器的数据 = 0xF448,即 -3000 FE D4 地址为 7 的寄存器的数据 = 0xFED4,即 -300 |
CRC校验码 | 2个字节 | 9C 9B | 08 10 00 05 00 03 06 FF EC F4 48 FE D4的 CRC 校验码 |
从机返回数据(HEX):08 10 00 05 00 03 90 90
格式 | 长度 | 数据 | 作用 |
设备地址 | 1个字节 | 08 | 设备地址 |
功能码 | 1个字节 | 10 | 10:写多个寄存器 |
起始地址 | 2个字节 | 00 05 | 起始地址:0005,先发高位字节 00,后发低位字节 05 |
寄存器个数 | 2个字节 | 00 03 | 写入 3 个寄存器的数据 |
CRC校验码 | 2个字节 | 90 90 | 08 10 00 05 00 03的 CRC 校验码 |