当前位置: 首页 > news >正文

C#上位机与欧姆龙PLC的通信06---- HostLink协议(FINS版)

1、介绍

 对于上位机开发来说,欧姆龙PLC支持的主要的协议有Hostlink协议,FinsTcp/Udp协议,EtherNetIP协议,本项目使用Hostlink协议。 

Hostlink协议是欧姆龙PLC与上位机链接的公开协议。上位机通过发送Hostlink命令,可以对PLC进行I/O读写、可以对PLC进行I/O读写、改变操作模式、强制置位/复位等操作。由于是公开协议,即便是非欧姆龙的上位设备(软件),都可以通过该协议和欧姆龙PLC实现通信链接,

Hostlink通讯协议有两种模式:C-mode和FINS

上个文章采用C-mode方式,本篇采用FINS方式

1.Cmode:专用于hostlink通讯指令,采用的是ASCII码,适用于所有OMRON的PLC通讯。只能上位机发出指令给CPU,CPU无法主动发数据给上位机,只可以通过串口进行通讯

2.FINS:采用的二进制码,适用于新开发的PLC,可用在多种网络设备(Controller  Link,  Ethernet,  etc),可被 CPU、IO模块、上位机主动发出,不同的指令分别适用于不同的信息接受单元。有两种链接协议:CMND和hostlink,当上位机是做发送源时,必须采用hostlink协议,既可以通过串口通讯也可以通过各类网络通讯(适应性较强)。 

欧姆龙PLC与上位机连接时一般采用的是Hoslink协议,它是一种简易经济的通讯方式,比较适合一台上位机和一台PLC或者多台PLC进行通讯。上位机可对PLC进行程序传送和读写等操作。HOSTLINK系统允许一台上位机通过上位机链接命令向HOSTLINK系统的PLC发送命令,PLC处理来自上位机的每条指令,并把结果传回上位机。

2、欧姆龙Fins协议

欧姆龙FINS协议:现代工业自动化领域的通信利器,欧姆龙FINS协议,全称为”Factory Interface Network Service",是日本欧姆龙(Omron)公司开发的一套高效的工业自动化通信协议。它作为欧姆龙工业设备之间的通信接日,被广泛应用于全球范围内的工业自动化领域。

支持以太网的欧姆龙PLC CPU、以太网通信模块根据型号的不同,一般都会支持FINS(Factory Interface Network Service)协议,一些模块也会支持EtherNet/IP协议。Fins协议封装在TCP/UDP之上。

下图表述了FINS会话开始几个数据帧的作用。FINS协议的会话有一次请求帧,请求帧中附带着发起方的节点参数。PLC端(Server端)会确认并将自己的节点参数放回给请求方。

1、Fins协议和我们常用的ModbusTCP协议不同,首先体现在有握手验证命令,就是说在正常的三次握手的基础上,还需要进行一次握手,如果能正常握手,方可通信,这样做的目的也是为了PLC通信安全。

命令均为十六进制 字节数据流

 2、Fins握手命令

发送报文格式:

返回报文格式:

3、Fins通信命令

Fins通信协议的整体命令如下所示

4、Fins读取数据

Fins读取数据的报文会在通用命令的基础上,将 Parameter替换为 Area+Address+Length,因此读取数据命令如下所示:

读取数据返回命令如下所示:

5、Fins写入数据

Fins写入数据会在通用命令的基础上,将 Parameter替换为 Area+Address+Length+Value,因此写入数据命令如下所示:

写入数据返回命令如下所示:

 3、开搞Fins协议

1、确认环境

确认你的cx-simulator的串口设置已经设置好虚拟串口工具软件的com2

 2、运行网络调试工具NetAssist.exe

3、发送握手报文

首先要有握手验证命令,就是说在正常的三次握手的基础上,还需要进行一次握手,如果能正常握手,方可通信,这样做的目的也是为了PLC通信安全。

 发送:46 49 4E 53 00 00 00 0C 00 00 00 00 00 00 00 00 00 00 00 04
 接收:46 49 4E 53 00 00 00 10 00 00 00 01 00 00 00 00 00 00 00 04 00 00 00 0A

发送报文格式:

1)发送报文分析:

发送:46 49 4E 53 00 00 00 0C 00 00 00 00 00 00 00 00 00 00 00 04
接收:46 49 4E 53 00 00 00 10 00 00 00 01 00 00 00 00 00 00 00 04 00 00 00 0A

