Modbus TCP

csharp 复制代码
using EasyModbus;
using System;
using System.Net;
using System.Threading;
/**
                0x01 读取线圈的操作,
                0x02 读取离散的操作,
                0x03 读取寄存器的值,
                0x05 写一个线圈操作,
                0x06 写一个寄存器值,
                0x0F 批量写线圈操作,
                0x10 批量写寄存器值,
                // 1. 保持寄存器 (功能码03读、06写单个、16写多个) → 最常用 ✅
                // 类型:ushort[] ,取值范围 0~65535 ,地址 0~n
                modbusServer.HoldingRegisters[0] = 100; // 赋值
                ushort val = modbusServer.HoldingRegisters[0]; // 取值

                // 2. 线圈寄存器 (功能码01读、05写单个、15写多个) → 开关量 ✅
                // 类型:bool[] ,true=通/1 ,false=断/0 ,地址 0~n
                modbusServer.Coils[1] = true; // 赋值
                bool coilVal = modbusServer.Coils[1]; // 取值

                // 3. 输入寄存器 (功能码04读) → 只读,通常存传感器输入数据
                modbusServer.InputRegisters[5] = 250;

                // 4. 离散输入寄存器 (功能码02读) → 只读,通常存开关量输入数据
                modbusServer.DiscreteInputs[3] = true;

                角色分为主站(Mater)、从站(Slave);
                数据类型分为线圈(Coil)、离散输入(Input)、
                保持寄存器(HoldingRegister)、输入寄存器(InputRegister)
                线圈(Coils):1 位布尔值,可读写。
                离散输入(Discrete Inputs):1 位布尔值,只读。
                保持寄存器(Holding Registers):16 位寄存器,可读写。
                输入寄存器(Input Registers):16 位寄存器,只读。

                每个数据类型都有它自己的地址范围:
                线圈地址范围:000001~065536
                离散量输入地址范围:100001~165536
                输入寄存器地址范围:300001~365536
                保持寄存器地址范围:400001~465536

                但别被这些数字吓到,实际应用中,我们通常只用到10000以内的地址。比如:
                线圈地址范围:00001~09999
                离散量输入地址范围:10001~19999
                输入寄存器地址范围:30001~39999
                保持寄存器地址范围:40001~49999
                如何解读Modbus地址? 🔍

                当你看到地址40001或30004时,怎么判断它是什么类型的寄存器呢?其实很简单:
                40001 / 400001:最前面的4表明它是一个保持寄存器,后面的0001或00001都指第一个保持存储器,地址是0。
                30004:表明它是输入寄存器,地址是3。
                10008:表明它是离散量输入,地址是7。
                */
namespace ConsoleApp12
{
    /// <summary>
    /// EasyModbus 客户端
    /// string clientIp = client.Client.RemoteEndPoint.ToString().Split(':')[0];
    /// </summary>
    internal class Program
    {
        static void Main(string[] args)
        {
            ModbusClient modbusClient = new ModbusClient("127.0.0.1", 502);

            try
            {
                Console.WriteLine("正在连接Modbus服务器...");
                modbusClient.Connect();

                // 读取保持寄存器
                Console.WriteLine("读取保持寄存器...");


                int[] registers = modbusClient.ReadHoldingRegisters(0, 5);
                for (int i = 0; i < registers.Length; i++)
                {
                    Console.WriteLine($"寄存器 {i}: {registers[i]}");
                }

                // 写入寄存器
                Console.WriteLine("写入寄存器...");
                int ii = 1;
                /*while (true)
                {
                    ii++;
                    modbusClient.WriteSingleRegister(1, ii);
                    Thread.Sleep(500);
                }*/
                while (true)
                {
                    registers = modbusClient.ReadHoldingRegisters(0, 5);
                    for (int i = 0; i < registers.Length; i++)
                    {
                        Console.WriteLine($"寄存器 {i}: {registers[i]}");
                    }
                    Thread.Sleep(1000);
                }

                

                // 1、线圈------读写,布尔类型,主要用于设置某个值。
                // 读取多个输出线圈
                // 读取线圈状态 (功能码01)
                // 从地址0开始读取5个线圈
                // bool[] coilStatus = modbusClient.ReadCoils(0, 5); 

                // 写入单个线圈 (功能码05)
                // 向地址0写入true
                //modbusClient.WriteSingleCoil(0, true); 

                //2、离散量输入------只读,布尔类型,获取某个IO状态(1bit)。


                //3、输入寄存器------只读,无符号2字节整型,获取某个16bit数据的值。
                // 读取输入寄存器
                //int[] inputRegisters = modbusClient.ReadInputRegisters(0, 5);

                //4、保持寄存器------读写,无符号2字节整型,设置某个16bit数据的值。
                // 读取保持寄存器 (功能码03)
                // 从地址0开始读取10个寄存器
                //int[] holdingRegisters = modbusClient.ReadHoldingRegisters(0, 10); 

                // 写入单个保持寄存器
                //modbusClient.WriteSingleRegister(0, 1234);

                // 写入多个保持寄存器
                // 写入多个寄存器 (功能码16)
                //int[] valuesToWrite = { 100, 200, 300 };
                // 从地址0开始写入
                //modbusClient.WriteMultipleRegisters(0, valuesToWrite); 

                // 验证写入
                //int value = modbusClient.ReadHoldingRegisters(10, 1)[0];
                //Console.WriteLine($"寄存器10的新值: {value}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"错误: {ex.Message}");
            }
            finally
            {
                modbusClient.Disconnect();
                Console.WriteLine("连接已关闭");
            }
        }

        
    }
}

要安装这个包

相关推荐
人工智能AI技术3 小时前
能用C#开发AI吗?
人工智能·c#
自己的九又四分之三站台5 小时前
6. 简单将原生代码改为流式请求
c#
一叶星殇8 小时前
C# .NET 如何解决跨域(CORS)
开发语言·前端·c#·.net
JQLvopkk8 小时前
C#调用Unity实现设备仿真开发浅述
开发语言·unity·c#
zxy28472253019 小时前
使用Topshelf部署window后台服务(C#)
c#·安装·topshelf·后台服务
缺点内向11 小时前
C# 高效统计 Word 文档字数:告别手动,拥抱自动化
c#·自动化·word
skywalk816312 小时前
介绍一下 Backtrader量化框架(C# 回测快)
开发语言·c#·量化
Never_Satisfied12 小时前
C#数组去重方法总结
开发语言·c#
阿蒙Amon12 小时前
C#每日面试题-静态构造函数和普通构造函数区别
java·开发语言·c#