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("连接已关闭");
            }
        }

        
    }
}

要安装这个包

相关推荐
bugcome_com12 小时前
零基础入门C#:一篇搞懂核心知识点
c#
程序员敲代码吗15 小时前
如何通过命令行启动COMSOL的参数化、批处理和集群扫描
java·c#·bash
缺点内向17 小时前
C#: 告别繁琐!轻松移除Word文档中的文本与图片水印
c#·自动化·word·.net
喵叔哟18 小时前
06-ASPNETCore-WebAPI开发
服务器·后端·c#
2501_9307077818 小时前
使用 C# .NET 从 PowerPoint 演示文稿中提取背景图片
c#·powerpoint·.net
初级代码游戏18 小时前
套路化编程 C# winform 自适应缩放布局
开发语言·c#·winform·自动布局·自动缩放
大空大地202620 小时前
流程控制语句--switch多分支语句使用、while循环语句的使用、do...while语句、for循环
c#
kylezhao201921 小时前
C#序列化与反序列化详细讲解与应用
c#
JQLvopkk21 小时前
C# 实践AI :Visual Studio + VSCode 组合方案
人工智能·c#·visual studio
故事不长丨21 小时前
C#线程同步:lock、Monitor、Mutex原理+用法+实战全解析
开发语言·算法·c#