46494E53:转换成ASCII编码就是FINS;

0000000C:指后面跟的字节长度;12个字节,不包括自己的字节长度,也就是后面的 000000000000000000000004,它有12个字节

00000000:固定命令;

00000000:错误代码;

00000004:PC节点IP,当设置为0时,会自动获取节点IP

当前我的机器IP地址是:

格式中的clientnode就是指PC的IP地址中的最后一位,也就是4,转换成16进制就是4,它占4个字节,所以是 00000004,每2位算一个字节。其实这个地址写什么都可以,PLC并不会去校验客户端的IP地址,只是一个表示占位格式而已。

发送报文共占20个字节。

2)接收报文分析如下:

报文格式:

 发送:46 49 4E 53 00 00 00 0C 00 00 00 00 00 00 00 00 00 00 00 04
 接收:46 49 4E 53 00 00 00 10 00 00 00 01 00 00 00 00 00 00 00 04 00 00 00 0A

46494E53:ASCII编码就是FINS;

00000010:指后面跟的字节长度;16个字节,不包括自己的长度

00000001:固定命令;

00000000:错误代码;

00000004:本机电脑节点IP;

0000000A:PLC节点IP

servernode就是PLC的IP地址的最后一位,其实clientnode和servernode写什么都可以,也只是表示一个占位。

接收报文共24个字节,比发送多了servernode(4个字节)

4、读取和写入CIO区的2进制数据

  设置CIO0.0到0.5的6个数据,分别是111101

 1、读取指令,读取CIO区0.0开始的6个bool数据

发送:46 49 4E 53 00 00 00 1A 00 00 00 02 00 00 00 00 80 00 02 00 0A 00 00 04 00 00 01 01 30 00 00 00 00 06 
接收:46 49 4E 53 00 00 00 1C 00 00 00 02 00 00 00 00 C0 00 02 00 0A 00 00 04 00 00 01 01 00 00 01 01 01 01 00 01   

1)发送:46 49 4E 53 00 00 00 1A 00 00 00 02 00 00 00 00 80 00 02 00 0A 00 00 04 00 00 01 01 30 00 00 00 00 06 

发送报文格式

发送报文分析如下:

46 49 4E 53 00 00 00 1A 00 00 00 02 00 00 00 00 80 00 02 00 0A 00 00 04 00 00 01 01 30 00 00 00 00 06

46494E53:ASCII编码:FINS;

0000001A:指后面跟的字节长度;26个字节,不包括自己的长度

00000002:固定命令;

00000000:错误代码,00000000表示没有错误

80:ICF,固定值0x80;

00:RSV,固定值;

02:GCT,固定值;

00:PLC网络地址;

0A:PLC节点地址,PLC的IP地址最后一位

00:PLC单元地址;

00:PC网络地址;

04:PC节点地址,客户端IP地址最后一位

00:PC单元地址;

00:SID,固定值;

0101:读指令;

30:读地址区(D位:02,D字:82,W位:31,C位:30,W字:B1,C字:B0);

000000:起始地址,占3个字节

0006:读个数,占2个字节

--------------------------------------------------------------------------------------------------------------------------------

2)接收:46 49 4E 53 00 00 00 1C 00 00 00 02 00 00 00 00 C0 00 02 00 0A 00 00 04 00 00 01 01 00 00 01 01 01 01 00 01

接收报文格式

接收报文分析如下:

46 49 4E 53 00 00 00 1C 00 00 00 02 00 00 00 00 C0 00 02 00 0A 00 00 04 00 00 01 01 00 00 01 01 01 01 00 01

46494E53:ASCII编码:FINS;

0000001C:指后面跟的字节长度,1C转换成10进制就是28,就是指后面的字节长度是28个(56个字符,每2个字符为1个字节)

00000002:固定命令;

00000000:错误代码,全是0表示没有错误;

C0:ICF,固定值;

00:RSV,固定值;

02:GCT,固定值;

00:PLC网络地址;

0A:PLC节点地址;

00:PLC单元地址;

00:PC网络地址;

04:PC节点地址;

00:PC单元地址;

00:SID;

0101:读指令;

0000:读取成功标识;

01 01 01 01 00 01:读到的数据,这是2进制的数据,也就是C#中的bool类型,表示true,true,true,true,false,true,与内存存储区的数据一致。

2、写入指令,写入CIO区0.0开始的6个bool数据true, true, false, false, true,true

