C#读取modbus值,C#读写modbus,支持读写uint32值,Modbus TCP工具类

发布于:2025-07-10 ⋅ 阅读:(15) ⋅ 点赞:(0)

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

                    //合并还原为uint32
                    uint 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);
        }


    }
}


网站公告

今日签到

点亮在社区的每一天
去签到