协议描述
MODBUS 协议定义了一个与基础通信层无关的简单协议数据单元(PDU,Protocol Data Unit)。特定总线或网络上的MODBUS 协议映射能够在应用数据单元(ADU)上引入一些附加域。
- 启动MODBUS 事务处理的客户机创建MODBUS应用数据单元,功能码向服务器指示将执行哪种操作。
- 客户机向服务器设备发送的报文数据域包括附加信息,服务器使用这个信息执行功能码定义的操作。这个域还包括离散项目和寄存器地址、处理的项目数量以及域中的实际数据字节数。
- 在某种请求中,数据域可以是不存在的(0长度),在此情况下服务器不需要任何附加信息。功能码仅说明操作。
- 如果在一个正确接收的MODBUS ADU 中,不出现与请求MODBUS 功能有关的差错,那么服务器至客户机的响应数据域包括请求数据。如果出现与请求MODBUS 功能有关的差错,那么域包括一个异常码,服务器应用能够使用这个域确定下一个执行的操作。
- 当服务器对客户机响应时,它使用功能码域来指示正常(无差错)响应或者出现某种差错(称为异常响应)。对于一个正常响应来说,服务器仅对原始功能码响应。
- 对于异常响应,服务器返回一个与原始功能码等同的码,设置该原始功能码的最高有效位为逻辑1。
PDU
MODBUS 协议定义了三种PDU。它们是:
• MODBUS请求PDU,mb_req_pdu
• MODBUS响应PDU,mb_rsp_pdu
• MODBUS异常响应PDU,mb_excep_rsp_pdu
mb_req_pdu
mb_req_pdu = { function_code, request_data},其中
function_code - [1个字节] ,功能码
request_data - [n个字节],这个域与功能码有关,并且通常包括诸如可变参考、变量、数据偏移量、子功能码等信息。mb_rsp_pdu
mb_rsp_pdu = { function_code, response_ data},其中
function_code - [1个字节],功能码
response_data - [n个字节],这个域与功能码有关,并且通常包括诸如可变参考、变量、数据偏移量、子功能码等信息。mb_excep_rsp_pdu
mb_excep_rsp_pdu = { function_code, request_data},其中
function_code - [1个字节],功能码+ 0x80
exception_code - [1个字节],异常码。
数据模型
基本表格 | 对象类型 | 访问类型 | 内容 |
离散量输入 | 1 bit | 只读 | 读取服务器端位状态 |
线圈 | 1 bit | 读写 | 读、写服务器端位状态 |
输入寄存器 | 16 bits | 只读 | 读取服务器端寄存器 |
保持寄存器 | 16 bits | 读写 | 读、写服务器端寄存器 |
通常使用较多的是输入寄存器、保持寄存器。
举栗子🌰
测试说明:STM32开发板作为Modbus主机,使用Modbus Slave软件模拟从机,分别测试保持寄存器、输入寄存器、线圈、离散量的读写操作。
HoldingReg.mbs:保持寄存器
InputReg.mbs:输入寄存器
Coils:线圈
Input:输入离散量
结合数据帧的数据与该图对照,了解各数据模型是如何进行读写操作的。
数据帧的数据,即是开发板与Modbus Slave仿真软件之间的测试数据,对从机四种数据模型的读写测试。
读取到的从机数据打印出来,写数据直接通过Modbus Slave仿真软件查看
保持寄存器
写单个保持寄存器
客户端:01 06 00 01 00 4C D9 FF
服务器:01 06 00 01 00 4C D9 FF
客户端发送数据 | 分析 | 服务器发送数据 | 分析 |
01 | 从机地址 | 01 | 本机地址 |
06 | 写单个保持寄存器 | 06 | 原功能码 |
00 01 | 保持寄存器地址 | 00 01 | 原地址 |
00 4C | 写入保持寄存器的数据 | 00 4C | 原数据 |
D9 FF | CRC校验 | D9 FF | CRC校验 |
客户端请求向地址为1的服务器写保持寄存器,保持寄存器的地址为1,写入的数据为0x004C
写多个保持寄存器
客户端:01 10 00 02 00 02 04 00 6F 00 DE C2 33
服务器:01 10 00 02 00 02 E0 08
客户端发送数据 | 分析 | 服务器发送数据 | 分析 |
01 | 从机地址 | 01 | 本机地址 |
10 | 写多个保持寄存器 | 10 | 原功能码 |
00 02 | 保持寄存器地址 | 00 02 | 原地址 |
00 02 | 保持寄存器数量 | 00 02 | 原数量 |
04 | 数据域长度 | E0 08 | CRC校验 |
00 6F | 写入地址为2的保持寄存器的数据111 | ||
00 DE | 写入地址为3的保持寄存器的数据222 | ||
C2 33 | CRC校验 |
读多个保持寄存器
客户端:01 03 00 04 00 02 85 CA
服务器:01 03 04 01 4D 01 BC 6B F9
客户端发送数据 | 分析 | 服务器发送数据 | 分析 |
01 | 从机地址 | 01 | 本机地址 |
03 | 读多个保持寄存器 | 03 | 原功能码 |
00 04 | 读地址为4开始的保持寄存器 | 04 | 数据域长度 |
00 02 | 读地址为4开始的2个保持寄存器 | 01 4D | 地址为4的保持寄存器值333 |
85 CA | CRC校验 | 01 BC | 地址为5的保持寄存器值444 |
6B F9 | CRC校验 |
读写多个保持寄存器
客户端:01 17 00 06 00 02 00 08 00 02 04 03 78 03 E7 0E 09
服务器:01 17 04 02 2B 02 9A 09 9C
客户端发送数据 | 分析 | 服务端发送数据 | 分析 |
01 | 从机地址 | 01 | 本机地址 |
17 | 读写多个保持寄存器 | 17 | 原功能码 |
00 06 | 读地址为6开始的保持寄存器 | 04 | 数据域长度 |
00 02 | 读地址为6开始的2个保持寄存器 | 02 2B | 地址为6的保持寄存器值555 |
00 08 | 写地址为8开始的保持寄存器 | 02 9A | 地址为7的保持寄存器值666 |
00 02 | 写地址为8开始的2个保持寄存器 | ||
04 | 数据域长度4 | ||
03 78 | 写入地址为8的保持寄存器的数据888 | ||
03 E7 | 写入地址为9的保持九年起的数据999 | ||
0E 09 | CRC校验 |
线圈、离散量、输入寄存器与保持寄存器大同小异。
Modbus资料大全
笔者将Modbus 主机、从机协议完整资料整理如下:
文件 | 说明 |
freemodbus-v1.6.zip | FreeModbusV1.6源码 |
FreeModbusMasterSlave(Rev1.0.0).zip | 笔者移植好测试通过STM32+FreeRTOS+FreeModbus Master Slave代码 |
ModbusSlave 7.0和ModbusPoll_7.0软件注册码.zip | FreeModbus Master Slave调试工具 |
FreeModbus V1.6 主机使用说明.md | FreeModbus 主机使用说明文档 |
FreeModbus 从机流程图.vsd | FreeModbus 从机流程图 |
FreeModbus 主机流程图.vsd | FreeModbus 主机流程图 |
Modbus应用协议.doc | 笔者整理的 FreeModbus 协议文档 |
FreeModbus Datasheet | 笔者搜集 FreeModbus 官方协议文档 |
上面的数据,均来自以下资料内的测试工程,Modbus Slave的设置参照上面的图即可。