终于有人把欧姆龙PLC通信协议说清楚了
上位机Guide 2025-03-31


西门子、三菱、欧姆龙是我们自动化行业使用最多的三个PLC品牌。今天分享一下欧姆龙PLC的FinsTCP通信协议。大家在学习FinsTCP通信协议时,建议先掌握ModbusTCP或三菱MC通信协议。这样看来,ModbusTCP协议太简单了三菱PLC的MC通信协议报文解析Fins通信协议是欧姆龙PLC专用协议,主要用于控制欧姆龙系列PLC,它是一个公开的协议,可以通过欧姆龙官方下载到协议文档。

一、握手协议

FinsTCP通信协议,与ModbusTCP和MC协议有一个不同地方在于,当我们完成TCP连接后,不能直接进行读取或写入,需要有一个握手过程,以保证通信安全。这点与西门子S7协议类似,S7协议会有两次握手验证,FinsTCP只需要一次即可。握手命令如下所示:发送报文格式:接收报文格式:我们使用TCP助手测试一下:本机IP地址是192.168.2.77,PLC的IP地址是192.168.2.164,因此发送报文为:46 49 4E 53 00 00 00 0C 00 00 00 00 00 00 00 00 00 00 00 4D返回报文为:46 49 4E 53 00 00 00 10 00 00 00 01 00 00 00 00 00 00 00 4D 00 00 00 A4 其中0x4D=77,对应ClientNode,PC的IP最后一位。0xA4=164,对应ServerNode,PLC的IP最后一位。

二、Fins通用格式

我们学习通信,一般都会有个通用格式。

所谓通用格式,就是无论发送、接收的报文都会按照这个格式来,会将变化的部分封装成一个整体,一般叫做数据部分或者Parameter。

Fins通用报文格式如下:

三、读取协议帧

FinsTCP通信协议读取数据的请求帧报文是在通用格式的基础上,将 Parameter部分替换为 Area+Address+Length。读取请求帧格式如下所示:

响应帧报文是在通用格式的基础上,将 Parameter部分替换为 ErrorCode+Value。读取响应帧格式如下所示:

四、写入协议帧

FinsTCP通信协议写入数据的请求帧报文是在通用格式的基础上,将 Parameter部分替换为 Area+Address+Length+Value。写入请求帧格式如下所示:响应帧报文是在通用格式的基础上,将 Parameter部分替换为 ErrorCode。写入响应帧报文如下所示:

五、通信测试

我们以读取D0开始的5个寄存器为例,结合协议文档,来进行报文拼接。

发送报文如下:

Header:0x46 0x49 0x4E 0x53

Length:0x00 0x00 0x00 0x1A

Command:0x00 0x00 0x00 0x02

ErrorCode:0x00 0x00 0x00 0x00

ICF:0x80

RSV:0x00

GCT:0x02

DNA:0x00

DA1:0xA4

DA2:0x00

SNA:0x00

SA1:0x4D

SA2:0x00

SID:0x00

MRC:0x01

SRC:0x01

Area:0x82

Address:0x00 0x00 0x00

Length:0x00 0x05

我们通过网络调试助手发送这个报文,观察一下返回的报文:

响应报文如下

我们只需要关注最后的ErrorCode和Value即可。

ErrorCode:0x00 0x00

Value:0x00 0x0A 0x00 0x14 0x00 0x1E 0x00 0x28 0x00 0x32

其中0x00 0x0A 0x00 0x14 0x00 0x1E 0x00 0x28 0x00 0x32即表示D0-D4的值,进行数据解析处理后的值分别为10、20、30、40、50,与PLC数据一致。

六、代码实现

我们也可以编写C#程序来实现整个过程。

这里测试为主,代码相对简单,实际应用时可进一步封装,代码如下:

static void Main(string[] args){ // 连接 Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Connect("192.168.2.164", 9600); //握手 byte[] handsend = new byte[] { 0x46, 0x49, 0x4E, 0x53,  0x00, 0x00, 0x00, 0x0C,  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x4D };  socket.Send(handsend); byte[] handrcv = new byte[1024]; int count = socket.Receive(handrcv); //简单验证握手正确 if (count == 24 && handrcv[12] == 0x00 && handrcv[13] == 0x00 && handrcv[14] == 0x00 && handrcv[15] == 0x00) { //读取D0开始的5个字 byte[] readsend = new byte[] { 0x46, 0x49, 0x4E, 0x53,  0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x02, 0x00,  0x00, 0x00, 0x00, 0x80, 0x00, 0x02, 0x00, 0xA4, 0x00,  0x00, 0x4D, 0x00, 0x00,0x01,0x01,0x82,0x00,0x00, 0x00,0x00,0x05}; socket.Send(readsend); byte[] readrcv = new byte[1024]; int rcvCount = socket.Receive(readrcv);  if (rcvCount == 40) { for (int i = 30; i < rcvCount; i += 2) { // 每2个字节作为一个数据 byte[] dataBytes = new byte[2]; dataBytes[0] = readrcv[i + 1]; dataBytes[1] = readrcv[i]; Console.WriteLine(BitConverter.ToInt16(dataBytes, 0)); } } } Console.ReadLine();}

输出结果如下:

写在最后

去年8月,历经2年,我出版了一本上位机书籍——《C#上位机开发实战指南》。

我的新书《C#上位机开发实战指南》出版了

大家如果需要购买,可以通过京东旗舰店购买。

-END-

上位机技术文章,请关注公众号【上位机Guide】上位机技术交流,请添加本人微信【fuswj001】

感谢大家阅读,关注我,分享上位机开发技术。



声明: 本文转载自其它媒体或授权刊载,目的在于信息传递,并不代表本站赞同其观点和对其真实性负责,如有新闻稿件和图片作品的内容、版权以及其它问题的,请联系我们及时删除。(联系我们,邮箱:evan.li@aspencore.com )
0
评论
  • 相关技术文库
  • RF
  • 射频
  • 通信
  • 无线
下载排行榜
更多
评测报告
更多
广告