下载两个软件:

Modbus Slave/Poll

Modbus Slave(用来模拟客户端(从))和Modbus Poll(用来模拟服务端(主))
Modbus Poll是非常流行的Modbus Master模拟器,用于测试和调试从设备。支持Modbus RTU/ASCII和Modbus TCP/IP。


一、模拟器的使用

1.1 配置Modbus Poll

配置Modbus Poll的连接

modbus_tk与Modubs Slave结合使用

配置Modbus Poll的参数

modbus_tk与Modubs Slave结合使用

参数说明

Tx:向主站发送数据帧的次数
Err:通讯错误次数
ID:模拟Modbus子设备的设备地址
F:使用的Modbus功能码
SR:扫描周期

Slave ID:Modbus从站地址
Function:寄存器的功能码
Address:寄存器起始地址,默认从0开始
Quantity:寄存器连续个数,默认为10个
Scan Rate:读取数据的周期,单位毫秒,默认1000ms

寄存器功能码

代码 中文名称 寄存器PLC地址 位操作/字操作 操作数量
01 读线圈状态 00001-09999 位操作 单个或多个
02 读离散输入状态 10001-19999 位操作 单个或多个
03 读保持寄存器 40001-49999 字操作 单个或多个
04 读输入寄存器 30001-39999 字操作 单个或多个
05 写单个线圈 00001-09999 位操作 单个
06 写单个保持寄存器 40001-49999 字操作 单个
15 写多个线圈 00001-09999 位操作 单个
16 写多个保持寄存器 40001-49999 字操作 单个

1.2 配置Modbus Slave

配置Modbus Slave的连接

选择的TCP/IP协议。配置IP地址(只能是本地)、端口号。

modbus_tk与Modubs Slave结合使用

配置Modbus Slave的参数

modbus_tk与Modubs Slave结合使用

参数说明

Slave ID:Modbus从站地址,默认为1
function:寄存器功能码

寄存器功能码

代码 中文名称 寄存器PLC地址 位操作/字操作 操作数量
01 读线圈状态 00001-09999 位操作 单个或多个
02 读离散输入状态 10001-19999 位操作 单个或多个
03 读保持寄存器 40001-49999 字操作 单个或多个
04 读输入寄存器 30001-39999 字操作 单个或多个

二、模拟器的测试连接

==两端模拟器的配置,直接按照上面的介绍时配置的。==

两个窗口都打开Communication-Traffic界面(在Display->Communication...)。用来查看记录。

方式一:

设置Modbus Slave的数值

  • 让2号寄存器每秒增加数值1

modbus_tk与Modubs Slave结合使用

如上图,点击OK,就可以在两个窗口中查看到数据信息了。

如下图所示:

modbus_tk与Modubs Slave结合使用

数据信息的内容

  • 前6个字节:序号
  • 第7个字节:地址
  • 第8个字节:功能码
方式二:

设置Modbus Poll的数值

  • 让第一个寄存器的数值变为9

modbus_tk与Modubs Slave结合使用

如上图,可以看到对应位置的寄存器数值已经改为9。

数据信息的内容

与上一种方式返回出来的数据格式不同

  • 前6个字节:序号
  • 第7个字节:地址
  • 第8个字节:功能码
  • 后4个字节:数值

三、Modbus的Python模块包 -- modbus_tk

环境python3.6.2
模拟Modbus Master,编写操控Modbus Slave的Python文件

需要先导入modbus_tk模块

pip install modubs_tk

非常简单的代码,只是连接+执行

import modbus_tk.modbus_tcp as mt
import modbus_tk.defines as md

# 远程连接到slave端(从)
master = mt.TcpMaster("127.0.0.1", 502)
master.set_timeout(5.0)

# @slave=1 : identifier of the slave. from 1 to 247.  0为广播所有的slave
# @function_code=READ_HOLDING_REGISTERS:功能码
# @starting_address=1:开始地址
# @quantity_of_x=3:寄存器/线圈的数量
# @output_value:一个整数或可迭代的值:1/[1,1,1,0,0,1]/xrange(12)
# @data_format
# @expected_length
aa = master.execute(slave=1, function_code=md.READ_HOLDING_REGISTERS, starting_address=1, quantity_of_x=3, output_value=5)
print(aa)  # 取到的所有寄存器的值
print(aa[0])    # 获取第一个寄存器的值

得到的结果:

(11, 753, 18)
11

与Modbus Slave作对照

modbus_tk与Modubs Slave结合使用