跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

c#如何与欧姆龙PLC通讯_c#与欧姆龙PLC通讯完整教程与代码实例

推荐使用OmronFinsNet(HslCommunication)实现FINS/TCP通信,因其封装完整、支持自动重试与错误码映射、地址格式贴近PLC编程习惯,且默认适配大小端,一行代码即可读写D/CIO/HR/WR区,省去手动拼帧、FCS计算及节点号配置等复杂细节。 直接用
OmronFinsNet
(来自
HslCommunication.Profinet.Omron
)是最省事、最稳的选择,尤其对 FINS/TCP 场景。串口 Host Link 虽然还能用,但配置繁琐、校验易错、响应解析反直觉,新手掉坑里基本靠手册硬啃。 FINS/TCP 通信:用 HslCommunication 一行地址就能读写 绝大多数现代欧姆龙 PLC(CP/CJ/NJ/NX 系列)都支持 FINS/TCP,默认端口
9600
,只要网线通、IP 配对、节点号不冲突,连上就跑得动。
OmronFinsNet
封装了完整的帧构造、超时重试、字节序转换和错误码映射,你不用碰
0x02 0x46 0x49...
这类原始字节 地址写法完全贴近 PLC 编程习惯:
"D100"
、
"CIO0"
、
"HR10.0"
、
"WR200.3"
,不用手动补零或拆高低字节 读取返回的是
ushort[]
,写入也直接传
ushort[]
,底层自动处理大小端——NJ/NX 默认小端,
HslCommunication
默认按此适配 连接失败时会明确告诉你错误码,比如
0x0020
(目标节点未响应)、
0x0030
(内存区域不存在),比抓包看
*00RD0000000000\r
强太多 示例代码:
var plc = new OmronFinsNet("192.168.1.10", 9600); var connectResult = plc.ConnectServer(); if (!connectResult.IsSuccess) { Console.WriteLine($"连接失败: {connectResult.Message}"); return; } // 读 D100~D105 共 6 个字 var readResult = plc.ReadUInt16("D100", 6); if (readResult.IsSuccess) { ushort[] values = readResult.Content; // [123, 456, ...] }
串口 Host Link:必须手算 FCS 且地址格式反直觉 老设备(如 CPM1A、CPM2A)没网口,只能走 RS-232/485,这时得自己拼 Host Link 帧。核心难点不在串口本身,而在协议细节: 地址必须严格四字符 ASCII:
"DM100"
要写成
"DM0100"
,
"CIO50"
得是
"CIO050"
,少一个零就返回
*00RD0000000000\r
FCS 是对
@00RD...0001
这段纯 ASCII 字符逐字节异或,不是对整个
*@00RD...0001XX\r
计算 响应数据中,
"00ABCD"
表示一个 Word,但实际值是
0xCDAB
(低位在前),不能直接
Convert.ToUInt16("ABCD", 16)
SerialPort
的
DataReceived
事件不可靠,建议用
ReadExisting()
+ 固定延时(
Thread.Sleep(200)
)收完整帧,否则容易截断 关键片段: C知道 CSDN推出的一款AI技术问答工具 下载
string address = "DM" + addr.ToString("D4"); // DM100 → DM0100 string finsFrame = $"@00RD{address}0001"; byte fcs = 0; foreach (char c in finsFrame) fcs ^= (byte)c; string cmd = $"*{finsFrame}{fcs:X2}\r";

sp.Write(cmd); Thread.Sleep(200); string resp = sp.ReadExisting().Trim(); // 解析 "00ABCD" → 先取后 4 字符,再反转字节顺序 string hexData = resp.Substring(resp.Length - 8, 4); // 示例取法,需按实际响应结构调整 byte[] bytes = new byte[2] { Convert.ToByte(hexData.Substring(2, 2), 16), Convert.ToByte(hexData.Substring(0, 2), 16) }; ushort value = BitConverter.ToUInt16(bytes, 0);

节点号与网络号配错:TCP 连不上最常卡在这儿 FINS/TCP 不是“IP 通就能连”,它有一套独立的寻址逻辑,和 IP 层无关。配错会导致静默失败(无异常,但
ConnectServer()
返回 false):
RemoteNode
(PLC 节点号)默认是
0
,但在 NJ/NX 中可能被设为其他值(查 PLC 系统寄存器
D8000
或编程软件设置)
LocalNode
(上位机节点号)不能为
0
,推荐用
100
~
254
,避免和 PLC 冲突 网络号(
SA1/DA1
)多数场景填
0
即可;若 PLC 在多网段,才需匹配其网络配置 有些型号(如 CP1E)需在 PLC 上启用“FINS 通信”功能(通过 DIP 开关或系统设置),否则端口监听都不开 为什么别自己从头写 FINS/TCP 帧 看似只是拼几个字节,但实际要处理的边界远超想象: 事务 ID(
SID
)必须递增且不能重复,否则 PLC 可能丢弃后续请求 帧长度字段(
0x00 0x00
位置)要动态计算并填充,漏填或填错导致 PLC 直接断连 读写命令的地址编码方式不同:DM 区用 0x02,CIO 区用 0x30,HR 区用 0x34,写错就返回
0x0040
(非法地址) 批量读写时,长度字段单位是“字”(Word),不是“字节”,
0x000A
表示读 10 个
ushort
,不是 10 字节 没有内置重试机制,网络抖动一次就失败,而
HslCommunication
默认带 3 次重试 真正难的从来不是“怎么发”,而是“发完之后怎么确定它真的被 PLC 执行了”。用成熟库,等于把三年踩过的坑打包买断。

相关文章