ModbusTCP批量写入寄存器的完整实现方案
-
核心批量写入方法
以下是使用NModbus库实现ModbusTCP批量写入的完整代码实现
public async Task<bool> WriteMultipleRegistersAsync( byte slaveAddress, ushort startAddress, ushort[] values, int maxRetries = 3) { try { await _semaphore.WaitAsync(); return await _modbusMaster.WriteMultipleRegistersAsync( slaveAddress, startAddress, values); } catch (Exception ex) when (maxRetries > 0) { await Task.Delay(TimeSpan.FromSeconds(1)); return await WriteMultipleRegistersAsync( slaveAddress, startAddress, values, maxRetries - 1); } finally { _semaphore.Release(); } } -
数据分块处理策略
Modbus协议限制单次最多写入123个寄存器,需实现分块写入逻辑
public async Task BatchWriteRegistersAsync(
byte slaveAddress,
ushort startAddress,
ushort[] values)
{
const int maxRegistersPerWrite = 123;
int offset = 0;while (offset < values.Length) {
int count = Math.Min(maxRegistersPerWrite, values.Length - offset);
var chunk = new ushort[count];
Array.Copy(values, offset, chunk, 0, count);bool success = await WriteMultipleRegistersAsync( slaveAddress, (ushort)(startAddress + offset), chunk); if (!success) { throw new InvalidOperationException( $"批量写入失败 at address {startAddress + offset}"); } offset += count;}
} -
带校验的增强实现
增加写入后读取验证机制确保数据一致性
`public async TaskVerifiedBatchWriteAsync(
byte slaveAddress,
ushort startAddress,
ushort[] values)
{
// 执行批量写入
await BatchWriteRegistersAsync(slaveAddress, startAddress, values);// 延迟确保设备处理完成
await Task.Delay(50);// 读取验证
var readValues = await _modbusMaster.ReadHoldingRegistersAsync(
slaveAddress,
startAddress,
(ushort)values.Length);// 逐寄存器校验
for (int i = 0; i < values.Length; i++) {
if (readValues[i] != values[i]) {
throw new ModbusWriteException(
$"寄存器{startAddress + i}校验失败,期望:{values[i]} 实际:{readValues[i]}");
}
}return true;
}
` -
并发安全实现
使用连接池和对象池优化高并发场景
`public class ModbusTcpPooledService : IAsyncDisposable
{
private readonly ObjectPool_masterPool; public ModbusTcpPooledService(string ip, int port)
{
var policy = new MasterPooledObjectPolicy(ip, port);
_masterPool = new DefaultObjectPool(policy);
}public async Task BatchWriteWithPoolAsync(
byte slaveAddress,
ushort startAddress,
ushort[] values)
{
var master = _masterPool.Get();
try {
await master.WriteMultipleRegistersAsync(
slaveAddress,
startAddress,
values);
}
finally {
_masterPool.Return(master);
}
}
}
class MasterPooledObjectPolicy : IPooledObjectPolicy
{
private readonly string _ip;
private readonly int _port;
public MasterPooledObjectPolicy(string ip, int port)
{
_ip = ip;
_port = port;
}
public IModbusMaster Create()
{
var client = new TcpClient(_ip, _port);
return ModbusIpMaster.CreateIp(client);
}
public bool Return(IModbusMaster obj)
{
return obj.Transport?.Connected ?? false;
}
}
`
5. 完整集成示例
将各组件集成到实际应用中
public class ModbusTcpWriter
{
private readonly ModbusTcpService _modbusService;
private readonly ILogger _logger;
public ModbusTcpWriter(string ip, int port, ILogger logger)
{
_modbusService = new ModbusTcpService();
_logger = logger;
_modbusService.InitializeAsync(ip, port).Wait();
}
public async Task ProcessBatchMessagesAsync(
IEnumerable<ModbusWriteCommand> commands)
{
var groupedCommands = commands
.GroupBy(c => new { c.SlaveAddress, c.StartAddress });
foreach (var group in groupedCommands) {
try {
var values = group.Select(c => c.Value).ToArray();
await _modbusService.VerifiedBatchWriteAsync(
group.Key.SlaveAddress,
group.Key.StartAddress,
values);
_logger.LogInformation(
$"成功写入{values.Length}个寄存器到从站{group.Key.SlaveAddress}");
}
catch (Exception ex) {
_logger.LogError(ex,
$"批量写入从站{group.Key.SlaveAddress}失败");
throw;
}
}
}
}
public record ModbusWriteCommand(
byte SlaveAddress,
ushort StartAddress,
ushort Value);
总结:该实现方案包含完整的批量写入功能、错误处理、数据校验和性能优化措施,可直接用于工业自动化控制系统

浙公网安备 33010602011771号