发送:46 49 4E 53 00 00 00 20 00 00 00 02 00 00 00 00 80 00 02 00 0A 00 00 04 00 00 01 02 30 00 00 00 00 06 01 01 00 00 01 01 
接收:46 49 4E 53 00 00 00 16 00 00 00 02 00 00 00 00 C0 00 02 00 0A 00 00 04 00 00 01 02 00 00

1)发送报文分析如下:

写入命令格式:

发送:46 49 4E 53 00 00 00 20 00 00 00 02 00 00 00 00 80 00 02 00 0A 00 00 04 00 00 01 02 30 00 00 00 00 06 01 01 00 00 01 01 

46494E53:ASCII编码:FINS;

00000020:指后面跟的字节长度,20转换成10进制就是32,表示后面有32个字节(64个字符);

00000002:固定命令;

00000000:错误代码,全0表示没有错误;

80:ICF,固定值;

00:RSV,固定值;

02:GCT,固定值;

00:PLC网络地址;

0A:PLC节点地址;

00:PLC单元地址;

00:PC网络地址;

04:PC节点地址;

00:PC单元地址;

00:SID;

0102:写指令;

30:写地址区(D位:02,D字:82,W位:31,C位:30,W字:B1,C字:B0);

000000:起始地址,即0.0开始的地址

0006:写入个数,占2个字节

01 01 00 00 01 01 :写入数据,具体来说表示true, true, false, false, true,true

2)接收报文分析如下:

返回命令如下

46 49 4E 53 00 00 00 16 00 00 00 02 00 00 00 00 C0 00 02 00 0A 00 00 04 00 00 01 02 00 00

46494E53:ASCII编码:FINS;

00000016:指后面跟的字节长度,表示后面的字节有22个字节

00000002:固定命令;

00000000:错误代码;

C0:ICF;

00:RSV;

02:GCT;

00:PLC网络地址;

0A:PLC节点地址;

00:PLC单元地址;

00:PC网络地址;

04:PC节点地址;

00:PC单元地址;

00:SID;

0102:写指令;

0000:写入成功标识,也就是说写入成功啦,没有错误。

以上读取或写入命令之前都必须先发送握手报文命令,而且只能发一次握手报文

5、读取和写入D区的ushort类型数据

首先设置内存区D区100的4个数据,注意D区设置的数据类型为10进制无符号的整数,对应C#中就是ushort类型。

1、读取D区100开始的4个数据

发送:46 49 4E 53 00 00 00 1A 00 00 00 02 00 00 00 00 80 00 02 00 0A 00 00 04 00 00 01 01 82 00 64 00 00 04
接收:46 49 4E 53 00 00 00 1E 00 00 00 02 00 00 00 00 C0 00 02 00 0A 00 00 04 00 00 01 01 00 00 00 7B 00 87 00 92 03 84

1)发送报文分析如下:

46 49 4E 53 00 00 00 1A 00 00 00 02 00 00 00 00 80 00 02 00 0A 00 00 04 00 00 01 01 82 00 64 00 00 04

46494E53:ASCII编码:FINS;

0000001A:指后面跟的字节长度;26个字节,不包括自己的长度

00000002:固定命令;

00000000:错误代码,表示没有错误

80:ICF;

00:RSV;

02:GCT;

00:PLC网络地址;

0A:PLC节点地址,PLC的IP地址最后一位

00:PLC单元地址;

00:PC网络地址;

04:PC节点地址,客户端IP地址最后一位

00:PC单元地址;

00:SID;

0101:读指令;

82:读地址区(D位:02,D字:82,W位:31,C位:30,W字:B1,C字:B0);

006400:起始地址,100转成16进制就是64,占3个字节,就是006400

0004:读取的个数,占2个字节

2)接收报文分析如下:

46 49 4E 53 00 00 00 1E 00 00 00 02 00 00 00 00 C0 00 02 00 0A 00 00 04 00 00 01 01 00 00 00 7B 00 87 00 92 03 84

46494E53:ASCII编码:FINS;

0000001E:指后面跟的字节度 

00000002:固定命令;

00000000:错误代码,全是0表示没有错误;

C0:ICF,固定值;

00:RSV,固定值;

02:GCT,固定值;

00:PLC网络地址;

0A:PLC节点地址;

00:PLC单元地址;

00:PC网络地址;

04:PC节点地址;

00:PC单元地址;

00:SID;

0101:读指令;

0000:读取成功标识;

