C# Modbus TCP/IP学习记录

打印 上一主题 下一主题

主题 1835|帖子 1835|积分 5505

Modbus协议中,脚色分为主站(Mater)、从站(Slave);数据范例分为线圈(Coil)、离散输入(Input)、保持寄存器(HoldingRegister)、输入寄存器(InputRegister)。
主站作为哀求发起方,负责发送命令给一个或多个从站;从站作为哀求响应方,负责接收主站命令并执行响应的操纵。
线圈为可读写布尔值,离散输入为只读布尔值,保持寄存器为可读写16位比特数值,输入寄存器为只读16为比特数值。
实操步骤:
1.利用Visual Studio创建C# Framework 控制台应用程序,作为TCP Client(客户端)、Modbus Master(主站)。
2.利用Visual Studio安装Nuget包NModbus:

3.下载Modbus Slave应用程序,作为TCP Server(服务端)、Modbus Slave(从站)。
下载地址:Download

4.打开Modbus Slave,单击工具栏“New”,创建四个Slave:



5.创建的Slave默认内容为10行,Slave ID为1,数据范例为保持寄存器,如需修改利用工具栏Slave Defintion。

运用SlaveDefintion把Mbslave1.mbs的Function改为01 Coil Status(0x),为线圈;
把Mbslave2.mbs的Function改为02 Input Status(1x),为离散输入;
把Mbslave3.mbs的Function改为03 Holding Register(4x),为保持寄存器;
把Mbslave3.mbs的Function改为04  Input Register(4x),为输入寄存器。

6.利用工具栏Connection项,单击Connect,弹窗Connection Setup,修改Connection下拉框为Modbus TCP/IP,下列配置按实际需求修改:




