一、握手协议
FinsTCP通信协议,与ModbusTCP和MC协议有一个不同地方在于,当我们完成TCP连接后,不能直接进行读取或写入,需要有一个握手过程,以保证通信安全。这点与西门子S7协议类似,S7协议会有两次握手验证,FinsTCP只需要一次即可。握手命令如下所示:发送报文格式:


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

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



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


五、通信测试
我们以读取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#上位机开发实战指南》。
大家如果需要购买,可以通过京东旗舰店购买。
-END-
上位机技术文章,请关注公众号【上位机Guide】上位机技术交流,请添加本人微信【fuswj001】感谢大家阅读,关注我,分享上位机开发技术。