00 7B 00 87 00 92 03 84:读到的数据,00 7B转换成10进制就是12300 87就是135,00 92就是146,03 84就是900

这里注意10进制的无符号整数占2个字节,也就是PLC中的一个寄存器,PLC中的word,占一个寄存器,在C#占2个字节,用来表示整数(不用带小数)

2、向D区30的地址写入4个ushort数据110, 120, 130, 140

发送:46 49 4E 53 00 00 00 22 00 00 00 02 00 00 00 00 80 00 02 00 0A 00 00 04 00 00 01 02 82 00 1E 00 00 04 00 6E 00 78 00 82 00 8C 
接收:46 49 4E 53 00 00 00 16 00 00 00 02 00 00 00 00 C0 00 02 00 0A 00 00 04 00 00 01 02 00 00

写入成功

发送报文分析

46 49 4E 53 00 00 00 22 00 00 00 02 00 00 00 00 80 00 02 00 0A 00 00 04 00 00 01 02 82 00 1E 00 00 04 00 6E 00 78 00 82 00 8C 

46494E53:ASCII编码:FINS;

00000022:指后面跟的字节长度 ;

00000002:固定命令;

00000000:错误代码,全0表示没有错误;

80:ICF,固定值;

00:RSV,固定值;

02:GCT,固定值;

00:PLC网络地址;

0A:PLC节点地址;

00:PLC单元地址;

00:PC网络地址;

04:PC节点地址;

00:PC单元地址;

00:SID;

0102:写指令;

82:写地址区(D位:02,D字:82,W位:31,C位:30,W字:B1,C字:B0);

001E00:起始地址,即0.0开始的地址

0004:写入个数,占2个字节

00 6E 00 78 00 82 00 8C:写入数据,具体来说表示00 6E=》110, 00 78=》120, 00 82=》130, 00 8C=》140


接收报文分析

46 49 4E 53 00 00 00 16 00 00 00 02 00 00 00 00 C0 00 02 00 0A 00 00 04 00 00 01 02 00 00

46494E53:ASCII编码:FINS;

00000016:指后面跟的字节长度,表示后面的字节有22个字节

00000002:固定命令;

00000000:错误代码;

C0:ICF;

00:RSV;

02:GCT;

00:PLC网络地址;

0A:PLC节点地址;

00:PLC单元地址;

00:PC网络地址;

04:PC节点地址;

00:PC单元地址;

00:SID;

0102:写指令;

0000:写入成功标识,也就是说写入成功啦,没有错误。

以上读取或写入命令之前都必须先发送握手报文命令,而且只能发一次握手报文

6、读取和写入H区的short类型数据

 设置H区的4个数据

1、读取H区100开始的4个short类型的数据

发送:46 49 4E 53 00 00 00 1A 00 00 00 02 00 00 00 00 80 00 02 00 0A 00 00 04 00 00 01 01 B2 00 64 00 00 04
接收:46 49 4E 53 00 00 00 1E 00 00 00 02 00 00 00 00 C0 00 02 00 0A 00 00 04 00 00 01 01 00 00 00 6E 00 6F FF 90 FF 8F 

1)发送报文分析如下:

46 49 4E 53 00 00 00 1A 00 00 00 02 00 00 00 00 80 00 02 00 0A 00 00 04 00 00 01 01 B2 00 64 00 00 04

46494E53:ASCII编码:FINS;

0000001A:指后面跟的字节长度;26个字节,不包括自己的长度

00000002:固定命令;

00000000:错误代码,表示没有错误

80:ICF;

00:RSV;

02:GCT;

00:PLC网络地址;

0A:PLC节点地址,PLC的IP地址最后一位

00:PLC单元地址;

00:PC网络地址;

04:PC节点地址,客户端IP地址最后一位

00:PC单元地址;

00:SID;

0101:读指令;

B2:读地址区(D位:02,D字:82,W位:31,C位:30,W字:B1,C字:B0,H字:B2);

006400:起始地址,100转成16进制就是64,占3个字节,就是006400

0004:读取的个数,占2个字节

2)接收报文分析如下:

46 49 4E 53 00 00 00 1E 00 00 00 02 00 00 00 00 C0 00 02 00 0A 00 00 04 00 00 01 01 00 00 00 6E 00 6F FF 90 FF 8F

46494E53:ASCII编码:FINS;

0000001E:指后面跟的字节度 

00000002:固定命令;

00000000:错误代码,全是0表示没有错误;

