C#modbus rtu读取单个寄存器
时间: 2025-06-08 13:36:33 浏览: 23
### C# Modbus RTU 读取单个寄存器
为了使用C#通过Modbus RTU协议读取单个寄存器,可以基于现有的库或自行构建通信逻辑。下面提供了一种实现方式,其中包含了创建请求帧、计算校验和以及解析响应的过程。
#### 创建请求消息并发送给目标设备
当需要读取特定地址上的单个保持寄存器时,应构造一个遵循Modbus标准的消息格式的数据包。对于功能码`03`(即读取保持寄存器),此操作涉及指定起始地址和数量为1的寄存器数:
```csharp
public class ModbusMaster
{
private SerialPort _serialPort;
public void Initialize(string portName, int baudRate)
{
_serialPort = new SerialPort(portName, baudRate);
_serialPort.Open();
}
/// <summary>
/// 构建用于读取单个寄存器的功能码03命令报文
/// </summary>
/// <param name="slaveAddress">从站地址</param>
/// <param name="registerAddress">要读取的寄存器地址(十六进制)</param>
/// <returns>完整的Modbus RTU请求字节数组</returns>
public byte[] BuildReadSingleRegisterRequest(int slaveAddress, ushort registerAddress)
{
List<byte> requestBytes = new List<byte>();
// 添加从机地址
requestBytes.Add((byte)slaveAddress);
// 功能码03表示读取保持寄存器
const byte functionCode = 0x03;
requestBytes.Add(functionCode);
// 起始地址高位低位拆分
requestBytes.AddRange(BitConverter.GetBytes(registerAddress).Reverse());
// 寄存器数量设为1
requestBytes.AddRange(new byte[] { 0x00, 0x01 });
// 计算CRC校验值并附加到请求末尾
var crcResult = CRC16(requestBytes.ToArray());
requestBytes.AddRange(crcResult);
return requestBytes.ToArray();
}
}
```
上述代码片段展示了如何准备一条针对某个具体寄存器执行查询的操作指令[^2]。
#### 接收来自远程设备的回复
一旦发出请求之后,程序会等待接收到来自被控端返回的信息流,并对其进行处理来提取实际存储于所选寄存器内的数值:
```csharp
/// <summary>
/// 发送读取单个寄存器的请求并获取结果
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public short ReadSingleRegister(byte[] request)
{
try
{
// 将构建好的请求发送出去
_serialPort.Write(request, 0, request.Length);
Thread.Sleep(50); // 短暂延时以确保数据传输完成
// 假定最大可能接收到9个字节作为回应
byte[] responseBuffer = new byte[9];
int bytesReadCount = _serialPort.Read(responseBuffer, 0, responseBuffer.Length);
if (bytesReadCount >= 5 && ValidateResponseChecksum(responseBuffer))
{
// 解析有效载荷部分得到寄存器中的值
Array.Reverse(responseBuffer, 3, 2);
return BitConverter.ToInt16(responseBuffer, 3);
}
throw new Exception("Invalid or corrupted message received.");
}
catch (Exception ex)
{
Console.WriteLine($"Error occurred while reading single register: {ex.Message}");
throw;
}
}
private bool ValidateResponseChecksum(byte[] responseData)
{
// 验证除最后两个字节外的内容与传回的CRC相匹配
byte[] calculatedChecksum = CRC16(responseData.Take(responseData.Length - 2).ToArray());
return calculatedChecksum.SequenceEqual(responseData.Skip(responseData.Length - 2));
}
```
这段示例说明了怎样对接收到的数据进行验证及其后续转换成可理解的形式[^1]。
#### 辅助函数:CRC16算法实现
由于Modbus RTU采用CRC-16校验机制保障通讯质量,在每次组装新消息前都需要调用相应的方法来进行必要的错误检测编码工作:
```csharp
// 定义静态辅助类中的CRC16方法
public static class HelperFunctions
{
public static byte[] CRC16(byte[] data)
{
int len = data.Length;
if (len > 0)
{
ushort crc = 0xFFFF;
for (int i = 0; i < len; ++i)
{
crc ^= data[i];
for (int j = 0; j < 8; ++j)
crc = ((crc & 1) != 0) ? (ushort)((crc >> 1) ^ 0xA001) : (ushort)(crc >> 1);
}
byte hi = (byte)((crc & 0xFF00) >> 8);
byte lo = (byte)(crc & 0x00FF);
return new byte[] { hi, lo };
}
return new byte[] { 0, 0 };
}
}
```
以上就是关于利用C#编程语言配合串口连接实施Modbus RTU规约下单一寄存器访问行为的整体流程介绍[^3]。
阅读全文
相关推荐



















