基于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.pswp.cn/diannao/93913.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/93913.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/93913.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

想要批量提取视频背景音乐?FFmpeg 和转换器都安排上

你是否遇到过这样的情况&#xff1f;看到一个超赞的短视频&#xff0c;里面的背景音乐特别好听&#xff0c;想单独保存下来当手机铃声或收藏&#xff0c;却不知道怎么把音乐从视频里“抠”出来&#xff1f;别担心&#xff01;今天就为大家分享两种简单易行的方法&#xff0c;无…

为什么MCP协议是AI集成的未来API

一、企业AI应用的核心挑战与架构演进 当前企业AI落地面临三大核心痛点&#xff1a; ​​系统集成困境​​&#xff1a;需对接企业内部业务系统&#xff08;CRM/ERP等&#xff09;​​异构环境兼容​​&#xff1a;需整合第三方AI服务与传统API​​数据孤岛突破​​&#xff1…

Apache Tomcat样例目录session操纵漏洞解读

【漏洞名称】&#xff1a;Apache Tomcat样例目录session操纵漏洞 &#xff08;Apache Tomcat示例目录漏洞&#xff09;【漏洞等级】&#xff1a;中危&#xff0c;5.9分。【漏洞描述】Apache Tomcat默认安装页面中存在examples样例目录&#xff0c;里面存放着Servlets、JSP、Web…

Go语言实战案例:实现HTTP客户端请求并解析响应

本文是 Go 网络与并发实战系列的第2篇&#xff0c;聚焦于如何使用 Go 实现一个 HTTP 客户端&#xff0c;完成请求发送、响应解析、错误处理、Header与Body提取等完整流程。一、前言&#xff1a;为什么学习HTTP客户端&#xff1f;在日常开发中&#xff0c;无论是调用 RESTful AP…

java的冒泡排序算法

冒泡排序是一种简单的排序算法&#xff0c;通过重复遍历待排序序列&#xff0c;比较相邻元素并在必要时交换位置&#xff0c;最终实现排序。以下是Java实现的详细说明&#xff1a;核心原理‌比较相邻元素‌&#xff1a;从序列第一个元素开始&#xff0c;逐对比较相邻元素的大小…

玻尔兹曼分布与玻尔兹曼探索

目录 玻尔兹曼分布定义 玻尔兹曼探索&#xff1a; 1. 玻尔兹曼分布公式 2. 温度 T 如何影响采样结果&#xff1f; (1) 高温 (T→∞)&#xff1a; (2) 低温 (T→0)&#xff1a; (3) 中等温度 (T∈(0,∞))&#xff1a; 3. 直观示例 4. 实际应用中的意义 5.核心误区澄清…

【工具】jsDelivr CDN完全指南:免费高速的开源项目CDN服务

前言 在现代Web开发中&#xff0c;内容分发网络&#xff08;CDN&#xff09;已经成为提升网站性能的重要工具。jsDelivr作为一个免费、快速、可靠的开源CDN服务&#xff0c;为全球开发者提供了优质的静态资源分发服务。无论是加速GitHub仓库访问、分发npm包&#xff0c;还是为…

OSPF笔记整理

一、OSPF 基础特性1. 技术背景&#xff08;对比 RIP&#xff09;RIP 的缺陷&#xff1a;最大跳数 15 限制、周期性发送全路由表&#xff08;占用带宽&#xff09;、收敛慢、以跳数为度量值、易产生环路、30 秒更新间隔。OSPF 的改进&#xff1a;无跳数限制&#xff08;支持大规…

sqLite 数据库 (3):以编程方式使用 sqLite,4 个函数,以及 sqLite 移植,合并编译

&#xff08;22&#xff09; 只有四个函数 &#xff1a;以及 &#xff1a;&#xff08;23&#xff09;以及 &#xff1a;&#xff08;24&#xff09;&#xff08;25&#xff09; sqLite 的源代码很少 &#xff1a;&#xff08;26&#xff09;&#xff08;27&#xff09;&#x…

Nginx跨域问题与 MIME 类型错误深度排错指南:解决 MIME type of “application/octet-stream“ 报错