C0:ICF,固定值;

00:RSV,固定值;

02:GCT,固定值;

00:PLC网络地址;

0A:PLC节点地址;

00:PLC单元地址;

00:PC网络地址;

04:PC节点地址;

00:PC单元地址;

00:SID;

0101:读指令;

0000:读取成功标识;

00 6E 00 6F FF 90 FF 8F:读到的数据,00 6E转换成10进制就是110。00 6F就是111,FF 90就是65424,FF 8F就是65423,这里要将65424-65536=-112,同样65423-65536=-113,short的表示范围是 -32,768 到 32,767,表示有符号 16 位整数,ushort:代表有符号的16位整数,范围从0 到 65,535,这就也说明了,我们需要对返回的数据进行有效的处理,这个留着在后面的通讯库封装代码中去处理。

 

 2、向H区30的地址写入4个short数据,分别是-98,654,-800,327

发送:46 49 4E 53 00 00 00 22 00 00 00 02 00 00 00 00 80 00 02 00 0A 00 00 04 00 00 01 02 B2 00 1E 00 00 04 FF 9E 02 8E FC E0 01 47 
接收:46 49 4E 53 00 00 00 16 00 00 00 02 00 00 00 00 C0 00 02 00 0A 00 00 04 00 00 01 02 00 00

发送报文分析

46 49 4E 53 00 00 00 22 00 00 00 02 00 00 00 00 80 00 02 00 0A 00 00 04 00 00 01 02 B2 00 1E 00 00 04 FF 9E 02 8E FC E0 01 47  

46494E53:ASCII编码:FINS;

00000022:指后面跟的字节长度 ;

00000002:固定命令;

00000000:错误代码,全0表示没有错误;

80:ICF,固定值;

00:RSV,固定值;

02:GCT,固定值;

00:PLC网络地址;

0A:PLC节点地址;

00:PLC单元地址;

00:PC网络地址;

04:PC节点地址;

00:PC单元地址;

00:SID;

0102:写指令;

82:写地址区(D位:02,D字:82,W位:31,C位:30,W字:B1,C字:B0);

001E00:起始地址,即0.0开始的地址

0004:写入个数,占2个字节

FF 9E 02 8E FC E0 01 47:写入数据,具体来说表示FF 9E=》-98, 02 8E=》654,FC E0 =》-800,01 47=》327

同样的可以看到写入的负数,前面的第一个是F,这是因为负数用补码表示。


接收报文分析

46 49 4E 53 00 00 00 16 00 00 00 02 00 00 00 00 C0 00 02 00 0A 00 00 04 00 00 01 02 00 00

46494E53:ASCII编码:FINS;

00000016:指后面跟的字节长度,表示后面的字节有22个字节

00000002:固定命令;

00000000:错误代码;

C0:ICF;

00:RSV;

02:GCT;

00:PLC网络地址;

0A:PLC节点地址;

00:PLC单元地址;

00:PC网络地址;

04:PC节点地址;

00:PC单元地址;

00:SID;

0102:写指令;

0000:写入成功标识,也就是说写入成功啦,没有错误。

以上读取或写入命令之前都必须先发送握手报文命令,而且只能发一次握手报文

7、读取和写入W区的float类型数据

float类型的数据是包括正负整数和正负小数,如40,-98,2.34,-89.53

设置W区的5个数据

1、读取W区100开始的5个float数据

发送:46 49 4E 53 00 00 00 1A 00 00 00 02 00 00 00 00 80 00 02 00 0A 00 00 04 00 00 01 01 B1 00 64 00 00 0A
接收:46 49 4E 53 00 00 00 2A 00 00 00 02 00 00 00 00 C0 00 02 00 0A 00 00 04 00 00 01 01 00 00 47 AE 3F 81 8F 5C BF 82 00 00 42 F6 00 00 C4 75 C0 00 44 02

1)发送报文分析如下:
46 49 4E 53 00 00 00 1A 00 00 00 02 00 00 00 00 80 00 02 00 0A 00 00 04 00 00 01 01 B1 00 64 00 00 0A
46494E53:ASCII编码:FINS;
0000001A:指后面跟的字节长度;26个字节,不包括自己的长度
00000002:固定命令;
00000000:错误代码,表示没有错误
80:ICF;
00:RSV;
02:GCT;
00:PLC网络地址;
0A:PLC节点地址,PLC的IP地址最后一位
00:PLC单元地址;
00:PC网络地址;
04:PC节点地址,客户端IP地址最后一位
00:PC单元地址;
00:SID;
0101:读指令;
B1:读地址区(D位:02,D字:82,W位:31,C位:30,W字:B1,C字:B0,H字:B2);
006400:起始地址,100转成16进制就是64,占3个字节,就是006400
000A:读取的个数,占2个字节,这里为什么是A,即10个,因为一个float类型是占2个寄存器的,那么5个float就是10个寄存器,所以是A,需要注意这个不同的地方。

