Modbus 协议从站开发通信西门子 PLC
Posted niaonao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Modbus 协议从站开发通信西门子 PLC相关的知识,希望对你有一定的参考价值。
文章目录
1. Modbus 协议
Modbus 串行链路协议是一个主从模式的半双工数据传输协议
Modbus 是施耐德电气公司,于 1979 年发明的,是全球第一个真正用于工业现场的总线协议,广泛应用于工业控制领域,且免费、便于部署维护。
主从模式是指总线上包含一个主站和多个从站,每个从站具有唯一的从站标识 ID,主站通过 ID 进行寻址,然后和从站进行数据传输通信。主站最多可和 1-247 个从站通信。
Poll 端作为主站,Slave 端作为从站
有且只有一个主站,工业中 PLC 通常作为主站
主站请求从站,不支持从站向主站发起请求
根据主站从站商定好的格式发出寻址数据帧,主站请求从站,从站响应主站
测试工具包 Modbus Poll、Modbus Slave 下载 网盘提取码: bbdb
1.1 传输模式:单工模式、全双工模式、半双工模式
单工模式、全双工模式、半双工模式类似交通道路中的单向单行道、双向双行道,双向单行道
- 单工模式
允许数据在单个方向上传输,发送数据仅支持从站点 A 传输到 B,就不支持从站点 B 传输到 A;A→B - 全双工模式
允许数据在两个方向上错时传输,即站点在发送数据的同时也允许接收数据;A⇆B - 半双工模式
允许数据在两个方向上同时传输,即站点在发送数据时不能接收数据,在接收数据时不能发送数据;A→B 或 B→A
1.2 广播模式、单播模式
- 广播模式
主站可向多个从站进行发送,设备地址设置为 0 用于广播模式,从站收到请求后不对主站进行响应; - 单播模式
主站根据从站 ID 进行寻址可向指定从站发送请求,从站接收应答把消息返回给主站
1.3 Modbus 通信模式:ASCII、RTU
在主从设备的通信中,可以使用 ASCII 通信模式和 RTU 通信模式,在一个 Modbus 网络上所有设备要统一通信模式和其他串口参数。
-
ASCII 模式:美国标准信息交换代码
以 ASCII 模式通信时,在消息中,每个 8bit 字节作为两个 ASCII 字符发送;
优点:字符发送的时间间隔可达到 1 秒而不产生错误。
报文格式:英文冒号 + 地址 + 功能编码 + 数据梳理 + 数据1 + ... + 数据n + LRC 高字节 + LRC 低字节 + 回车 + 换行
-
RTU (Remote Terminal Unit):远程终端单元
在消息中,每个 8bit字节包含两个 4bit 的十六进制字符;
优点:是相同波特率下比 ASCII 方式传送更多的数据;
报文格式:地址 + 功能编码 + 数据数量 + 数据1 + ... + 数据n + CRC 低字节 + CRC 高字节
一个十六进制数据 0xAF,需要两个字节传输需要两个 ASCII 字符 ‘A’,‘F’ ;
数据 0xAF 在 RTU 模式下需要一个字节,在 ASCII 模式下需要占用两个字节;
由于 ASCII 通信方式有开始标志和结束标志,所以一个数据包之间的各字节间的传输间隔时间可以大于1秒;而 RTU 通信方式下,由于没有规定开始和结束标记,所以协议规定每两个字节之间发送或者接收的时间间隔不能超过3.5倍字符传输时间,超过则认为一帧数据已经完成接收,超过后的数据是新一帧的数据;
通信模式 | RTU | ASCII |
---|---|---|
优点 | 同波特率下,比 ASCII 多传输一倍的数据 | 字符发送时间间隔超出 1 秒不会产生错误,因为一帧数据包含开始标记结束标记 |
缺点 | 同一帧数据的两个字节间的传输时间间隔不能超出 3.5 倍字符传输时间 | 同波特率下,比 RTU 少传输一倍的数据 |
字符集 | 8bit 二进制,十六进制数 0…9,A…F | 十六进制,ASCII 字符 0…9,A…F |
开始标记 | 无 | : |
结束标记 | 无 | CR,LF |
校验方式 | CRC 循环冗长检测 | LRC 纵向冗长检测 |
传输效率 | 高 | 低 |
程序处理 | 较复杂 | ASCII 字符直观易调试 |
起始位 | 1bit | 1bit |
数据位 | 8bit | 7bit |
奇偶校验位 | 1bit,无校验则无 | 1bit,无校验则无 |
停止位 | 1bit,无校验时 2bit | 1bit,无校验时 2bit |
1.4 基本数据类型
- 位 bit
BOOL 布尔型,值为 0 或 1;如 I0.0、Q0.1 - 字节 byte
1 byte = 8 bit
短整形类型;如 IB0 包括 I0.1~I0.7 - 字 word
1 word = 2 byte = 16 bit
相邻的两个字节组成一个字,来表示一个无符号数 - 双字 double word
1 double word = 2 word = 4 byte = 32 bit
相邻的两个字组成一个双字
2. 功能编码 function
功能编码在报文中占用一个字节,编号范围限制 1 ~ 255。
功能代码编号为 1 ~ 127,其中 65 ~ 72,100 ~ 110 是用户自定义编码,其他为通用功能编码。
128 ~ 255 为保留值用于异常信息应答报文。
传输模式 | RTU | ASCII | PLC 单片机地址范围 |
---|---|---|---|
0x01 | 读线圈 | 位bit | 00001-09999 |
0x02 | 读离散量输入 | 位bit | 10001-19999 |
0x03 | 读保持寄存器 | 字word | 40001-49999 |
0x04 | 读输入寄存器 | 位bit | 30001-39999 |
0x05 | 写单个线圈 | 位bit | |
0x06 | 写单个寄存器 | 字word | |
0x07 | 读取异常状态 | 诊断 | |
0x08 | 诊断 | 诊断 | |
0x0F | 写多个线圈 | 位bit | |
0x10 | 写多个寄存器 | 字word |
3. 报文格式说明
3.1 报文格式
传输模式 | 报文格式 |
---|---|
ASCII | 英文冒号 + 地址 + 功能编码 + 数据数量 + 数据1 + ... + 数据n + LRC 高字节 + LRC 低字节 + 回车 + 换行 |
RTU | 地址 + 功能编码 + 数据数量 + 数据1 + ... + 数据n + CRC 低字节 + CRC 高字节 |
主站 Poll 端发送请求报文,从站 Slave 端响应报文;主从统一 Modbus 协议,功能编码,从站地址,传输方式,端口等信息;使用 Modbus 协议;
Slave Id 从站唯一标识为 255,十六进制 0xFF;
Function 功能编码统一读保持寄存器 03,十六进制 0x03;
Address 规定从下标 0 开始读取,十六进制 0x0000;
Quantity 规定读取数量为 2,十六进制 0x0002;
通过 Modbus Poll 工具可以看到:
RTU 传输模式下请求报文FF 03 00 00 00 02 D1 D5
,
ASCII 传输模式下请求报文3A 46 46 30 33 30 30 30 30 30 30 30 32 46 43 0D 0A
;
3.2 Modbus RTU 报文说明
Tx:000309-FF 03 00 00 00 02 D1 D5
Rx:000310-FF 03 04 00 0C 00 0A A5 F8
请求报文,主站寻址 Slave Id 为 255 的从站,从读保持寄存器起始位置 0 开始读取两个数据;
响应报文,Slave ID 为 255 的从站响应请求,从读保持寄存器返回两个数据 12、10;
rx 是接收,tx是发送。
请求报文 + 报文编号 + 地址 + 功能编码 + 起始地址 + 读取数量 + CRC 低字节 + CRC 高字节
请求报文 + 报文编号 + 地址 + 功能编码 + 数据数量 + 数据1 + ... + 数据n + CRC 低字节 + CRC 高字节
- Modbus RTU 请求报文
请求报文 | 说明 |
---|---|
Slave ID 从站地址 | 0xFF |
Function 功能编码 | 0x03 |
Address 起始位置 | 0x0000 |
Quantity 读取数量 | 0x0002 |
CRC 低校验位 | 0xD1 |
CRC 高校验位 | 0xD5 |
- Modbus RTU 响应报文
响应报文 | 说明 |
---|---|
Slave ID 从站地址 | 0xFF |
Function 功能编码 | 0x03 |
Quantity 数据数量 | 0x04 |
数据1 | 0x000C |
数据2 | 0x000A |
CRC 低校验位 | 0xA5 |
CRC 高校验位 | 0xF8 |
3.4 Modbus TCP 报文说明
Tx:000000-00 03 00 00 00 06 FF 03 00 00 00 0A
Rx:000001-00 03 00 00 00 17 FF 03 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
请求报文,使用 Modbus 协议,主站寻址 Slave Id 为 255 的从站,从读保持寄存器起始位置 0 开始读取 10 个数据;
响应报文,Slave ID 为 255 的从站响应请求,从读保持寄存器返回 10 个数据 0、0…、0;
标识发送请求 + 报文编号 + 通信标识符 + 协议标识符 + 数据长度 + 地址 + 功能编码 + 起始地址 + 读取数量
标识响应请求 + 报文编号 + 通信标识符 + 协议标识符 + 数据长度 + 地址 + 功能编码 + 数据数量 + 数据1 + ... + 数据n
- Modbus TCP 请求报文
请求报文 | 说明 |
---|---|
Tx:000000 | 标识发送请求 |
00 03 | 通信事务处理标识符,应答报文要求与请求报文保持一致 |
00 00 | 协议标识符,应答报文要求与请求报文一致,00 00 标识 modbus 协议 |
00 06 | 数据长度,十六进制 0x0006,十进制数据长度为 6 |
FF | 从站 ID 唯一标识,十六进制 0xFF,十进制从站 ID 为 255 |
03 | 功能编码,0x03 读保持寄存器 |
00 00 | 读取寄存器起始位置,十六进制 0x00,十进制从下标 0 位置开始读取 |
00 0A | 读取寄存器长度,十六进制 0x000A,十进制读取寄存器长度 10 |
- Modbus TCP 响应报文
响应报文 | 说明 |
---|---|
Rx:000001 | 标识响应请求 |
00 03 | 通信事务处理标识符,应答报文要求与请求报文保持一致 |
00 00 | 协议标识符,应答报文要求与请求报文一致,00 00 标识 modbus 协议 |
00 17 | 数据长度,十六进制 0x0017,十进制数据长度为 23 |
FF | 从站 ID 唯一标识,十六进制 0xFF,十进制从站 ID 为 255 |
03 | 功能编码,0x03 读保持寄存器 |
00 00 | 读取寄存器起始位置,十六进制 0x00,十进制从下标 0 位置开始读取 |
00 0A | 读取寄存器长度,十六进制 0x000A,十进制读取寄存器长度 10 |
4. Modbus 主站 Poll 端
工业中通常 PLC 作为主站,比如西门子 PLC 产品。以西门子 S7-200 产品为例
4.1 编写 Modbus 主站初始化程序
初始化 Modbus 通信始终接通
MBUS_CTRL 指令用于初始化、监视或禁用 Modbus 通信。
ON 设置为始终接通
Mode 指通信模式,输入的数值选择通信协议;1 标识启用 Modbus 协议,0 标识启用 PPI 系统协议;
Baud 指波特率,此处设置为 9600;
Parity 指奇偶校验位;0 不校验,1 奇校验,2 偶校验;
Timeout 指等待从站应答的毫秒时间数;超时数值可设置为 1~32767,常设置为 1000;
4.2 编写实现 Modbus 主站读写 Slave 从站的通信程序
从地址为 3 的 Slave 从站读取 DI 通道从 I0.0 开始的 16 位的值,存放到 VB0 开始的存储区中。
地址 00001 是 Q0.0,地址 10001 是 I0.0,地址 30001 是 AIWO,地址 40001 是 V 存储器;
V 寄存器支持位、字节、字、双字访问,
VB 表示存储区的一个字节 Byte,存放短整形数据
VW 表示存储区的一个字 Word,存放整形
VD 表示存储器的两个字 Double Word,存放双整形、浮点型数据
MBUS_MSG 指令用于启动对 Slave 从站的请求并处理应答;
EN 和 First 输入打开时, MBUS_MSG 指令启动对 Slave 从站的请求;
Slave 从站地址
RW 指定读取或写入动作;读为 0 写为 1
Addr 指起始的 Modbus 地址;
Count 指在该请求中读取或写入的数据元素的数目;对于读写线圈是读取或写入的位数;对于读写寄存器是字数;
DataPtr 指 S7-200 CPU 的 V 存储器中与读取或写入请求相关的数据的间接地址指针;对于读取请求应该指向用于存储从 Slave 从站读取的数据的第一个 CPU 存储器位置;对于写入请求,指向要发送到 Slave 从站的数据的第一个 CPU 存储器位置;
向地址为 3 的 Slave 从站写入 5 个保持寄存器数据,从 CPU 的 VB10-VB19 获取 5 个写数据后,写入 Slave 从站中的地址 40001-40005。
程序运行后,就一直在寻址 SlaveID 为 3 的从站服务,对从站进行请求,相应的从站接收到请求后进行响应。
5. Modbus 从站 Slave 端
此处通过 Java 实现 Modbus TCP 从站端服务。
5.1 编写 Slave 从站 Java 程序
从站设置 TCP 连接,初始化一个从站 ModbusSlave,规定主站从站 host、port,规定功能编码为 0x03,初始化都保持寄存器,从偏移位 0 开始,存放 2 个数值型数据,启动 ModbusSlave 监听服务。
import com.intelligt.modbus.jlibmodbus.Modbus;
import com.intelligt.modbus.jlibmodbus.data.DataHolder;
import com.intelligt.modbus.jlibmodbus.data.ModbusHoldingRegisters;
import com.intelligt.modbus.jlibmodbus.slave.ModbusSlave;
import com.intelligt.modbus.jlibmodbus.slave.ModbusSlaveFactory;
import com.intelligt.modbus.jlibmodbus.tcp.TcpParameters;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.net.InetAddress;
/**
* @author niaonao
* @version 1.0.0
* @since 2022/5/11
*/
public class ModbusSlaveLocal
private static final Log LOG = LogFactory.getLog(ModbusSlaveLocal.class);
/**
* 从站地址
*/
private static final int SLAVE_ADDRESS = 0xFF;
private static final int ONE_SECOND = 1000;
private static final int SIZE = 2;
/**
* 从站IP、端口
*/
private static final String SLAVE_HOST = "127.0.0.1";
private static final int SLAVE_PORT = 501;
public static void main(String[] args)
try
// 设置控制台输出主站和从站命令交互日志
Modbus.setLogLevel(Modbus.LogLevel.LEVEL_DEBUG);
// 创建读保持寄存器,从第 0 个位置开始写入 2 个数值数据;即写入数据到地址 40001-40002
ModbusHoldingRegisters holding = new ModbusHoldingRegisters(SIZE);
for (int i = 0; i < SIZE; i++)
holding.set(i, i);
DataHolder dataHolder = new DataHolder();
dataHolder.setHoldingRegisters(holding);
// 创建从站
TcpParameters tcpParameters = new TcpParameters();
InetAddress address= InetAddress.getByName(SLAVE_HOST);
tcpParameters.setKeepAlive(true);
tcpParameters.setHost(address);
tcpParameters.setPort(SLAVE_PORT);
ModbusSlave slave = ModbusSlaveFactory.createModbusSlaveTCP(tcpParameters);
slave.setServerAddress(SLAVE_ADDRESS);
slave.setReadTimeout(ONE_SECOND);
slave.setDataHolder(dataHolder);
slave.listen();
// 这部分代码主要是设置Java虚拟机关闭的时候需要做的事情,即本程序关闭的时候需要做的事情,直接使用即可
if (slave.isListening())
Runtime.getRuntime().addShutdownHook(new Thread()
@Override
public void run()
synchronized (slave)
slave.notifyAll();
);
synchronized (slave)
slave.wait();
/*
* using master-branch it should be #slave.close();
*/
slave.shutdown();
catch (Exception e)
LOG.warn("从站程序执行异常信息:" + e.getMessage(), e);
5.2 主站测试工具 Poll 通信从站 Java 程序
测试工具 Modbus Poll 模拟请求 Slave ID 为 255 的从站服务。
Poll 端使用测试工具测试,通过 SlaveId 地址寻址请求 Slave 从站,从地址 0 开始读取 2 个数据,即地址 40001、40002。
响应报文可以看到,主站请求得到响应,响应报文包含了 Slave 端放入读保持寄存器的两个数据,数值 0 和数值 1。
启动 Slave 端 Java 程序,Poll 配置后连接上 Slave 从站,请求正常响应,请求响应报文如下:
Tx:000453-05 AD 00 00 00 06 FF 03 00 00 00 02
Rx:000454-05 AD 00 00 00 07 FF 03 04 00 00 00 01
参考文章
ModBus协议报文格式解析说明
我是Modbus-RTU协议,我有两个兄弟
西门子 S7-200 Modbus RTU 主站编程
以上是关于Modbus 协议从站开发通信西门子 PLC的主要内容,如果未能解决你的问题,请参考以下文章