目录
一、环境配置和准备
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程序写操作
五、测试工程下载
PLC地址
安装库文件
PLC硬件环境设置、库文件安装、防火墙设置等,参见博客文章:TwinCAT3中ModbusTCP Server和C# Client连接-CSDN博客
将创建的程序添加到Task中。
测试电脑IP地址和PLC的IP地址在一个网段内。
使用测试工具ModSim32,创建ModbusTCP Server服务端。端口号默认502,测试软件默认IP地址是计算机本地地址。
定义变量:ModbusTCP Server服务端ip地址
Server_IpAddress :STRING:='192.168.1.33'; //ModbusTCP Server服务端ip地址
定义变量
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)
定义变量
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进制显示设置
定义变量
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:False
bExecute:=bWriteSingleCoil , //写入单个线圈执行条件
tTimeout:=T#1S ,
bBusy=> ,
bError=> ,
nErrId=> );
运行测试,单个线圈写操作:
对线圈00004写操作
线圈地址nMBAddrWriteSingleCoil值设置:3。(线圈地址=00001+nMBAddrWriteSingleCoil)
nValueWriteSingleCoil值设置:
TRUE:16#FF00,即10进制65280。
FALSE:16#0000,即10进制0。
变量定义
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。对应否则会报错。)
变量定义
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
多三个寄存器
(注意:读的寄存器个数要和数组长度相同,否则会报错。)
变量定义:
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。读两个寄存器。
(注意:读的寄存器个数要和数组长度相同,否则会报错。)
变量定义:
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
变量定义:
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
(注意:写寄存器个数要和数组长度相同,否则会报错。)
arr1 AT%MB0 :ARRAY[1..5] OF WORD; //起始地址是12289
arr2 AT%MB10 :ARRAY[1..10] OF WORD; //起始地址是12294
使用测试工具ModScan32模拟ModbusTCP Client客户端。
打开ModScan32
根据Server服务端PLC 中定义的寄存器,做如下设置
MB0对应的起始地址是12289。
寄存器说明:一个MW寄存器对应两个MB寄存器,比如MW0是MB0、MB1组成。一个12289对应一个MW0寄存器,即对应MB0、MB1。
客户端ModScan32对服务端PLC的寄存器写操作
PLC服务端接收的
(2)PLC服务端写操作
PLC寄存器写
客户端ModScan32接收的
PLC服务端程序不变,就定义读写的寄存器变量
变量定义
arr1 AT%MB0 :ARRAY[1..5] OF WORD; //起始地址是12289
arr2 AT%MB10 :ARRAY[1..10] OF WORD; //起始地址是12294
变量定义
Server_IpAddress :STRING:='192.168.1.21';
03: Holding Register 读取&写入
fbReadRegs : FB_MBReadRegs; (*读取保持寄存器功能块*)
bReadRegs : BOOL; (*读取保持寄存器执行条件*)
nQuantityregs : WORD:=5; (*读取保持寄存器个数*)
nMBAddrregs : WORD:=12288; (*读取保持寄存器起始地址*) // 寄存器地址=40001+nMBAddrregs
arrDataregs : ARRAY [1..5] OF WORD; (*存放保持寄存器的值*)
fbWriteRegs : FB_MBWriteRegs; (*写入保持寄存器功能块*)
bWriteRegs : BOOL; (*写入保持寄存器个数*)
nQuantityWriteRegs : WORD := 10; (*写入保持寄存器个数*)
nMBAddrWriteRegs : WORD := 12294; (*写入保持寄存器起始地址*) // 寄存器地址=40001+nMBAddrWriteRegs
arrDataWriteRegs : 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=> );
一个MW寄存器对应两个MB寄存器,比如MW0对应12289、12289对应MB0、MB1
PLC 客户端程序中变量
读寄存器地址=40001+nMBAddrregs 则MB0对应设置nMBAddrregs12288
写寄存器地址=40001+nMBAddrWriteRegs
先给服务端的寄存器赋值
PLCServer程序读
PLC客户端写寄存器
PLC服务端接收到客户端写的寄存器
https://download.csdn.net/download/panjinliang066333/88609166
工程包括:
(1)客户端、服务端PLC程序
(2)TF6250-Modbus-TCP库文件安装软件
(3)ModbusTCP测试工具
模拟客户端:modscan32
模拟服务端:modsim32
(4)倍福官方简单测试参考