2)接收报文分析如下:
46 49 4E 53 00 00 00 2A 00 00 00 02 00 00 00 00 C0 00 02 00 0A 00 00 04 00 00 01 01 00 00 47 AE 3F 81 8F 5C BF 82 00 00 42 F6 00 00 C4 75 C0 00 44 02
46494E53:ASCII编码:FINS;
0000001E:指后面跟的字节度 
00000002:固定命令;
00000000:错误代码,全是0表示没有错误;
C0:ICF,固定值;
00:RSV,固定值;
02:GCT,固定值;
00:PLC网络地址;
0A:PLC节点地址;
00:PLC单元地址;
00:PC网络地址;
04:PC节点地址;
00:PC单元地址;
00:SID;
0101:读指令;
0000:读取成功标识;
47 AE 3F 81 8F 5C BF 82 00 00 42 F6 00 00 C4 75 C0 00 44 02:读到的数据,47 AE 3F 81是第一个数据, 8F 5C BF 82是第二个数据,00 00 42 F6是第三个数据,00 00 C4 75是第四个数据,C0 00 44 02是第五个数据,这里为什么是这样的数据,如果转成10进制都不是当初设置的1.01,-1.02,123,-980,523,这是因为存在大小端,字节序的问题,这需要在程序后端进行处理,这里返回的数据是没有问题的,等后面在我的封装通讯库的进行处理,保证响当当的没有问题。

2、向W区30的地址写入5个数据120, -130, -140,15.6f,-89.4f

发送:46 49 4E 53 00 00 00 2E 00 00 00 02 00 00 00 00 80 00 02 00 0A 00 00 04 00 00 01 02 B1 00 1E 00 00 0A 00 00 42 F0 00 00 C3 02 00 00 C3 0C 99 9A 41 79 CC CD C2 B2
接收:46 49 4E 53 00 00 00 16 00 00 00 02 00 00 00 00 C0 00 02 00 0A 00 00 04 00 00 01 02 00 00

发送报文分析
46 49 4E 53 00 00 00 2E 00 00 00 02 00 00 00 00 80 00 02 00 0A 00 00 04 00 00 01 02 B1 00 1E 00 00 0A 00 00 42 F0 00 00 C3 02 00 00 C3 0C 99 9A 41 79 CC CD C2 B2  

46494E53:ASCII编码:FINS;
0000002E:指后面跟的字节长度 ;
00000002:固定命令;
00000000:错误代码,全0表示没有错误;
80:ICF,固定值;
00:RSV,固定值;
02:GCT,固定值;
00:PLC网络地址;
0A:PLC节点地址;
00:PLC单元地址;
00:PC网络地址;
04:PC节点地址;
00:PC单元地址;
00:SID;
0102:写指令;
B1:写地址区(D位:02,D字:82,W位:31,C位:30,W字:B1,C字:B0);
001E00:起始地址, 
000A:写入个数,占2个字节,要写入5个float的,每个float占2个寄存器,5个就是10个寄存器,所以是A;
00 00 42 F0 00 00 C3 02 00 00 C3 0C 99 9A 41 79 CC CD C2 B2:写入数据,具体来说00 00 42 F0是第一个, 00 00 C3 02是第二个, 00 00 C3 0C是第三个, 99 9A 41 79是第四个, CC CD C2 B2是第五个。但这5个数据都不是120, -130, -140,15.6f,-89.4f转换成16进制的表示,这也是因为存在大小端,字节序的问题,在后面的通讯库封装中来处理,发送的报文指令绝对没有错。
 

接收报文分析
46 49 4E 53 00 00 00 16 00 00 00 02 00 00 00 00 C0 00 02 00 0A 00 00 04 00 00 01 02 00 00

