C#读取modbus值,C#读写modbus,支持读写uint32值;Modbus TCP工具类
需要首先安装nuget包Modbus

using Modbus.Device;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using Modbus;namespace WindowsServiceMESProcessDispatchOrder
{/// <summary>/// Modbus工具类,提供Modbus TCP通信的基本操作/// </summary>/// <remarks>/// 创建时间:2025-6-25 09:10:34,作者:wanghaoli/// </remarks>public sealed class ModbusTool{/// <summary>///  超时时间,单位为毫秒 /// </summary>const int timeout = 1200;private static readonly object _obj = new object(); /// <summary>/// 下位机ip/// </summary>private static string ip = "192.168.0.50";/// <summary>///  默认端口为502,实际使用时可以根据需要修改/// </summary>private static int port = 502;/// <summary>/// 从站标识,默认为1,实际使用时可以根据需要修改/// </summary>private static byte slaveAddress = 1;/// <summary>/// 默认使用预设配置,此方法不需要调用;/// 当从站ip、端口、从站标识改变时,才需调用此方法设置新地址;/// </summary>/// <param name="_ip">下位机ip</param>/// <param name="_port">下位机端口</param>/// <param name="_slaveAddress">从站标识</param>public static void SetModbusSlaveInfo(string _ip = "192.168.0.50", int _port = 502, byte _slaveAddress = 1){ip = _ip;port = _port;slaveAddress = _slaveAddress;}/// <summary>/// 读取数据地址/// </summary>private static List<ushort> AddressReadList = new List<ushort>() {1000,1010,1012,1013,1014,1015,1020,1024,1025,1027,1028,1029,1030,1041,};/// <summary>/// 单个位置写入数据/// </summary>/// <param name="address">要写的寄存器地址,比如1000</param>/// <param name="value">写入的值</param>public static void WriteValue(ushort address, ushort value){try{using (TcpClient client = new TcpClient(ip, port)){client.ReceiveTimeout = timeout; // 设置接收超时为1秒client.SendTimeout = timeout; // 设置发送超时为1秒IModbusMaster master = ModbusIpMaster.CreateIp(client);// 写入 master.WriteSingleRegister(slaveAddress, address, value);LogHelpter.AddLog($"地址{address},写入值{value},成功");}}catch (Exception ex){LogHelpter.AddLog($"modbus访问异常:{ex.ToString()}", null, "error_modbus");}}/// <summary>/// 写入值 uint32;会从startAddress地址开始写入2个寄存器;/// 比如startAddress传参1000,则会写入1000和1001两个寄存器;  /// </summary>/// <param name="startAddress">开始地址</param>/// <param name="value">写入值,uint32</param>/// <param name="slaveId">从属机</param>public static void WriteUInt32(ushort startAddress, uint value, byte slaveId = 1){try{using (TcpClient client = new TcpClient(ip, port)){client.ReceiveTimeout = timeout; // 设置接收超时为1秒client.SendTimeout = timeout; // 设置发送超时为1秒IModbusMaster master = ModbusIpMaster.CreateIp(client);ushort highNum = (ushort)((value >> 16) & 0xFFFF);ushort lowNum = (ushort)(value & 0xFFFF);//Console.WriteLine($"位置={startAddress},uint32写入,highNum={highNum},lowNum={lowNum}");// 写入              master.WriteMultipleRegisters(slaveId, startAddress, new ushort[] { highNum, lowNum });LogHelpter.AddLog($"地址{startAddress},写入值{value},成功");//Console.WriteLine($"uint32写入成功,写入值{value}");}}catch (Exception ex){//Console.WriteLine($"WriteUInt32,modbus访问异常:{ex.ToString()}");LogHelpter.AddLog($"WriteUInt32,异常:{ex.ToString()}", null, "error_modbus");}}/// <summary>/// 读取uint32值;会从startAddress地址开始读取2个寄存器的值合并还原为一个uint32值;/// </summary>/// <param name="startAddress">读取地址</param>/// <param name="slaveId">从属机</param>/// <returns></returns>public static uint ReadValueUInt32(ushort startAddress, byte slaveId = 1){try{using (TcpClient client = new TcpClient(ip, port)){client.ReceiveTimeout = timeout; // 设置接收超时为1秒client.SendTimeout = timeout; // 设置发送超时为1秒IModbusMaster master = ModbusIpMaster.CreateIp(client);// 读取ushort[] buffer = master.ReadHoldingRegisters(slaveId, startAddress, 2);//Console.WriteLine($"读取buffer[0]={buffer[0]},1={buffer[1]}");//合并还原为uint32uint result = ((uint)buffer[0] << 16) | buffer[1];return result;}}catch (Exception ex){//Console.WriteLine($"ReadValueUInt32,modbus访问异常:{ex.ToString()}");LogHelpter.AddLog($"ReadValueUInt32,modbus访问异常:{ex.ToString()}",null, "error_modbus");}return 0;}/// <summary>/// 读取单个位置数据,并返回读取的值/// </summary>/// <param name="address">要读取的寄存器位置,比如1000</param>/// <returns></returns>public static ushort ReadValue(ushort address){try{using (TcpClient client = new TcpClient(ip, port)){client.ReceiveTimeout = timeout; // 设置接收超时为1秒client.SendTimeout = timeout; // 设置发送超时为1秒IModbusMaster master = ModbusIpMaster.CreateIp(client);master.Transport.ReadTimeout = timeout; // 设置读取超时为1秒master.Transport.WriteTimeout = timeout; // 设置写入超时为1秒//读取数据ushort[] buffer = master.ReadHoldingRegisters(slaveAddress, address, 1);ushort value = buffer.FirstOrDefault();return value;}}catch (Exception ex){LogHelpter.AddLog($"ReadValue异常:{ex.ToString()}", null, "error_modbus");}return 0;}/// <summary>/// 读取数据/// </summary>public static void TestRead(){try{using (TcpClient client = new TcpClient(ip, port)){client.ReceiveTimeout = timeout; // 设置接收超时为1秒client.SendTimeout = timeout; // 设置发送超时为1秒IModbusMaster master = ModbusIpMaster.CreateIp(client);master.Transport.ReadTimeout = timeout; // 设置读取超时为1秒master.Transport.WriteTimeout = timeout; // 设置写入超时为1秒foreach (var item in AddressReadList){//读取数据ushort[] buffer = master.ReadHoldingRegisters(slaveAddress, item, 1);ushort value = buffer.FirstOrDefault();Console.WriteLine($"读取地址{item}的数值={value}");}}}catch (Exception ex){LogHelpter.AddLog($"modbus访问异常:{ex.ToString()}", null, "error_modbus");}}/// <summary>///读取值, modbus超时控制,会在规定时间内返回/// </summary>/// <param name="address">modbus读取地址</param>/// <returns></returns>public static ushort CallReadValue(ushort address){ushort result = 0;var task = Task.Factory.StartNew(_address =>{ushort argsAddress = Convert.ToUInt16(_address);result = ReadValue(argsAddress);return result;}, address);task.Wait(timeout);//  return task.Result;return result;}/// <summary>///读取值 UInt32类型, modbus超时控制,会在规定时间内返回/// </summary>/// <param name="address">modbus读取地址</param>/// <returns></returns>public static uint CallReadValueUInt32(ushort address){uint result = 0;var task = Task.Factory.StartNew(_address =>{ushort argsAddress = Convert.ToUInt16(_address);result = ReadValueUInt32(argsAddress, slaveAddress);return result;}, address);task.Wait(timeout);return result;}/// <summary>///  写入值,modbus超时控制,会在规定时间内返回/// </summary>/// <param name="address">写入地址</param>/// <param name="value">写入值</param>public static void CallWriteValue(ushort address, ushort value){Task.Factory.StartNew(() =>{WriteValue(address, value);                  }).Wait(timeout);}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/88006.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/88006.shtml
英文地址,请注明出处:http://en.pswp.cn/web/88006.shtml

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

相关文章

Oracle注释详解

在Oracle SQL中&#xff0c;注释是用于解释代码逻辑、提高可读性的文本&#xff0c;不会被数据库执行。Oracle支持两种类型的注释语法&#xff1a; 1. 单行注释&#xff08;--&#xff09; 使用双连字符--在一行中添加注释&#xff0c;从--开始到行末的所有内容都会被视为注释。…

关于 scrapy框架 详解

scrapy 是一个纯 Python 编写的异步爬虫框架&#xff0c;具备以下特点&#xff1a;优势说明异步高效基于 Twisted&#xff0c;非阻塞 IO模块化各部分可灵活配置/替换中间件机制支持代理、UA、cookie 控制等强大的解析内置 XPath、CSS 提取器自动去重Scheduler 内部维护请求 fin…

DHCP中继实验及其核心原理

DHCP 中继&#xff08;DHCP Relay&#xff09;是一种允许跨网段分配 IP 地址的技术&#xff0c;无需在每个子网部署 DHCP 服务器。以下是其原理和配置方法的详细说明&#xff1a;一、核心原理1. 为什么需要 DHCP 中继&#xff1f;问题&#xff1a;DHCP 客户端通过广播&#xff…

ABP VNext + RediSearch:微服务级全文检索

ABP VNext RediSearch&#xff1a;微服务级全文检索 &#x1f680; &#x1f4da; 目录ABP VNext RediSearch&#xff1a;微服务级全文检索 &#x1f680;&#x1f4da; 一、背景与动机 &#x1f680;&#x1f6e0;️ 二、环境与依赖 &#x1f433;2.1 Docker Compose 启动 R…

TensorFlow深度学习实战——基于自编码器构建句子向量

TensorFlow深度学习实战——基于自编码器构建句子向量 0. 前言1. 句子向量2. 基于自编码器构建句子向量2.1 数据处理2.2 模型构建与训练 3. 模型测试相关链接 0. 前言 在本节中&#xff0c;我们将构建和训练一个基于长短期记忆 (Long Short Term Memory, LSTM) 的自编码器&…

C语言使用Protobuf进行网络通信

笔者前面博文Go语言网络游戏服务器模块化编程介绍了Go语言在开发网络游戏时如何进行模块化编程&#xff0c;在其中使用了Protobuf进行网络通信。在Protobuf官方实现中并没有生成C语言的实现&#xff0c;不过有一个开源的protobuf-c可以使用。 先来看看protobuf-c生成的代码&am…

vue3 随手笔记12--组件通信方式9/5--useAttrs

一 什么是useAttrsuseAttrs 是 Vue 3 Composition API 中提供的一个函数&#xff0c;它属于 Vue 的组合式 API 工具集的一部分。通过 useAttrs&#xff0c;你可以访问传递给组件但未被声明为 props 的所有属性。这对于处理非 prop 特性&#xff08;attributes&#xff09;特别有…

HumanRisk-自动化安全意识与合规教育平台方案

权威数据显示&#xff0c;74%以上的数据泄露与网络安全事件归根结底与人为因素有关&#xff0c;60%以上的网络安全事件是由内部人员失误造成的。这一现状揭示了一个核心命题&#xff1a;网络安全威胁正从技术漏洞转向“人为因素风险”。Gartner的调查发现&#xff0c;即便接受了…

2025年食品科学与健康大数据国际会议(SHBD 2025)

2025年食品科学与健康大数据国际会议 2025 International Conference on Food Science and Health Big Data&#xff08;一&#xff09;大会信息 会议简称&#xff1a;ICFSHBD 2025 大会地点&#xff1a;中国上…

CompareFace人脸识别算法环境部署

一、docker 安装 步骤1&#xff1a;启用系统功能 右键开始菜单 → 应用和功能 → 点击 程序和功能 → 勾选 Hyper-V 和 Windows子系统Linux 步骤2&#xff1a;获取安装包 访问Docker官网安装包下载页 &#xff0c;下载「Docker Desktop Installer.rar」压缩包 步骤3&#…

STM32固件升级设计——内部FLASH模拟U盘升级固件

目录 一、功能描述 1、BootLoader部分&#xff1a; 2、APP部分&#xff1a; 二、BootLoader程序制作 1、分区定义 2、 主函数 3、配置USB 4、配置fatfs文件系统 5、程序跳转 三、APP程序制作 四、工程配置&#xff08;默认KEIL5&#xff09; 五、运行测试 结束语…

操作系统引导过程

操作系统引导是指计算机利用 CPU 运行特定程序&#xff0c;通过程序识别硬盘&#xff0c;识别硬盘分区&#xff0c;识别硬盘分区上的操作系统&#xff0c;最后通过程序启动操作系统。 引导流程&#xff08;8步核心环节&#xff09; 1. 激活CPU 加电后CPU自动读取 ROM中的Boot…

Safetensors与大模型文件格式全面解析

Safetensors是一种专为存储大型张量数据设计的文件格式&#xff0c;由Hugging Face团队开发&#xff0c;旨在提供安全高效的模型参数存储解决方案。下面将详细介绍Safetensors格式及其特点&#xff0c;并全面梳理当前主流的大模型文件格式。 一、Safetensors格式详解 1. 基本概…

分布式理论:CAP、Base理论

目录 1、CAP理论 1.1、介绍 1.2、CAP的三种选择 1.3、CAP的注意事项 2、BASE理论 2.1、定义介绍 2.2、最终一致性的介绍 2.3、BASE的实现方式 2.4、与ACID的对比 3、CAP与BASE的联系 4、如何选择CAP 前言 在分布式系统中&#xff0c;CAP理论和BASE理论是指导系统设计…

【最新】飞算 JavaAl安装、注册,使用全流程,让ai自己给你写代码,解放双手

目录 飞算 JavaAl 产品介绍 安装飞算 JavaAl 第一步&#xff1a;点击 File->Setting 第二步&#xff1a;点击 Plugins 第三步&#xff1a;搜索 CalEx-JavaAI 第四步&#xff1a;点击 Install 进行安装 第五步&#xff1a;点击 Install &#xff0c;查看安装好的飞算…

无人设备遥控器之姿态控制算法篇

无人设备遥控器的姿态控制算法通过传感器数据融合、控制算法优化和执行机构调节实现动态平衡&#xff0c;核心算法包括PID控制、自适应控制、模型预测控制&#xff08;MPC&#xff09;&#xff0c;以及数据融合中的互补滤波和卡尔曼滤波&#xff0c;同时涉及四元数算法和深度强…

【加解密与C】Base系列(三)Base85

Base85 编码简介 Base85&#xff08;也称为 Ascii85&#xff09;是一种二进制到文本的编码方案&#xff0c;用于将二进制数据转换为可打印的ASCII字符。它的效率高于Base64&#xff0c;但生成的字符串可能包含特殊字符&#xff08;如引号或反斜杠&#xff09;&#xff0c;需在…

Docker企业级应用:从入门到生产环境最佳实践

一、Docker核心概念与架构 1.1 Docker技术栈 #mermaid-svg-CUEiyGo05ZYG524v {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-CUEiyGo05ZYG524v .error-icon{fill:#552222;}#mermaid-svg-CUEiyGo05ZYG524v .error-te…

8、保存应用数据

目录用户首选项的使用用户首选项主要API用户首选项开发流程用户首选项开发实践关系型数据库的使用关系型数据库工作流程关系型数据库开发实践用户首选项的使用 用户首选项主要API 用户首选项开发流程 成功的获取了一个名为myStore的Preferences实例 保存了一个键值对&#x…

(C++)list列表相关基础用法(C++教程)(STL库基础教程)

源代码&#xff1a;#include <iostream> #include <list>using namespace std;int main(){list<int> numbers{10,20,30};numbers.push_front(5);numbers.push_back(40);auto it numbers.begin();advance(it,2);numbers.insert(it,15);cout<<"该列…