TwinCAT3 Modbus-TCP Client/Server使用

2023-12-15 00:15

本文主要是介绍TwinCAT3 Modbus-TCP Client/Server使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、环境配置和准备

1、PLC中安装TF6250-Modbus-TCP库

2、勾选TF6250的license

3、PLC工程中添加Tc2_ModbusSrv库文件

4、分别创建测试ModbusTCP测试的Server和Client程序

二、PLC作为Client端

1、设置测试电脑IP地址

2、运行MobusTCP测试工具

3、PLC端程序编写

(1)读取离散量输入

(2)读取线圈

(3)单个线圈写操作

(4)多个线圈写操作

(5)读取输入寄存器值

(6)读取保持寄存器值

(7)单个保持寄存器写操作

(8)多个保持寄存器写操作

三、PLC作为Server端

1、PLC程序

(1)寄存器变量定义

2、Client客户端工具

3、通讯测试

(1)客户端写操作

四、PLC中使用服务端和客户端程序进行寄存器操作

1、PLC程序

(1)服务端程序

(2)客户端程序

2、通讯测试

(1)寄存器说明

(2)PLC的Client程序读操作

(3)PLC的Client程序写操作

五、测试工程下载


一、环境配置和准备

1、PLC中安装TF6250-Modbus-TCP库

PLC地址

安装库文件

PLC硬件环境设置、库文件安装、防火墙设置等,参见博客文章:TwinCAT3中ModbusTCP Server和C# Client连接-CSDN博客

2、勾选TF6250的license

3、PLC工程中添加Tc2_ModbusSrv库文件

4、分别创建测试ModbusTCP测试的Server和Client程序

将创建的程序添加到Task中。

二、PLC作为Client端

1、设置测试电脑IP地址

测试电脑IP地址和PLC的IP地址在一个网段内。

2、运行MobusTCP测试工具

使用测试工具ModSim32,创建ModbusTCP Server服务端。端口号默认502,测试软件默认IP地址是计算机本地地址。

3、PLC端程序编写

定义变量:ModbusTCP Server服务端ip地址

Server_IpAddress	:STRING:='192.168.1.33';        //ModbusTCP Server服务端ip地址

(1)读取离散量输入

定义变量

	02: Input Status 读取//fbReadInputs      : FB_MBReadInputs;						(*读取离散量输入功能块*)bReadInputs       : BOOL;									(*读取离散量输入执行条件*)nQuantityinput    : WORD:=1 ;								(*读取离散量输入个数*)nMBAddrinput      : WORD:=1 ;								(*读取离散量输入起始地址*)arrDatainput      : BYTE;									(*存放离散量输入的值*)

程序

nUnitID:Modbus-Tcp从站号。如果实际中不知道从站号多少,默认写1就行。