ASCII编码:FINS;
00000016:指后面跟的字节长度,表示后面的字节有22个字节
00000002:固定命令;
00000000:错误代码;
C0:ICF;
00:RSV;
02:GCT;
00:PLC网络地址;
0A:PLC节点地址;
00:PLC单元地址;
00:PC网络地址;
04:PC节点地址;
00:PC单元地址;
00:SID;
0102:写指令;
0000:写入成功标识,也就是说写入成功啦,没有错误。
以上读取或写入命令之前都必须先发送握手报文命令,而且只能发一次握手报文

4、小结

这节,我们读取和写入了CIO区,D区,H区,W区的二进制数据,ushort数据,short数据,float数据,充分熟悉了fins指令的格式要求,都有固定的格式。

  FINS协议是一种基于TCP/IP网络通信的实时通信协议.能够实现欧姆龙工业设备之间的数据交换和控制指令传输。它采用了客户端/服务器模型,客户端发送请求,服务器返回响应,通过建立连接、传输数据包来实现设备之间的通信。
  FINS协议的核心是消息和指令的传输。消息格式包括消息头、命令和数据区。消息头定义了消息的类型、长度和地址等信息。命令部分包含了具体的指令内容,如读取数据、写入数据或执行其他操作。数据区则是存储实际的数据信息。

注意几点:

1)读取命令0101,写入命令0102,固定的,不能改

2)存储区代号:(D位:02,D字:82,W位:31,C位:30,W字:B1,C字:B0,H字:B2),固定的不能改

3)协议头部:46 49 4E 53,转换成ascii码就是fins

码字不易,截图不易,写作不易,共享不易,请多多点赞支持。



 

相关文章:

C#上位机与欧姆龙PLC的通信06---- HostLink协议(FINS版)

1、介绍 对于上位机开发来说,欧姆龙PLC支持的主要的协议有Hostlink协议,FinsTcp/Udp协议,EtherNetIP协议,本项目使用Hostlink协议。 Hostlink协议是欧姆龙PLC与上位机链接的公开协议。上位机通过发送Hostlink命令,可…...

认识SpringBoot项目中的Starter

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: 循序渐进学SpringBoot ✨特色专栏&…...

ChatGPT 4.0真的值得花钱买入吗?

性能提升: ChatGPT 4.0的推出不仅意味着更先进的技术,还代表着更强大的性能。相较于3.5,4.0在处理任务时更为高效,响应更迅速。 更智能的理解: 随着版本的升级,ChatGPT 4.0对语境的理解能力得到了进一步的…...

vue3对比vue2是怎样的

一、前言 Vue 3通过引入Composition API、升级响应式系统、优化性能等一系列的改进和升级,提供了更好的开发体验和更好的性能,使得开发者能够更方便地开发出高质量的Web应用。它在Vue.js 2的基础上进行了一系列的改进和升级,以提供更好的性能、更好的开发体验和更好的扩展性…...

openGauss学习笔记-184 openGauss 数据库运维-升级-升级验证

文章目录 openGauss学习笔记-184 openGauss 数据库运维-升级-升级验证184.1 验证项目的检查表184.2 升级版本查询184.2.1 验证步骤 184.3 检查升级数据库状态184.3.1 验证步骤 openGauss学习笔记-184 openGauss 数据库运维-升级-升级验证 本章介绍升级完成后的验证操作。给出验…...

[Verilog语言入门教程] Verilog 减法器 (半减器, 全减器, 加减共用)

依公知及经验整理,原创保护,禁止转载。 专栏 《元带你学Verilog》 <<<< 返回总目录 <<<< “逻辑设计是一门艺术,它需要创造力和想象力。” - 马克张伯伦(Mark Zwolinski) 减法器是数字电路中常见的组件,用于减去两个二进制数的和。 在Verilog中…...

预编译仓库中的 Helm Chart

背景 内网部署项目, 没法直接hlem install , 需要提前看看有哪些镜像, 拉到本地看看 要使用预编译仓库中的 Helm Chart&#xff0c;你可以使用 helm fetch 命令来将 Chart 下载到本地&#xff0c;并使用 helm template 命令来预编译该 Chart。 首先&#xff0c;你可以使用以…...

Python requests get和post方法发送HTTP请求

requests.get() requests.get() 方法用于发送 HTTP GET 请求。下面介绍 requests.get() 方法的常用参数&#xff1a; url: 发送请求的 URL 地址。params: URL 中的查询参数&#xff0c;可以是字典或字符串。headers: 请求头信息。可以是字典类型&#xff0c;也可以是自定义的…...

