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);}}
}