一、MODBUS协议基础
- MODBUS简介
定位:应用层主从式通信协议(OSI L7),基于串行(RS-232/485)或以太网(TCP/IP)。
核心特点:
简单易用:协议格式简洁,适合资源受限设备。
开放免费:无授权费用,广泛支持。
主从架构:一个主站(Master)轮询多个从站(Slave)。
版本类型:
MODBUS RTU:二进制格式,基于RS-485(常用)。
MODBUS ASCII:ASCII字符格式(较少使用)。
MODBUS TCP:基于以太网(IP地址+端口502)。
-
数据模型
-
协议帧格式
MODBUS RTU帧:
plaintext
| 地址(1B) | 功能码(1B) | 数据(N B) | CRC(2B) |
CRC校验:16位循环冗余校验(多项式0x8005)。
MODBUS TCP帧:
plaintext
| 事务ID(2B) | 协议标识(0x0000) | 长度(2B) | 地址(1B) | 功能码(1B) | 数据(N B) |
事务ID:用于匹配请求与响应。
二、MODBUS通信配置
- 硬件连接
RS-485网络:
主站:USB转RS-485适配器(如FTDI FT232)。
从站:支持MODBUS RTU的设备(如PLC、传感器)。
布线要点:
使用双绞线,A/B线加终端电阻(120Ω)。
避免星型拓扑,推荐总线型或菊花链。
以太网网络:
主站:PC/嵌入式设备通过网口连接。
从站:支持MODBUS TCP的设备(如智能电表)。
- 参数配置
三、MODBUS功能码详解
-
常用功能码
-
请求与响应示例
① 读保持寄存器(功能码0x03)
主站请求:
plaintext
地址: 0x01
功能码: 0x03
起始地址: 0x0000 (40001)
寄存器数量: 0x0002
CRC: 0xC40B
完整帧: 01 03 00 00 00 02 C4 0B
从站响应:
plaintext
地址: 0x01
功能码: 0x03
数据长度: 0x04
数据: 0x1234 0x5678
CRC: 0xABCD
完整帧: 01 03 04 12 34 56 78 AB CD
② 写单个线圈(功能码0x05)
主站请求:
plaintext
地址: 0x01
功能码: 0x05
线圈地址: 0x0001 (00002)
值: 0xFF00 (ON)
CRC: 0x8C3A
完整帧: 01 05 00 01 FF 00 8C 3A
从站响应:
p
laintext
地址: 0x01
功能码: 0x05
线圈地址: 0x0001
值: 0xFF00
CRC: 0x8C3A
完整帧: 01 05 00 01 FF 00 8C 3A
四、代码实现(基于STM32 + FreeMODBUS)
- FreeMODBUS从站配置
c
// 初始化Modbus从站(RTU)
#include "mb.h"
#include "mbrtu.h"
#define SLAVE_ADDR 0x01 // 从站地址
#define PORT_NUM 1 // 串口号(USART1)
int main() {
eMBInit(MB_RTU, SLAVE_ADDR, PORT_NUM, 9600, MB_PAR_NONE);
eMBEnable();
while (1) {
eMBPoll(); // 处理Modbus请求
}
}
// 回调函数:处理保持寄存器读写
eMBErrorCode eMBRegHoldingCB(UCHAR *pucRegBuffer, USHORT usAddress,
USHORT usNRegs, eMBRegisterMode eMode) {
if (eMode == MB_REG_READ) {
// 读取保持寄存器(示例:返回固定值)
for (int i = 0; i < usNRegs; i++) {
pucRegBuffer[i*2] = 0x12;
pucRegBuffer[i*2+1] = 0x34;
}
} else if (eMode == MB_REG_WRITE) {
// 写入保持寄存器(示例:存储数据)
memcpy(&hr_registers[usAddress], pucRegBuffer, usNRegs * 2);
}
return MB_ENOERR;
}
- MODBUS TCP主站(Python示例)
python
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient('192.168.1.100', port=502)
client.connect()
读取保持寄存器(地址40001,长度2)
response = client.read_holding_registers(0, 2, unit=0x01)
if not response.isError():
print("Registers:", response.registers)
else:
print("Error:", response)
写入单个寄存器(地址40001,值0x1234)
client.write_register(0, 0x1234, unit=0x01)
client.close()
五、调试与故障排查
-
常见问题
-
调试工具
MODBUS Poll/Master(Windows工具):模拟主站发送请求。
MODBUS Slave(从站模拟器):测试主站功能。
Wireshark + MODBUS插件:抓包分析MODBUS TCP通信。
USB转RS-485适配器:配合串口助手调试RTU帧。
六、MODBUS的优缺点
七、学习资源与工具推荐
协议标准:《MODBUS Application Protocol Specification》
开发库:
FreeMODBUS(C语言,嵌入式从站)。
pymodbus(Python主/从站)。
ModbusTool(Java跨平台工具)。
硬件工具:
USR-TCP232(MODBUS TCP转RTU网关)。
ADI Trinamic TMCM-1276(集成MODBUS的步进驱动模块)。
总结
MODBUS以其简洁性和高兼容性,成为工业通信领域的“通用语言”。在嵌入式开发中,通过FreeMODBUS等库可快速实现从站功能;在高级应用中,结合TCP/IP扩展其适用场景。调试时需重点排查物理层问题(如RS-485接线),并注意地址映射规则。对于高安全性或实时性需求,可考虑结合加密模块或升级为MODBUS over TLS等变种协议