7.回到Visual Studio的控制台应用程序,输入以下代码,代码含有4种数据范例的读写(离散输入和输入寄存器为只读,所以只有读)方法,按需修改:
  1. using System;
  2. using System.Diagnostics.SymbolStore;
  3. using System.Net.Sockets;
  4. using NModbus;
  5. using NModbus.Message;
  6. class ModbusTcpClient
  7. {
  8.     private static string ipAddress = "127.0.0.1"; // 替换为实际 IP 地址
  9.     private static int port = 502; // Modbus TCP 默认端口号
  10.     private static byte slaveId = 1; // 从设备 ID
  11.     static void Main(string[] args)
  12.     {
  13.         try
  14.         {
  15.             using (TcpClient client = new TcpClient(ipAddress, port))
  16.             {
  17.                 // 创建 Modbus TCP 主站
  18.                 var factory = new ModbusFactory();
  19.                 IModbusMaster master = factory.CreateMaster(client);
  20.                 HoldingRegisterTest(master);
  21.                 InputRegisterTest(master);
  22.                 ColiTest(master);
  23.                 InputTest(master);
  24.             }
  25.         }
  26.         catch (Exception ex)
  27.         {
  28.             Console.WriteLine($"发生错误: {ex.Message}");
  29.         }
  30.         Console.ReadLine();
  31.     }
  32.     private static void HoldingRegisterTest(IModbusMaster master)
  33.     {
  34.         //保持寄存器是可读写的16位字(16位bits)
  35.         ReadHoldingRegisters(master, slaveId, 0, 10);//从地址0寄存器起,读10个保持寄存器数值
  36.         WriteSingleRegister(master, slaveId, 0, 21);//往地址0寄存器写入值21
  37.         ReadSingleHoldingReister(master, slaveId, 0);//读取地址0寄存器数值
  38.         WriteHoldingRegister(master, slaveId, 0, new ushort[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });//从地址0寄存器起,按数组顺序写入10个保持寄存器数值
  39.         ReadHoldingRegisters(master, slaveId, 0, 10);
  40.     }
  41.     private static void InputRegisterTest(IModbusMaster master)
  42.     {
  43.         //输入寄存器是只读的16位字(16位bits)
  44.         ReadInputRegisters(master, slaveId, 0, 10);
  45.         ReadSingleInputRegister(master, slaveId, 0);
  46.     }
  47.     private static void ColiTest(IModbusMaster master)
  48.     {
  49.         //线圈是可读写的布尔值
  50.         ReadCoils(master, slaveId, 0, 10);//从地址0寄存器起,读10个数值线圈
  51.         WriteSingleCoils(master, slaveId, 0, true);//往地址0寄存器写入值21
  52.         ReadCoils(master, slaveId, 0);//读取地址0寄存器数值
  53.         WriteCoils(master, slaveId, 0, new bool[] { true, false, true, false, true, false, true, false, true, false});//从地址0寄存器起,按数组顺序写入10个线圈数值
  54.         ReadCoils(master, slaveId, 0, 10);
  55.     }
  56.     private static void InputTest(IModbusMaster master)
  57.     {
  58.         //离散输入是只读的布尔值
  59.         ReadInputs(master, slaveId, 0, 10);
  60.         ReadSingleInput(master, slaveId, 0);
  61.     }
  62.     #region 保持寄存器
  63.     public static ushort[] ReadHoldingRegisters(IModbusMaster master, byte slaveId, ushort startAddress, ushort numRegisters)
  64.     {
  65.         ushort[] readValues = master.ReadHoldingRegisters(slaveId, startAddress, numRegisters);
  66.         Console.WriteLine("读取到的保持寄存器数据:");
  67.         for (int i = 0; i < readValues.Length; i++)
  68.         {
  69.             Console.WriteLine($"保持寄存器 {startAddress + i}: {readValues[i]}");
  70.         }
  71.         return readValues;
  72.     }
  73.     public static ushort ReadSingleHoldingReister(IModbusMaster master, byte slaveId, ushort startAddress)
  74.     {
  75.         ushort[] readValues = ReadHoldingRegisters(master, slaveId, startAddress, 1);//没有读单一保持寄存器的方法
  76.         return readValues[0];
  77.     }
  78.     public static void WriteHoldingRegister(IModbusMaster master, byte slaveId, ushort startAddress, ushort[] value)
  79.     {
  80.         master.WriteMultipleRegisters(slaveId, startAddress, value);
  81.         Console.WriteLine($"写入的保持寄存器数据:");
  82.         for (int i = 0; i < value.Length; i++)
  83.         {
  84.             Console.WriteLine($"保持寄存器 {startAddress + i}: {value[i]}");
  85.         }
  86.     }
  87.     public static void WriteSingleRegister(IModbusMaster master, byte slaveId, ushort address, ushort value)
  88.     {
  89.         master.WriteSingleRegister(slaveId, address, value);
  90.         Console.WriteLine($"写入的保持寄存器数据:");
  91.         Console.WriteLine($"保持寄存器 {address + 1}: {value}");
  92.     }
  93.     #endregion
  94.     #region 输入寄存器
  95.     public static ushort[] ReadInputRegisters(IModbusMaster master ,byte slaveId, ushort startAddress, ushort numRegisters)
  96.     {
  97.         ushort[] readValues = master.ReadInputRegisters (slaveId, startAddress, numRegisters);
  98.         Console.WriteLine("读取到的输入寄存器数据:");
  99.         for (int i = 0; i < readValues.Length; i++)
  100.         {
  101.             Console.WriteLine($"输入寄存器 {startAddress + i}: {readValues[i]}");
  102.         }
  103.         return readValues;
  104.     }
  105.     public static ushort ReadSingleInputRegister(IModbusMaster master, byte slaveId, ushort startAddress)
  106.     {
  107.         ushort[] readValues = ReadInputRegisters(master, slaveId, startAddress, 1);//没有读单一输入寄存器的方法
  108.         return readValues[0];
  109.     }
  110.     #endregion
  111.     #region 线圈
  112.     public static bool[] ReadCoils(IModbusMaster master, byte slaveId, ushort startAddress, ushort numRegisters)
  113.     {
  114.         bool[] readValues = master.ReadCoils(slaveId, startAddress, numRegisters);
  115.         Console.WriteLine("读取到的线圈数据:");
  116.         for (int i = 0; i < readValues.Length; i++)
  117.         {
  118.             Console.WriteLine($"线圈 {startAddress + i}: {readValues[i]}");
  119.         }
  120.         return readValues;
  121.     }
  122.     public static bool ReadCoils(IModbusMaster master, byte slaveId, ushort startAddress)
  123.     {
  124.         bool[] readValues = ReadCoils(master, slaveId, startAddress, 1);//没有读单一保持寄存器的方法
  125.         return readValues[0];
  126.     }
  127.     public static void WriteCoils(IModbusMaster master, byte slaveId, ushort startAddress, bool[] value)
  128.     {
  129.         master.WriteMultipleCoils(slaveId, startAddress, value);
  130.         Console.WriteLine($"写入的线圈数据:");
  131.         for (int i = 0; i < value.Length; i++)
  132.         {
  133.             Console.WriteLine($"线圈 {startAddress + i}: {value[i]}");
  134.         }
  135.     }
  136.     public static void WriteSingleCoils(IModbusMaster master, byte slaveId, ushort address, bool value)
  137.     {
  138.         master.WriteSingleCoil(slaveId, address, value);
  139.         Console.WriteLine($"写入的线圈数据:");
  140.         Console.WriteLine($"线圈{address + 1}: {value}");
  141.     }
  142.     #endregion
  143.     #region 离散输入
  144.     public static bool[] ReadInputs(IModbusMaster master, byte slaveId, ushort startAddress, ushort numRegisters)
  145.     {
  146.          bool[] readValues = master.ReadInputs(slaveId, startAddress, numRegisters);
  147.         Console.WriteLine("读取到的离散输入数据:");
  148.         for (int i = 0; i < readValues.Length; i++)
  149.         {
  150.             Console.WriteLine($"离散输入 {startAddress + i}: {readValues[i]}");
  151.         }
  152.         return readValues;
  153.     }
  154.     public static bool ReadSingleInput(IModbusMaster master, byte slaveId, ushort startAddress)
  155.     {
  156.         bool[] readValues = ReadInputs(master, slaveId, startAddress, 1);//没有读单一离散输入的方法
  157.         return readValues[0];
  158.     }
  159.     #endregion
  160. }
复制代码
8.执行结果:







免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

乌市泽哥

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表