目录
1. Modbus协议概述
Modbus是一种串行通信协议,由Modicon公司于1979年为可编程逻辑控制器(PLC)设计。作为工业领域通信协议的业界标准,Modbus已成为工业电子设备之间最常用的连接方式之一。其广泛流行的原因包括:
- 公开发表且无版税要求
- 相对容易的工业网络部署
- 对供应商修改原生位元或字节没有太多限制
Modbus协议支持多种传输模式,主要包括:
- RTU模式:使用二进制编码和CRC错误校验,通信效率高
- ASCII模式:使用ASCII字符编码和LRC错误校验,便于调试
- TCP/IP模式:基于以太网传输,使用TCP/IP协议栈
1.1 Modbus网络结构
Modbus网络是一个工业通信系统,由带智能终端的可编程序控制器和计算机通过公用线路或局部专用线路连接而成。其系统结构既包括硬件,也包括软件,可应用于各种数据采集和过程监控。
典型的Modbus网络采用主从架构:
- 一个主设备(通常为PC或HMI)
- 最多247个从设备(各种传感器、仪表、PLC等)
- 所有通信都由主设备发起,从设备被动响应
1.2 Modbus功能码
Modbus协议通过功能码定义操作类型,以下是主要功能码及其作用:
功能码 | 名称 | 作用 |
---|---|---|
01H | 读取线圈状态 | 取得一组逻辑线圈的当前状态(ON/OFF) |
02H | 读取输入状态 | 取得一组开关输入的当前状态(ON/OFF) |
03H | 读取保持寄存器 | 在一个或多个保持寄存器中取得当前的二进制值 |
04H | 读取输入寄存器 | 在一个或多个输入寄存器中取得当前的二进制值 |
05H | 强置单线圈 | 强置一个逻辑线圈的通断状态 |
06H | 预置单寄存器 | 把具体二进值装入一个保持寄存器 |
0FH | 强置多线圈 | 强置一串连续逻辑线圈的通断 |
10H | 预置多寄存器 | 把具体的二进制值装入一串连续的保持寄存器 |
16H | 掩码写入寄存器 | 使用掩码方式修改寄存器值(大部分设备不支持) |
2. Modbus RTU模式实现
2.1 RTU模式特点
RTU(Remote Terminal Unit)模式是Modbus协议中最常用的传输模式,具有以下特性:
- 采用二进制编码,传输效率高
- 使用CRC-16循环冗余校验
- 每个字节包含:1位起始位、8位数据位、1位奇偶校验位(可选)、1或2位停止位
- 报文帧以至少3.5个字符时间的静默间隔作为分隔
2.2 CRC-16校验算法
CRC(Cyclic Redundancy Check)校验是RTU模式的核心错误检测机制,其计算步骤如下:
// CRC-16校验算法实现
public static byte[] CalculateCRC(byte[] data)
{
ushort crc = 0xFFFF; // 初始化16位寄存器为全1
for(int i = 0; i < data.Length; i++)
{
crc ^= data[i]; // 高位字节与当前字节异或
for(int j = 0; j < 8; j++)
{
if((crc & 0x0001) != 0) // 检查最低位是否为1
{
crc >>= 1; // 右移一位
crc ^= 0xA001; // 与多项式A001异或
}
else
{
crc >>= 1; // 简单右移一位
}
}
}
// 返回低字节在前,高字节在后的校验码
return new byte[] { (byte)(crc & 0xFF), (byte)((crc >> 8) & 0xFF) };
}
2.3 使用NModbus4库实现RTU通信
NModbus是一个开源的.NET Modbus库,支持RTU和TCP模式。以下是使用NModbus4实现RTU通信的步骤:
- 安装NModbus4库
在Visual Studio中通过NuGet包管理器安装:
Install-Package NModbus4
- 配置串口参数
using Modbus.Device;
using System.IO.Ports;
// 创建SerialPort实例
SerialPort serialPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
serialPort.Open();
// 创建Modbus RTU主站
IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(serialPort);
// 设置从站地址
byte slaveId = 1;
// 读取保持寄存器示例 (功能码03H)
ushort startAddress = 0; // 起始地址
ushort numRegisters = 10; // 读取寄存器数量
ushort[] registers = master.ReadHoldingRegisters(slaveId, startAddress, numRegisters);
// 写入单个寄存器示例 (功能码06H)
ushort writeAddress = 0; // 写入地址
ushort value = 12345; // 写入值
master.WriteSingleRegister(slaveId, writeAddress, value);
// 关闭串口
serialPort.Close();
- 虚拟串口测试
在没有物理串口的情况下,可以使用虚拟串口工具(如Virtual Serial Port Driver)创建虚拟串口对(如COM1和COM2),然后使用Modbus Slave软件模拟从站设备进行测试。
3. Modbus TCP/IP模式实现
3.1 TCP模式特点
Modbus TCP/IP是在TCP/IP协议栈上实现的Modbus协议,具有以下特点:
- 使用标准TCP端口502
- 去掉了RTU模式中的CRC校验,改用TCP协议自身的错误检测
- 增加了MBA