Modbus-Tcp 通讯学习总结


一、项目概览

NuGet 依赖

<PackageReference Include="NModbus" Version="3.0.83" />
<PackageReference Include="NModbus.Serial" Version="3.0.83" />
  • NModbus:实现 Modbus TCP / UDP 协议主从站
  • NModbus.Serial:串口(RTU/ASCII)场景下使用,本项目未直接调用

二、Modbus-Tcp 业务流程图

                  +-----------------------------+
                  |        应用程序启动         |
                  |   Form1_Load 设置默认参数   |
                  |   IP=127.0.0.1  Port=502   |
                  +--------------+--------------+
                                 |
                                 v
            +--------------------+---------------------+
            |              用户操作界面                |
            |  [选择模式]  [输入IP]  [输入端口]        |
            +----+-------------+--------------+------+
                 |             |              |
                 v             v              v
          +------+----+  +-----+------+  +---+--------+
          | ModbusTCP|  | ModbusUDP   |  |RTU Over TCP|
          +------+----+  +-----+------+  +---+--------+
                 |             |              |
                 |             |              | 
                 |             |              |  
                 v             v              v
            +--------------------------------------+
            |        创建 ModbusFactory            |
            |   var factory = new ModbusFactory(); |
            +------------------+-------------------+
                               |
                               v
            +--------------------------------------+
            |  建立底层网络连接并创建 Master        |
            |  TcpClient.ConnectAsync(...)         |
            |  master = factory.CreateMaster(tcp)  |
            +------------------+-------------------+
                               |
                               v
                  +------------+------------+
                  |   连接成功 / 按钮切换   |
                  |   btnStart.Text=断开    |
                  +------------+------------+
                               |
            +------------------+------------------+
            |                                     |
            v                                     v
   +--------+--------+                 +----------+----------+
   |   读取流程       |                 |      写入流程        |
   +--------+--------+                 +----------+----------+
            |                                     |
            v                                     v
   +--------+--------+                 +----------+----------+
   | 创建CTS + 启动   |                 | 调用 master.       |
   | Task.Run 循环    |                 | WriteSingleRegister|
   +--------+--------+                 +----------+----------+
            |                                     |
            v                                     v
   +--------+--------+                 +----------+----------+
   | master.Read-     |                 |  功能码 0x06       |
   | HoldingRegisters|                 |  写入单个寄存器     |
   |  (1, 0, 4)       |                 +----------+----------+
   +--------+--------+
            |
            v
   +--------+--------+
   | 功能码 0x03      |
   | 读取 HR0 ~ HR3  |
   +--------+--------+
            |
            v
   +--------+--------+
   | Control.Invoke  |
   | 更新 4 个文本框  |
   +--------+--------+
            |
            v
   +--------+--------+
   | Task.Delay(1000)|
   | 1 秒轮询周期    |
   +--------+--------+
            |
            +<--------+ (循环直到 cts.Cancel)
            |
            v
   +--------+--------+
   |   退出读取循环   |
   +-----------------+
            |
            v
   +--------+--------+
   |   用户点击断开   |
   |   cts.Cancel()   |
   |   清空数据显示    |
   +-----------------+
            |
            v
       +----+----+
       |   结束   |
       +---------+

三、核心关键字段

private IModbusMaster? master;        // Modbus 主站接口,统一抽象 TCP/UDP/RTU
private CancellationTokenSource? cts;  // 异步读取任务的取消令牌

要点:

  • IModbusMaster 是 NModbus 的统一主站接口,屏蔽底层传输差异
  • CancellationTokenSource 用于优雅停止后台轮询任务

四、关键代码片段

4.1 创建 ModbusFactory 与 Master

var factory = new ModbusFactory();
TcpClient tcp = new TcpClient();
tcp.ConnectAsync(IPAddress.Parse(txtIP.Text), int.Parse(txtPort.Text));
master = factory.CreateMaster(tcp);

ModbusFactory.CreateMaster 接受 TcpClient / UdpClient / Socket,返回的 IModbusMaster 屏蔽底层传输差异。

4.2 周期读取保持寄存器

cts = new CancellationTokenSource();
Task.Run(async () =>
{
    while (!cts.IsCancellationRequested)
    {
        if (master == null) continue;
        ushort[] data = master.ReadHoldingRegisters(1, 0, 4);

        Invoke(new Action(() =>
        {
            txtData1.Text = data[0].ToString();
            // txtData2 / txtData3 / txtData4 ...
        }));

        await Task.Delay(1000);
    }
}, cts.Token);

调用:master.ReadHoldingRegisters(slaveAddress=1, startAddress=0, numberOfPoints=4)

对应 Modbus 功能码 0x03,读取从站 1 的保持寄存器 HR0 ~ HR3。

4.3 写入单个寄存器

if (master == null) return;
master.WriteSingleRegister(1, 0, 111);

对应 Modbus 功能码 0x06,向从站 1 的 HR0 写入值 111。

4.4 断开连接

cts?.Cancel();
txtData1.Text = "";
// 清空其余显示 ...
btnRead.Text = "实时读取";

五、NModbus 支持的传输模式对比

模式UI 控件底层类型NModbus 创建方式
Modbus TCPrdbTCPTcpClientfactory.CreateMaster(tcp)
Modbus UDPrdbUDPUdpClientfactory.CreateMaster(udp)
RTU Over TCP /UDPrdbRTUOverTCP/UDPSocket (Stream/Tcp/Udp)factory.CreateMaster(socket)

Modbus TCP 使用 MBAP Header + PDU 帧格式;RTU Over TCP 在 TCP 流上承载含 CRC 的 RTU 帧。切换传输模式时业务代码(ReadHoldingRegisters 等)无需改动。


六、NModbus 关键 API 速查

API功能码作用
ReadCoils0x01读线圈(bit)
ReadInputs0x02读离散输入(bit,只读)
ReadHoldingRegisters0x03读保持寄存器(16 bit)
ReadInputRegisters0x04读输入寄存器(只读)
WriteSingleCoil0x05写单个线圈
WriteSingleRegister0x06写单个保持寄存器
WriteMultipleCoils0x0F写多个线圈
WriteMultipleRegisters0x10写多个保持寄存器

更多推荐