当前位置: 代码网 > it编程>编程语言>Asp.net > 基于C#实现Modbus RTU通信

基于C#实现Modbus RTU通信

2026年03月12日 Asp.net 我要评论
一、环境配置与依赖安装# nuget包安装(支持.net framework 4.5+)install-package nmodbus4install-package system.io.ports二

一、环境配置与依赖安装

# nuget包安装(支持.net framework 4.5+)
install-package nmodbus4
install-package system.io.ports

二、核心代码实现

1. 串口初始化与连接

using system.io.ports;
using modbus.device;

public class modbusrtumaster
{
    private serialport _serialport;
    private imodbusserialmaster _master;

    public void connect(string portname, int baudrate = 9600, parity parity = parity.none, 
                       int databits = 8, stopbits stopbits = stopbits.one)
    {
        try
        {
            _serialport = new serialport(portname, baudrate, parity, databits, stopbits)
            {
                readtimeout = 3000,
                writetimeout = 3000
            };
            
            _serialport.open();
            _master = modbusserialmaster.creatertu(_serialport);
            _master.transport.retries = 3; // 设置重试次数
            _master.transport.writetimeout = 2000;
            _master.transport.readtimeout = 2000;
        }
        catch (exception ex)
        {
            console.writeline($"连接失败: {ex.message}");
            throw;
        }
    }

    public void disconnect()
    {
        _master?.close();
        _serialport?.close();
    }
}

2. 数据读取操作

public ushort[] readholdingregisters(byte slaveid, ushort startaddr, ushort count)
{
    try
    {
        return _master.readholdingregisters(slaveid, startaddr, count);
    }
    catch (modbusexception ex)
    {
        console.writeline($"modbus错误: {ex.errorcode}");
        return null;
    }
    catch (ioexception ex)
    {
        console.writeline($"通信异常: {ex.message}");
        return null;
    }
}

// 示例调用
var data = master.readholdingregisters(1, 0, 10); // 从站1读取保持寄存器0-9

3. 数据写入操作

public void writesingleregister(byte slaveid, ushort address, ushort value)
{
    _master.writesingleregister(slaveid, address, value);
}

public void writemultiplecoils(byte slaveid, ushort startaddr, bool[] values)
{
    _master.writemultiplecoils(slaveid, startaddr, values);
}

三、关键功能实现

1. crc16校验(modbus标准)

public static class crc16
{
    public static byte[] compute(byte[] data)
    {
        ushort crc = 0xffff;
        foreach (byte b in data)
        {
            crc ^= (ushort)b;
            for (int i = 0; i < 8; i++)
            {
                if ((crc & 0x0001) != 0)
                {
                    crc >>= 1;
                    crc ^= 0xa001;
                }
                else
                {
                    crc >>= 1;
                }
            }
        }
        return new[] { (byte)crc, (byte)(crc >> 8) };
    }

    public static bool validate(byte[] datawithcrc)
    {
        if (datawithcrc.length < 2) return false;
        byte[] data = datawithcrc.take(datawithcrc.length - 2).toarray();
        byte[] crc = compute(data);
        return crc[0] == datawithcrc[datawithcrc.length - 2] 
            && crc[1] == datawithcrc[datawithcrc.length - 1];
    }
}

2. 帧间延迟计算

private int calculateinterframedelay()
{
    int charbits = 1 + _serialport.databits + 
                  (_serialport.stopbits == stopbits.one ? 1 : 2) + 
                  (_serialport.parity == parity.none ? 0 : 1);
    return (int)(3500.0 * charbits / _serialport.baudrate); // 3.5字符时间
}

四、错误处理与调试

1. 异常处理策略

try
{
    var data = readholdingregisters(1, 0, 10);
    if (data == null) throw new invalidoperationexception("读取失败");
}
catch (timeoutexception)
{
    console.writeline("通信超时,请检查设备状态");
    reconnect();
}
catch (invalidoperationexception ex)
{
    console.writeline($"操作失败: {ex.message}");
}

2. 自动重连机制

private void reconnect()
{
    disconnect();
    thread.sleep(1000);
    connect(_config.portname, _config.baudrate);
}

五、性能优化

1批量操作优化

// 批量读取多个寄存器区域
public dictionary<ushort, ushort[]> batchread(
    params (byte slaveid, ushort startaddr, ushort count)[] requests)
{
    var results = new dictionary<ushort, ushort[]>();
    parallel.foreach(requests, request => 
    {
        var data = readholdingregisters(request.slaveid, request.startaddr, request.count);
        lock (results) results[request.slaveid] = data;
    });
    return results;
}

2异步通信实现

public async task<ushort[]> readasync(byte slaveid, ushort startaddr, ushort count)
{
    return await task.run(() => readholdingregisters(slaveid, startaddr, count));
}

参考代码 c#利用modbus rtu模式与下位机通讯 www.youwenfan.com/contentcsr/112701.html

六、完整项目结构

modbusrtudemo/
├── src/
│   ├── modbusmaster/          // 主站核心逻辑
│   ├── serialportconfig.cs    // 串口配置管理
│   └── protocolhandler.cs     // 协议解析器
├── tests/
│   ├── modbustests.cs         // 单元测试
│   └── stresstests.cs         // 压力测试
└── docs/
    └── 开发指南.md

七、调试与测试工具

  1. 虚拟串口工具

    使用vspd创建虚拟串口对(如com3<->com4),方便调试

  2. wireshark抓包分析

    过滤modbus rtu协议,观察完整的请求/响应帧结构

  3. modbus从站模拟

    使用modbus slave工具创建测试从站设备

八、扩展应用场景

1.多从站管理

public class modbusnetwork
{
    private dictionary<byte, modbusrtumaster> _slaves = new();
    
    public void addslave(byte address, string portname)
    {
        var master = new modbusrtumaster();
        master.connect(portname);
        _slaves[address] = master;
    }
}

2.数据缓存机制

public class datacache
{
    private dictionary<ushort, (datetime timestamp, ushort value)[]> _cache = new();
    
    public void updatecache(ushort[] data, ushort startaddr)
    {
        _cache[startaddr] = data.select((v, i) => 
            (datetime.now, v)).toarray();
    }
}

九、最佳实践建议

参数配置规范

  • 波特率:9600/19200/115200(根据设备手册选择)
  • 数据格式:8n1(默认配置)
  • 超时时间:读操作1000ms,写操作500ms

安全防护措施

  • 添加设备认证机制
  • 实现数据加密传输
  • 设置访问权限控制

到此这篇关于基于c#实现modbus rtu通信的文章就介绍到这了,更多相关c# modbus rtu通信内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com