前言&#xff1a;在 Web 开发中&#xff0c;跨域请求和资源加载错误是前端工程师和运维人员经常遇到的棘手问题。本文将详细解析 Nginx 环境下跨域配置的多种方案、gzip 类型参数的优化要点&#xff0c;以及.mjs 文件 MIME 类型错误的解决方法&#xff0c;并结合排错思路和原理…

什么是大端?什么是小端?如何验证?

什么是大端&#xff1f;什么是小端&#xff1f;如何验证&#xff1f; 在计算机系统中&#xff0c;大端&#xff08;Big-Endian&#xff09; 和小端&#xff08;Little-Endian&#xff09; 是两种不同的字节序&#xff08;Byte Order&#xff09;&#xff0c;用于描述多字节数据…

JavaScript 语句和函数

1. JavaScript 语句 1&#xff09;if语句 if (condition) statement1 else statement2这里的条件&#xff08;condition&#xff09;可以是任何表达式&#xff0c;并且求值结果不一定是布尔值。 ECMAScript会自动调用Boolean()函数将这个表达式的值转换为布尔值。 如果条件…

代码随想录刷题Day22

替换数字 这道题比较简单&#xff0c;遇到字母就copy到新的字符数组&#xff0c;如果是遇到数字&#xff0c;就在新字符数组中加入number的字符串。代码如下&#xff1a; #include<stdio.h> #include<ctype.h> #include<string.h> #define Max 1000000 int…

逻辑回归参数调优实战指南

逻辑回归的参数调节参数展示 LogisticRegression(penaltyl2,dualFalse,tol1e4,C1.0,fit_interceptTrue,intercept_scaling1,class_weightNone,random_stateNone,solverliblinear,max_iter100,multi_classovr,verbose0,warm_startFalse, n_jobs1)在前面的学习中&#xff0c;我们…

cocosCreator2.4 googlePlay登录升级、API 35、16KB内存页面的支持

环境&#xff1a;我这里是cocosCreator 2.4.12 导出的android 工程 登录升级 后台收到的google 的提醒&#xff1a; 之前是通过implementation com.google.android.gms:play-services-auth:20.0.0 来获取玩家 uid 和 邮箱&#xff0c;然后发送到我们的服务器获取账号。 升级…

unity avpro实现互动影游关键问题

创建视频播放器​在Hierarchy面板中右键创建&#xff1a;Video > AVPro Video - MediaPlayer创建后会生成一个MediaPlayer对象&#xff0c;用于控制视频播放添加视频资源将视频文件放入项目的StreamingAssets文件夹下在MediaPlayer组件的设置中选择要播放的视频文件在UI上显…

【C找第一个只出现一次的字符】2022-8-18

缘由样例通过&#xff0c;请问为什么错了呢&#xff1f;(语言-c语言)-编程语言-CSDN问答 char str[100000];fgets(str, 100000, stdin);int a[26]{}, i, count 0;int len strlen(str);for (i 0; i<len; i) a[str[i] - a];for (i 0; i<len; i){if (a[str[i] - a] 1){…

MCP AI应用通信的底层机制

技术小馆专注AI与Java领域的前沿技术知识库 技术小馆官网 在AI应用快速发展的今天&#xff0c;不同AI系统之间的高效通信成为技术架构的关键挑战。MCP&#xff08;Model Context Protocol&#xff09;作为新一代AI应用通信协议&#xff0c;正在重新定义AI工具生态的构建方式。…

UI测试平台TestComplete如何实现从Git到Jenkins的持续测试

还在为手动做UI测试又慢又累发愁&#xff1f;更头痛的是&#xff0c;代码改完还得等半天才能测&#xff0c;测完了结果又散得到处都是&#xff0c;根本看不清质量全貌?TestComplete帮你搞定&#xff1a;直接连上你的Git仓库&#xff0c;代码一有动静就能感知。接着&#xff0c…

【Debian】4-‌2 Gitea搭建

【Debian】4-‌2 Gitea搭建一、准备工作二、创建 Gitea 用户&#xff08;推荐&#xff09;三、下载并安装 Gitea四、配置Gitea4-1 创建目录结构4-2 创建配置目录五、配置 Systemd 服务六、访问 Gitea Web 界面七、小插曲一、准备工作 更新系统软件为最新 sudo apt update &am…