在Cadence中单独添加或删除器件与修改网络的方法

首先需要在设置中使能 ,添加或修改逻辑选项。 添加或删除器件&#xff0c;点击logic-part&#xff0c;选择需要添加或删除的器件&#xff0c;这里的器件必须是PCB中已经有的器件&#xff0c;Refdes中输入添加或删除的器件标号&#xff0c;点击Add添加。 添加完成后就会显示在R1…...

轻松调整视频时长,创意与技术的新篇章

传统的视频剪辑工具往往难以精确控制时间&#xff0c;而【媒体梦工厂】凭借其先进的算法和界面设计&#xff0c;让视频时长的调整变得简单而精确&#xff0c;助你释放无限的创意&#xff0c;用技术为你的创意插上翅膀&#xff0c;让每一秒都有意义。 所需工具&#xff1a; 一…...

树与二叉树笔记整理

摘自小红书 ## 树与二叉树 ## 排序总结...

如何自动生成 API 接口文档 - 一份详细指南

本篇文章详细教你如何使用 Apifox 的 IDEA 插件实现自动生成接口代码。好处简单总结有以下几点&#xff1a; 自动生成接口文档&#xff1a; 不用手写&#xff0c;一键点击就可以自动生成文档&#xff0c;当有更新时&#xff0c;点击一下就可以自动同步接口文档&#xff1b;代码…...

【CF比赛记录】—— Good Bye 2023(A、B、C)

&#x1f30f;博客主页&#xff1a;PH_modest的博客主页 &#x1f6a9;当前专栏&#xff1a;CF比赛记录 &#x1f48c;其他专栏&#xff1a; &#x1f534;每日一题 &#x1f7e1; cf闯关练习 &#x1f7e2; C语言跬步积累 &#x1f308;座右铭&#xff1a;广积粮&#xff0c;缓…...

MySQL:索引

MySQL官方对索引的定义为: 索引 (Index) 是帮助MySQL高效获取数据的数据结构。 提取句子主干&#xff0c;就可以得到索引的本质:索引是数据结构。 1. 什么是索引&#xff0c;索引的作用 索引是一种用于快速查询和检索数据的数据结构&#xff0c;帮助mysql提高查询效率的数据…...

CUMT--Java复习--核心类

目录 一、装箱与拆箱 二、“”与equals 三、字符串类 1、String、StringBuffer、StringBuilder的区别 2、String类 3、StringBuffer类 4、StringBuilder类 四、类与类之间关系 一、装箱与拆箱 基本类型与对应封装类之间能够自动进行转换&#xff0c;本质就是Java的自…...

Redis:原理速成+项目实战——Redis实战4(解决Redis缓存穿透、雪崩、击穿)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;Redis&#xff1a;原理项目实战——Redis实战3&#xff08;Redis缓存最佳实践&#xff08;问题解析高级实现&#xff09;&#x…...

后端开发——jdbc的学习(一)

上篇结束了Mysql数据库的基本使用&#xff0c;本篇开始对JDBC进行学习总结&#xff0c;开始先简单介绍jdbc的基本使用&#xff0c;以及简单的练习&#xff1b;后续会继续更新&#xff01;以下代码可以直接复制到idea中运行&#xff0c;便于理解和练习。 JDBC的概念 JDBC&#…...

阿里云免费SSL证书时长只有3个月,应对方法来了

阿里云免费SSL证书签发有效期从12个月缩短至3个月&#xff1a;尊敬的用户&#xff0c;根据供应商变更要求&#xff0c;免费证书&#xff08;默认证书&#xff09;的签发有效期将由12个月缩短至3个月。 免费证书&#xff08;升级证书&#xff09;的有效期不会改变。 没错&#…...

Flutter 中使用 ICON

Flutter Icon URL &#xff1a; https://fonts.google.com/icons&#xff1a; 在Flutter中使用 Icon 步骤如下&#xff1a; 导入图标库 在Dart 文件中导入 material.dart 包&#xff0c;该包包含了 Flutter 的图标库。 import package:flutter/material.dart;使用图标组件 …...

百度编辑器常用设置

1、创建编辑器 UE.getEditor(editor, { initialFrameWidth:"100%" //初始化选项 }) 精简版 UE.getEditor(editor) 2、删除编辑器 UE.getEditor(editor).destroy(); 3、使编辑器获得焦点 UE.getEditor(editor).focus(); 4、获取编辑器内容 UE.getEditor(editor).getCo…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...