fbReadInputs(//sIPAddr:='169.254.0.1' , 				//modsim32的IP地址sIPAddr:=Server_IpAddress , 				//modsim32的IP地址nTCPPort:=502, 							//Modbus-Tcp端口号nUnitID:=1 , 							//Modbus-Tcp从站号nQuantity:=nQuantityinput , 			//读取离散量输入个数nMBAddr:= nMBAddrinput, 				//读取离散量输入 Modbus起始地址cbLength:= SIZEOF(arrDatainput), 		//存放离散量输入变量的个数pDestAddr:=ADR(arrDatainput), 			//存放离散量输入变量指针起始地址bExecute:=bReadInputs , 				//读取离散量输入执行条件tTimeout:=T#1S ,    bBusy=> , bError=> , nErrId=> , cbRead=> );

运行测试1,单个离散量读操作:

对10002写1

PLC读取

读取个数是1,nQuantityinput值为1

起始地址nMBAddrinput写1对应的寄存器是10002。离散变量实际地址=10001+nMBAddrinput

读取

运行测试2,多个离散量读操作:

对10002写1、10003写1、10004写1

PLC读取

设置读取个数是3。读取出来的值是7。(三个位都为1,就是7)

(2)读取线圈

定义变量

    fbReadCoils       			: FB_MBReadCoils;				(*读取线圈功能块*) bReadCoils        			: BOOL; 						(*读取线圈执行条件*)      nQuantitycoils    			: WORD :=3;  					(*读取线圈个数*) nMBAddrcoils      			: WORD :=1;  					(*读取线圈起始地址*) arrDatacoils      			: BYTE;							(*存放线圈的值*)

PLC程序

fbReadCoils(//sIPAddr:='169.254.0.1' , 				//modsim32的IP地址sIPAddr:=Server_IpAddress , 				//modsim32的IP地址nTCPPort:=502 ,							//Modbus-Tcp端口号 nUnitID:=1 , 							//Modbus-Tcp从站号nQuantity:=nQuantitycoils , 			//读取线圈个数nMBAddr:=nMBAddrcoils , 				//读取线圈 Modbus起始地址cbLength:=SIZEOF(arrDatacoils) , 		//存放线圈变量的个数pDestAddr:=ADR(arrDatacoils) , 			//存放线圈变量指针起始地址bExecute:=bReadCoils , 					//读取线圈执行条件tTimeout:= T#1S, bBusy=> , bError=>, nErrId=> , cbRead=> );

运行测试,多个线圈读操作:

对线圈00005/00006/0007/0008/00009写1操作

PLC

nMBAddrcoils:读取线圈的地址

nQuantitycoils:读取的线圈个数

线圈的实际地址=00001+nMBAddrcoils。

00005对应的nMBAddrcoils地址设置就是4。

5个线圈的值都是ON,即31

PLC中数据显示,2进制、10进制、16进制显示设置

(3)单个线圈写操作

定义变量

    fbWriteSingleCoil       	: FB_MBWriteSingleCoil;			(*写入单个线圈功能块*)bWriteSingleCoil            : BOOL;							(*写入单个线圈执行条件*)nMBAddrWriteSingleCoil      : WORD := 3;					(*写入单个线圈Modbus 地址*)nValueWriteSingleCoil       : WORD := 16#FF00;				(*16#FF00:True;16#0000:False*)

PLC程序

fbWriteSingleCoil(//sIPAddr:='169.254.0.1' , 				//modsim32的IP地址sIPAddr:=Server_IpAddress , 				//modsim32的IP地址nTCPPort:= 502, 						//Modbus-Tcp端口号nUnitID:= 1, 							//Modbus-Tcp从站号nMBAddr:=nMBAddrWriteSingleCoil , 		//写入单个线圈Modbus起始地址nValue:=nValueWriteSingleCoil , 		//写入单个线圈的值:16#FF00:True;16#0000:FalsebExecute:=bWriteSingleCoil , 			//写入单个线圈执行条件tTimeout:=T#1S , bBusy=> , bError=> , nErrId=> );

运行测试,单个线圈写操作:

对线圈00004写操作

线圈地址nMBAddrWriteSingleCoil值设置:3。(线圈地址=00001+nMBAddrWriteSingleCoil)

nValueWriteSingleCoil值设置:

TRUE:16#FF00,即10进制65280。

FALSE:16#0000,即10进制0。

(4)多个线圈写操作

变量定义

  	fbWriteCoils       			: FB_MBWriteCoils;				(*写入线圈功能块*)bWriteCoils      			: BOOL;							(*写入线圈执行条件*)nQuantityWriteCoils 		: WORD := 10;					(*写入离散量输入个数*)nMBAddrWriteCoils   		: WORD := 14;					(*写入离散量输入起始地址*)arrDataWriteCoils   		: ARRAY[1..2] OF  BYTE  := [16#11, 16#33];(*写入离散量输入的值*)

PLC程序

fbWriteCoils(//sIPAddr:='169.254.0.1' , 				//modsim32的IP地址sIPAddr:=Server_IpAddress , 				//modsim32的IP地址nTCPPort:=502, 							//Modbus-Tcp端口号nUnitID:=1 , 							//Modbus-Tcp从站号nQuantity:= nQuantityWriteCoils , 		//写入线圈个数nMBAddr:=nMBAddrWriteCoils , 			//写入线圈Modbus起始地址cbLength:=SIZEOF(arrDataWriteCoils), 	//写入线圈的变量个数pSrcAddr:=ADR(arrDataWriteCoils), 		//写入线圈的变量指针起始地址bExecute:=bWriteCoils , 				//写入线圈的执行条件tTimeout:=T#1S , bBusy=> , bError=> , nErrId=> );

运行测试,多个线圈写操作:

写16个线圈,线圈地址从00006开始。(00001+nMBAddrWriteCoils,nMBAddrWriteCoils设置值为5)。

1个BYTE是8位,8位都是1即BYTE值是255。

BYTE数组arrDataWriteCoils长度为2、即16位。最多可以写16个线圈操作。

注意:的线圈BYTE个数要和数组长度相同,16个线圈2个BYTE。对应否则会报错。)

(5)读取输入寄存器值

变量定义

    fbReadInputRegs    : FB_MBReadInputRegs;		(*读取输入寄存器功能块*)bReadInputRegs     : BOOL;						(*读取输入寄存器执行条件*)nQuantityInputRegs : WORD := 3;					(*读取输入寄存器个数*)nMBAddrInputRegs   : WORD:= 2;					(*读取输入寄存器起始地址*)arrDataInputRegs   : ARRAY [1..3] OF WORD;		(*存放输入寄存器的值*)

PLC程序

fbReadInputRegs(//sIPAddr:='169.254.0.1' , 				//modsim32的IP地址sIPAddr:=Server_IpAddress , 				//modsim32的IP地址nTCPPort:=502, 							//Modbus-Tcp端口号nUnitID:=1, 							//Modbus-Tcp从站号nQuantity:=nQuantityInputRegs, 			//读取输入寄存器个数nMBAddr:=nMBAddrInputRegs  , 			//读取输入寄存器Modbus起始地址cbLength:= SIZEOF(arrDataInputRegs),	//存放输入寄存器变量的个数和指针起始地址pDestAddr:=ADR(arrDataInputRegs), 		//存放输入寄存器变量指针起始地址bExecute:= bReadInputRegs  , 			//读取输入寄存器执行条件tTimeout:=T#1S , bBusy=> , bError=> , nErrId=> , cbRead=> );

运行测试,多个输入寄存器读操作:

给30003、30004、30005赋值

PLC读

寄存器地址30003=30001+nMBAddrInputRegs,nMBAddrInputRegs设置值2

多三个寄存器

注意:读的寄存器个数要和数组长度相同,否则会报错。)

(6)读取保持寄存器值

变量定义:

    fbReadRegs        			: FB_MBReadRegs;				(*读取保持寄存器功能块*)bReadRegs         			: BOOL;     					(*读取保持寄存器执行条件*) nQuantityregs     			: WORD:=2;   					(*读取保持寄存器个数*)nMBAddrregs       			: WORD:=24;   					(*读取保持寄存器起始地址*)arrDataregs       			: ARRAY [1..2] OF WORD;			(*存放保持寄存器的值*)

PLC程序:

fbReadRegs(//sIPAddr:='169.254.0.1' , 				//modsim32的IP地址sIPAddr:=Server_IpAddress , 				//modsim32的IP地址nTCPPort:=502,							//Modbus-Tcp端口号nUnitID:= 1, 							//Modbus-Tcp从站号nQuantity:=nQuantityregs, 				//读取保持寄存器个数nMBAddr:=nMBAddrregs , 					//读取保持寄存器Modbus起始地址cbLength:=SIZEOF(arrDataregs) , 		//存放保持寄存器变量的个数pDestAddr:=ADR(arrDataregs) , 			//存放保持寄存器变量指针起始地址bExecute:=bReadRegs, 					//读取保持寄存器执行条件tTimeout:= T#1S , bBusy=> , bError=> , nErrId=> , cbRead=> );

运行测试,多个保持寄存器读操作:

读保持寄存器40005、40006

寄存器首地址40005=40001+nMBAddrregs,设置nMBAddrregs值为4。读两个寄存器。

注意:读的寄存器个数要和数组长度相同,否则会报错。)

(7)单个保持寄存器写操作

变量定义:

 	fbWriteSingleReg            : FB_MBWriteSingleReg;			(*写入单个寄存器功能块*)bWriteSingleReg             : BOOL;							(*写入单个寄存器执行条件*)nMBAddrSingleReg            : WORD := 4;					(*写入单个寄存器Modbus 地址*)nValueSingleReg             : WORD := 16#1234;				(*写入单个寄存器数值*)

PLC程序:

fbWriteSingleReg(//sIPAddr:='169.254.0.1' , 				//modsim32的IP地址sIPAddr:=Server_IpAddress , 				//modsim32的IP地址nTCPPort:=502, 							//Modbus-Tcp端口号nUnitID:=1 , 							//Modbus-Tcp从站号nMBAddr:=nMBAddrSingleReg, 				//写入单个保持寄存器起始地址nValue:=nValueSingleReg, 				//写入单个寄存器数值bExecute:=bWriteSingleReg , 			//写入单个寄存器的执行条件tTimeout:=T#1S , bBusy=> , bError=> , nErrId=> );	

运行测试,单个保持寄存器写操作:

写保持寄存器40005。40005=40001+nMBAddrSingleReg,设置nMBAddrSingleReg值为4

(8)多个保持寄存器写操作

变量定义:

  	fbWriteRegs         		: FB_MBWriteRegs;				(*写入保持寄存器功能块*)bWriteRegs          		: BOOL;							(*写入保持寄存器个数*)nQuantityWriteRegs  		: WORD := 4;					(*写入保持寄存器个数*)nMBAddrWriteRegs    		: WORD := 4;					(*写入保持寄存器起始地址*)arrDataWriteRegs			: ARRAY[1..4] OF WORD := [1122, 3344, 5566, 7788];(*写入保持寄存器的值*)

PLC程序:

fbWriteRegs(//sIPAddr:='169.254.0.1' , 				//modsim32的IP地址sIPAddr:=Server_IpAddress , 				//modsim32的IP地址nTCPPort:=502, 							//Modbus-Tcp端口号nUnitID:=1 ,							//Modbus-Tcp从站号nQuantity:=nQuantityWriteRegs , 		//写入保持寄存器个数nMBAddr:= nMBAddrWriteRegs , 			//写入保持寄存器起始地址cbLength:= SIZEOF(arrDataWriteRegs), 	//写入变量的个数和指针起始地址pSrcAddr:=ADR(arrDataWriteRegs) , 		//写入变量指针起始地址bExecute:= bWriteRegs , 				//写入保持寄存器的执行条件tTimeout:=T#1S  , bBusy=> , bError=> , nErrId=> );

运行测试,多个保持寄存器写操作:

写保持寄存器40003、40004、40005,寄存器首地址40003=40001+nMBAddrWriteRegs,设置nMBAddrWriteRegs值2

注意:寄存器个数要和数组长度相同,否则会报错。)

三、PLC作为Server端

1、PLC程序

(1)寄存器变量定义

    arr1							AT%MB0			:ARRAY[1..5]		OF		WORD;		//起始地址是12289arr2							AT%MB10			:ARRAY[1..10]		OF		WORD;		//起始地址是12294

2、Client客户端工具

使用测试工具ModScan32模拟ModbusTCP Client客户端。

打开ModScan32

根据Server服务端PLC 中定义的寄存器,做如下设置

MB0对应的起始地址是12289。

寄存器说明:一个MW寄存器对应两个MB寄存器,比如MW0是MB0、MB1组成。一个12289对应一个MW0寄存器,即对应MB0、MB1。

3、通讯测试

(1)客户端写操作

客户端ModScan32对服务端PLC的寄存器写操作

PLC服务端接收的

(2)PLC服务端写操作

PLC寄存器写

客户端ModScan32接收的

四、PLC中使用服务端和客户端程序进行寄存器操作

1、PLC程序

(1)服务端程序

PLC服务端程序不变,就定义读写的寄存器变量

变量定义

    arr1							AT%MB0			:ARRAY[1..5]		OF		WORD;		//起始地址是12289arr2							AT%MB10			:ARRAY[1..10]		OF		WORD;		//起始地址是12294

(2)客户端程序

变量定义

Server_IpAddress	:STRING:='192.168.1.21';03: Holding Register 读取&写入fbReadRegs        			: FB_MBReadRegs;				(*读取保持寄存器功能块*)bReadRegs         			: BOOL;     					(*读取保持寄存器执行条件*) nQuantityregs     			: WORD:=5;   					(*读取保持寄存器个数*)nMBAddrregs       			: WORD:=12288;   				(*读取保持寄存器起始地址*)			//	寄存器地址=40001+nMBAddrregsarrDataregs       			: ARRAY [1..5] OF WORD;			(*存放保持寄存器的值*)fbWriteRegs         		: FB_MBWriteRegs;				(*写入保持寄存器功能块*)bWriteRegs          		: BOOL;							(*写入保持寄存器个数*)nQuantityWriteRegs  		: WORD := 10;					(*写入保持寄存器个数*)nMBAddrWriteRegs    		: WORD := 12294;				(*写入保持寄存器起始地址*)			//	寄存器地址=40001+nMBAddrWriteRegsarrDataWriteRegs			: ARRAY[1..10] OF WORD := [11, 22, 33, 44,55,66,77,88,99,100];		(*写入保持寄存器的值*)fbWriteSingleReg            : FB_MBWriteSingleReg;			(*写入单个寄存器功能块*)bWriteSingleReg             : BOOL;							(*写入单个寄存器执行条件*)nMBAddrSingleReg            : WORD := 4;					(*写入单个寄存器Modbus 地址*)nValueSingleReg             : WORD := 16#1234;				(*写入单个寄存器数值*)
//

PLC程序

fbReadRegs(//sIPAddr:='169.254.0.1' , 				//modsim32的IP地址sIPAddr:=Server_IpAddress , 				//modsim32的IP地址nTCPPort:=502,							//Modbus-Tcp端口号nUnitID:= 1, 							//Modbus-Tcp从站号nQuantity:=nQuantityregs, 				//读取保持寄存器个数nMBAddr:=nMBAddrregs , 					//读取保持寄存器Modbus起始地址cbLength:=SIZEOF(arrDataregs) , 		//存放保持寄存器变量的个数pDestAddr:=ADR(arrDataregs) , 			//存放保持寄存器变量指针起始地址bExecute:=bReadRegs, 					//读取保持寄存器执行条件tTimeout:= T#1S , bBusy=> , bError=> , nErrId=> , cbRead=> );fbWriteRegs(//sIPAddr:='169.254.0.1' , 				//modsim32的IP地址sIPAddr:=Server_IpAddress , 				//modsim32的IP地址nTCPPort:=502, 							//Modbus-Tcp端口号nUnitID:=1 ,							//Modbus-Tcp从站号nQuantity:=nQuantityWriteRegs , 		//写入保持寄存器个数nMBAddr:= nMBAddrWriteRegs , 			//写入保持寄存器起始地址cbLength:= SIZEOF(arrDataWriteRegs), 	//写入变量的个数和指针起始地址pSrcAddr:=ADR(arrDataWriteRegs) , 		//写入变量指针起始地址bExecute:= bWriteRegs , 				//写入保持寄存器的执行条件tTimeout:=T#1S  , bBusy=> , bError=> , nErrId=> );fbWriteSingleReg(//sIPAddr:='169.254.0.1' , 				//modsim32的IP地址sIPAddr:=Server_IpAddress , 				//modsim32的IP地址nTCPPort:=502, 							//Modbus-Tcp端口号nUnitID:=1 , 							//Modbus-Tcp从站号nMBAddr:=nMBAddrSingleReg, 				//写入单个保持寄存器起始地址nValue:=nValueSingleReg, 				//写入单个寄存器数值bExecute:=bWriteSingleReg , 			//写入单个寄存器的执行条件tTimeout:=T#1S , bBusy=> , bError=> , nErrId=> );	

2、通讯测试

(1)寄存器说明

一个MW寄存器对应两个MB寄存器,比如MW0对应12289、12289对应MB0、MB1

PLC 客户端程序中变量

读寄存器地址=40001+nMBAddrregs        则MB0对应设置nMBAddrregs12288

写寄存器地址=40001+nMBAddrWriteRegs        

(2)PLC的Client程序读操作

先给服务端的寄存器赋值

PLCServer程序读

(3)PLC的Client程序写操作

PLC客户端写寄存器

PLC服务端接收到客户端写的寄存器

五、测试工程下载

https://download.csdn.net/download/panjinliang066333/88609166

工程包括:

(1)客户端、服务端PLC程序

(2)TF6250-Modbus-TCP库文件安装软件

(3)ModbusTCP测试工具

模拟客户端:modscan32

模拟服务端:modsim32

(4)倍福官方简单测试参考

这篇关于TwinCAT3 Modbus-TCP Client/Server使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/494411

相关文章

SpringBoot中使用Flux实现流式返回的方法小结

《SpringBoot中使用Flux实现流式返回的方法小结》文章介绍流式返回(StreamingResponse)在SpringBoot中通过Flux实现,优势包括提升用户体验、降低内存消耗、支持长连... 目录背景流式返回的核心概念与优势1. 提升用户体验2. 降低内存消耗3. 支持长连接与实时通信在Sp

python使用库爬取m3u8文件的示例

《python使用库爬取m3u8文件的示例》本文主要介绍了python使用库爬取m3u8文件的示例,可以使用requests、m3u8、ffmpeg等库,实现获取、解析、下载视频片段并合并等步骤,具有... 目录一、准备工作二、获取m3u8文件内容三、解析m3u8文件四、下载视频片段五、合并视频片段六、错误

gitlab安装及邮箱配置和常用使用方式

《gitlab安装及邮箱配置和常用使用方式》:本文主要介绍gitlab安装及邮箱配置和常用使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1.安装GitLab2.配置GitLab邮件服务3.GitLab的账号注册邮箱验证及其分组4.gitlab分支和标签的

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

nginx启动命令和默认配置文件的使用

《nginx启动命令和默认配置文件的使用》:本文主要介绍nginx启动命令和默认配置文件的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录常见命令nginx.conf配置文件location匹配规则图片服务器总结常见命令# 默认配置文件启动./nginx

在Windows上使用qemu安装ubuntu24.04服务器的详细指南

《在Windows上使用qemu安装ubuntu24.04服务器的详细指南》本文介绍了在Windows上使用QEMU安装Ubuntu24.04的全流程:安装QEMU、准备ISO镜像、创建虚拟磁盘、配置... 目录1. 安装QEMU环境2. 准备Ubuntu 24.04镜像3. 启动QEMU安装Ubuntu4

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解

Windows下C++使用SQLitede的操作过程

《Windows下C++使用SQLitede的操作过程》本文介绍了Windows下C++使用SQLite的安装配置、CppSQLite库封装优势、核心功能(如数据库连接、事务管理)、跨平台支持及性能优... 目录Windows下C++使用SQLite1、安装2、代码示例CppSQLite:C++轻松操作SQ

SQL Server修改数据库名及物理数据文件名操作步骤

《SQLServer修改数据库名及物理数据文件名操作步骤》在SQLServer中重命名数据库是一个常见的操作,但需要确保用户具有足够的权限来执行此操作,:本文主要介绍SQLServer修改数据... 目录一、背景介绍二、操作步骤2.1 设置为单用户模式(断开连接)2.2 修改数据库名称2.3 查找逻辑文件名

Python常用命令提示符使用方法详解

《Python常用命令提示符使用方法详解》在学习python的过程中,我们需要用到命令提示符(CMD)进行环境的配置,:本文主要介绍Python常用命令提示符使用方法的相关资料,文中通过代码介绍的... 目录一、python环境基础命令【Windows】1、检查Python是否安装2、 查看Python的安