ModbusTCP批量写入寄存器的完整实现方案

  1. 核心批量写入方法
    以下是使用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(); } }

  2. 数据分块处理策略
    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;
    

    }
    }

  3. 带校验的增强实现
    增加写入后读取验证机制确保数据一致性
    `public async Task VerifiedBatchWriteAsync(
    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;
    }
    `

  4. 并发安全实现
    使用连接池和对象池优化高并发场景
    `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);
总结:该实现方案包含完整的批量写入功能、错误处理、数据校验和性能优化措施,可直接用于工业自动化控制系统

posted @ 2025-07-02 18:11  匠心灵域  阅读(95)  评论(0)    收藏  举报

章节1

这里是章节1的内容

章节2

这里是章节2的内容

章节3

这里是章节3的内容

章节4

小小代码,不值一提,如果您觉得对您还有一点用,就点个赞支持一下吧。