当前位置: 首页 > news >正文

基于C#和NModbus4库实现的Modbus RTU串口通信

基于C#和NModbus4库实现的Modbus RTU串口通信,包含完整的界面设计和功能实现:


一、项目依赖配置

  1. NuGet包安装

    Install-Package NModbus4
    Install-Package System.IO.Ports
    
  2. 窗体控件布局

    <!-- 基础控件配置 -->
    <ComboBox x:Name="cmbPort" Margin="5" Width="120"/>
    <Button x:Name="btnConnect" Content="连接" Margin="5"/>
    <Button x:Name="btnRead" Content="读取寄存器" Margin="5"/>
    <TextBox x:Name="txtLog" Height="200" Margin="5" TextWrapping="Wrap"/>
    <DataGrid x:Name="dgData" AutoGenerateColumns="False" Margin="5"><DataGrid.Columns><DataGridTextColumn Header="地址" Binding="{Binding Address}"/><DataGridTextColumn Header="" Binding="{Binding Value}"/></DataGrid.Columns>
    </DataGrid>
    

二、核心代码实现

using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Windows;
using Modbus.Device;namespace ModbusRTUDemo
{public partial class MainWindow : Window{#region 成员变量private IModbusSerialMaster _master;private SerialPort _serialPort;private const ushort START_ADDR = 40001; // 起始寄存器地址private const ushort READ_COUNT = 10;    // 读取数量#endregionpublic MainWindow(){InitializeComponent();InitializeSerialPorts();btnConnect.Click += BtnConnect_Click;btnRead.Click += BtnRead_Click;}#region 串口初始化private void InitializeSerialPorts(){var ports = SerialPort.GetPortNames();cmbPort.ItemsSource = ports;cmbPort.SelectedIndex = 0;}#endregion#region 连接控制private void BtnConnect_Click(object sender, RoutedEventArgs e){try{if (_master != null && _master.IsOpen){Disconnect();btnConnect.Content = "连接";txtLog.AppendText("已断开连接\n");return;}_serialPort = new SerialPort(cmbPort.Text, 9600, Parity.None, 8, StopBits.One){ReadTimeout = 3000,WriteTimeout = 3000};_master = ModbusSerialMaster.CreateRtu(_serialPort);_master.Transport.Retries = 3; // 重试次数_master.Transport.WriteTimeout = 2000;_master.Transport.ReadTimeout = 2000;_master.Open();btnConnect.Content = "断开";txtLog.AppendText($"已连接到 {_serialPort.PortName}\n");}catch (Exception ex){txtLog.AppendText($"连接失败: {ex.Message}\n");}}#endregion#region 数据读取private async void BtnRead_Click(object sender, RoutedEventArgs e){try{var result = await Task.Run(() => _master.ReadHoldingRegisters(1, START_ADDR, READ_COUNT));dgData.ItemsSource = result.Select((value, index) => new {Address = START_ADDR + index,Value = value.ToString("0.00")}).ToList();txtLog.AppendText($"读取成功: {result.Length} 个寄存器\n");}catch (Exception ex){txtLog.AppendText($"读取失败: {ex.Message}\n");}}#endregion#region 连接管理private void Disconnect(){_master?.Close();_master = null;_serialPort?.Close();}protected override void OnClosed(EventArgs e){base.OnClosed(e);Disconnect();}#endregion}
}

参考代码 C# 写的串口通信程序源码 youwenfan.com/contentcsb/111840.html

三、关键功能说明

  1. 串口配置
    • 支持自动检测可用串口(通过SerialPort.GetPortNames()
    • 默认参数:9600波特率、无校验、8数据位、1停止位
  2. Modbus操作
    • 读取保持寄存器ReadHoldingRegisters方法实现
    • 写单个寄存器:扩展方法WriteSingleRegister
    • 批量写线圈WriteMultipleCoils方法
  3. 异常处理
    • 自动重试机制(默认3次重试)
    • 超时设置(读写各2秒)

四、扩展功能实现

  1. 定时数据采集

    private System.Timers.Timer _pollTimer = new System.Timers.Timer(5000);private void StartPolling()
    {_pollTimer.Elapsed += (s,e) => {var data = _master.ReadHoldingRegisters(1, START_ADDR, READ_COUNT);Dispatcher.Invoke(() => UpdateDataGrid(data));};_pollTimer.Start();
    }
    
  2. CRC校验实现

    private byte[] CalculateCRC(byte[] data)
    {ushort crc = 0xFFFF;for (int i = 0; i < data.Length; i++){crc ^= (ushort)data[i];for (int j = 0; j < 8; j++){if ((crc & 0x0001) != 0){crc >>= 1;crc ^= 0xA001;}else{crc >>= 1;}}}return new byte[] { (byte)crc, (byte)(crc >> 8) };
    }
    

五、调试技巧

  1. 串口监控
    使用虚拟串口工具(如VSPD)进行通信调试

  2. 数据验证

    // 校验从站响应
    if (response.SlaveId != slaveId) throw new InvalidDataException("从站ID不匹配");
    
  3. 协议分析
    通过Wireshark抓包分析Modbus RTU帧结构


完整项目源码可通过NuGet部署NModbus4库后导入Visual Studio运行。实际应用中需根据设备手册调整功能码和寄存器地址。

http://www.lryc.cn/news/607053.html

相关文章:

  • ansible简单playbook剧本例子2
  • 团购商城 app 系统架构分析
  • 第三篇:几何体入门:内置几何体全解析
  • 无人机气象监测设备:穿梭云端的 “气象观察员”
  • 丝杆支撑座在电子装配中的关键作用
  • NLP 和 LLM 区别、对比 和关系
  • 深入剖析Spring IOC容器——原理、源码与实践全解析
  • mac系统自带终端崩溃修复
  • PAT 1022 Digital Library
  • 关于“PromptPilot” 之5 -标签词与标签动作的语言模型九宫格
  • HCLP--ospf综合实验
  • 神经网络----卷积层(Conv2D)
  • GitPython07-源码解读
  • 低通滤波器的原理以及作用
  • ctfshow_web签到题
  • 算法49. 字母异位词分组
  • 第11届蓝桥杯Python青少组中/高级组选拔赛(STEMA)2020年5月30日真题
  • Pydantic模块学习
  • gis qgis验证 tif地图文件
  • 10年24倍的etf轮动策略复现,回测+实盘一体解决方案:backtrader的模块化策略模板,附python代码
  • 机器学习第二课之逻辑回归(二)LogisticRegression
  • Spring事件监听设计原理全面深入指南
  • 3D 管道如何实现流动的?
  • Java试题-选择题(3)
  • python简单操作达梦数据库
  • VUE2 学习笔记15 代理
  • Leetcode 10 java
  • Go语言中的盲点:竞态检测和互斥锁的错觉
  • 常见的网络攻击以及预防
  • C++ 构造函数语义学