如何使用DotNet连接UDP Fins Gateway?求欧姆龙NX1P2 PLC UDP连接资源
用.NET对接欧姆龙NX1P2的UDP Fins Gateway指南
我刚好有过用.NET对接欧姆龙NX系列PLC的UDP Fins经验,市面上确实很少有现成的免费UDP库,但其实我们可以基于.NET自带的UdpClient手动封装核心通信逻辑,完全不需要依赖第三方付费组件。下面给你一步步拆解实现方案:
先搞懂Fins over UDP的基础逻辑
欧姆龙的Fins协议在UDP上的通信很直接:
- 默认通信端口是
9600 - 每个请求都是一个结构化的字节报文,PLC收到后会返回对应格式的响应报文
- 报文要严格遵循欧姆龙Fins协议规范(重点是帧头、命令码、数据区的字节顺序,PLC用大端字节序)
完整的.NET代码示例(读DM区为例)
下面是一个可直接测试的代码片段,实现读取NX1P2的DM区数据:
using System; using System.Net; using System.Net.Sockets; class OmronUdpFinsClient { private readonly UdpClient _udpClient; private readonly IPEndPoint _plcEndPoint; // 初始化客户端,传入PLC的IP和端口(默认9600) public OmronUdpFinsClient(string plcIp, int port = 9600) { _udpClient = new UdpClient(); _plcEndPoint = new IPEndPoint(IPAddress.Parse(plcIp), port); // 设置超时时间,避免无限等待 _udpClient.Client.ReceiveTimeout = 5000; } // 读取DM区数据:起始地址,读取长度 public ushort[] ReadDmArea(ushort startAddress, ushort count) { // 构建Fins请求报文 byte[] request = BuildFinsReadDmRequest(startAddress, count); // 发送请求 _udpClient.Send(request, request.Length, _plcEndPoint); // 接收响应 byte[] response = _udpClient.Receive(ref _plcEndPoint); // 解析响应数据 return ParseDmResponse(response, count); } // 构建读DM区的Fins请求帧(读DM命令码:主0x01,子0x01) private byte[] BuildFinsReadDmRequest(ushort startAddr, ushort count) { // Fins报文结构:帧头(8字节) + 命令帧(13字节) byte[] frame = new byte[21]; // 帧头固定标识 frame[0] = 0x46; // 'F' frame[1] = 0x49; // 'I' frame[2] = 0x4E; // 'N' frame[3] = 0x53; // 'S' // 命令帧长度(13字节,大端序) frame[4] = 0x00; frame[5] = 0x0D; // 错误码默认0 frame[6] = 0x00; frame[7] = 0x00; // 命令帧部分 frame[8] = 0x00; // 网络号(根据PLC实际设置调整) frame[9] = 0x00; // 节点号(根据PLC实际设置调整) frame[10] = 0x00; // 单元号(默认0) frame[11] = 0x01; // 主命令码(读内存区) frame[12] = 0x01; // 子命令码(DM区) // 起始地址(大端序) frame[13] = (byte)(startAddr >> 8); frame[14] = (byte)(startAddr & 0xFF); frame[15] = 0x00; // 地址扩展位(默认0) // 读取长度(大端序) frame[16] = (byte)(count >> 8); frame[17] = (byte)(count & 0xFF); frame[18] = 0x00; // 长度扩展位(默认0) // 附加码默认0 frame[19] = 0x00; frame[20] = 0x00; return frame; } // 解析DM区响应数据 private ushort[] ParseDmResponse(byte[] response, ushort count) { // 响应报文从第13字节开始是数据区,每个DM值占2字节(大端序) ushort[] result = new ushort[count]; for (int i = 0; i < count; i++) { result[i] = (ushort)((response[13 + i * 2] << 8) | response[14 + i * 2]); } return result; } // 释放资源 public void Dispose() { _udpClient.Dispose(); } } // 测试调用 class Program { static void Main() { using (var client = new OmronUdpFinsClient("192.168.1.100")) // 替换成你的PLC实际IP { try { // 读取DM0000到DM0004,共5个寄存器 ushort[] data = client.ReadDmArea(0, 5); Console.WriteLine("读取到DM区数据:"); for (int i = 0; i < data.Length; i++) { Console.WriteLine($"DM{i:D4}: {data[i]}"); } } catch (Exception ex) { Console.WriteLine($"通信失败:{ex.Message}"); } } } }
必须注意的几个坑(我之前踩过的)
- PLC侧设置:一定要在NX1P2的Fins Gateway设置里开启UDP通信,并且把你的客户端IP加入允许访问列表,端口保持默认9600即可
- 字节序问题:欧姆龙所有多字节数据(地址、长度、寄存器值)都是大端字节序,.NET默认是小端,所以一定要用移位和位运算转换
- 超时与重试:UDP是无连接协议,发送后可能收不到响应,一定要给
UdpClient设置超时时间,业务代码里建议加重试逻辑 - 命令码对应:不同操作的主/子命令码不同,比如写DM区是
0x0102,读CIO区是0x0001,需要对照欧姆龙官方Fins手册调整
如果需要扩展其他操作(比如写寄存器、读CIO区),只需要修改请求帧的命令码和数据区即可,核心通信逻辑都是一致的。
内容的提问来源于stack exchange,提问作者gabrielepetteno
相关产品推荐
相关产品推荐

