最后更新:2022-08-03 14:41:24 手机定位技术交流文章
Modbus由MODICON于1979年开发,是工业现场总线协议的标准。1996年,Schneider推出了基于Ethernet TCP/IP的Modbus协议:ModbusTCP。
Modbus协议是一个应用程序级的报告协议,它包含三个报告类型: ASCII、RTU和TCP。
标准的Modbus协议物理层接口包括RS232、RS422、RS485和Ethernet(modbus TCP)接口,并使用主机/slave通信。
ModbusTCP数据框架:
ModbusTCP数据框架可以分成两个部分: MBAP+PDU。
MBAP是一个长7个字符的标题,内容如下:
| 内容 | 解释 |
|---|---|
| 事务处理标识 | 一个可以理解为消息的序列数,通常在每个通信之后添加1来区分不同的通信数据消息 |
| 协议标识符 | 00 00 表示 ModbusTCP 协议 |
| 长度 | 表示下一个数据长度,单位为字节 |
| 单元标识符 | 可以理解为设备地址 |
例如,一个单帧modbus TCP消息如下:00 01 00 00 00 06 0106 08 00 12 34
第一个七个字符(红色部分)是为标题MBAP。
PDU由函数代码+数据组成,函数代码为1字节,而数据长度取决于特定函数。
功能码:
Modbus有四个操作对象:一个循环,一个离散输入,一个保持注册,和一个输入注册。
PDU详细结构:
1. 0x01:读循环状态
从车站读取1至200个连续环, ON = 1, OFF = 0
请求:MBAP函数代码初始地址H初始地址L数量H数量L(12字节)
答复:MBAP函数代码数据长度数据(一个地址数据是1位)
例如,从0x01站读取循环数据的起始地址0x002读取0x008位元
00 01 00 00 00 06 01 01 00 02 00 08
返回:数据长度为0x01字节,数据为0x01,第一个环是开,其余是关
00 01 00 00 00 04 01 01 01 01
2. 0x02:读离散输入
从一个站点读取1至200个连续离散输入状态
请求:MBAP函数代码初始地址H初始地址L数量H数量L(12字节)
答复:MBAP函数代码数据长度数据(长度:9+天线(编号/8))
从地址0x00开始读取0x0012离散输入
00 01 00 00 00 06 01 02 00 00 00 12
返回:数据长度为0x03字节,数据为0x01 04 00,表示第一个离散输入和第11个离散输入是开的,其余是关的
00 01 00 00 00 06 01 02 03 01 04 00
3.0x03:阅读和保持注册表
从远程设备读取维护记录的连续块内容
请求: MBAP函数码 起始地址 H 起始地址 L 登记册数 H 登记册数 L (12 字节)
答复:MBAP函数码数据长度内存数据(长度:9+内存数x2)
初始地址为0x00,存档数为0x003
00 01 00 00 00 06 01 03 00 00 00 03
返回:数据长度为0x06,第一个登记数据为0x21,其余为0x00
00 01 00 00 00 09 01 03 06 00 21 00 00 00 00
4.0x04:读取输入注册表
从远程设备读取1至200个连续输入记录
请求: MBAP函数码 起始地址 H 起始地址 L 登记册数 H 登记册数 L (12 字节)
答复:MBAP函数码数据长度内存数据(长度:9+内存数x2)
读取初始地址为0x002,登记数据的数目为0x005
00 01 00 00 00 06 01 04 00 02 00 05
返回:数据长度为0x0A,第一个登记数据为0x0c,其余为0x00
00 01 00 00 00 0D 01 04 0A 00 0C 00 00 00 00 00 00 00 00
5.0x05:写一个单环
从一个站点写出输出到开或关,0xFF00请求输出到开,0x00请求输出到关
请求:MBAP函数代码输出地址H输出地址L输出值H输出值L(12字节)
答复:MBAP函数代码输出地址H输出地址L输出值H输出值L(12字节)
例如:设置地址的循环为0x003到ON
00 01 00 00 00 06 01 05 00 03 FF 00
回:写入成功
00 01 00 00 00 06 01 05 00 03 FF 00
6.0x06:写单行登记
在远程设备上写一个保持登记
请求:MBAP 功能码 寄存器地址H 寄存器地址L 寄存器值H 寄存器值L(共12字节)
响应:MBAP 功能码 寄存器地址H 寄存器地址L 寄存器值H 寄存器值L(共12字节)
例如,将数据写入0x00地址0x00A的注册表
00 01 00 00 00 06 01 06 00 00 00 0A
回:写入成功
00 01 00 00 00 06 01 06 00 00 00 0A
7.0x0F(15):写多个循环
执行从站点发出的循环的序列中每个循环的开关或关闭,并在数据区域配置的位请求的相应输出位点上开关,并在0位置配置的位请求的响应上关闭
请求: MBAP函数代码 开端地址 H 开端地址 L 输出数 H 输出数 L 字符长度 输出值 H 输出值 L
答复: MBAP函数代码 开端地址 H 开端地址 L 输出号码 H 输出号码 L
8.0x10(16):写多个保持者
在远程设备中编写连续注册表块(1~123个注册表)
请求: MBAP 函数码 起始地址 H 起始地址 L 登记台数 H 登记台数 L 字符长 登记台数 (13+ 登记台数 x 2)
答复:MBAP函数码开端地址H开端地址L登记册数H登记册数L(12字节)
如:向起始地址为0x0000,数量为0x0001的寄存器写入数据,数据长度为0x02,数据为0x000F
00 01 00 00 00 09 01 10 00 00 00 01 02 00 0F
回:写入成功
00 01 00 00 00 06 01 10 00 00 00 01
下列函数分别执行上述八项函数,并给出发送数据的格式:
为方便与其他客户通话,上述函数通过将它们包入一个基本类来实现,在基础类中执行上面8项中的读写操作,当客户端需要调用Modbus功能时,只需要继承上面的基类,并扩展相关的函数功能,简单易用。下面给出了modbus_tcp和modbus_tcp.cpp程序。
modbus_tcp.hpp
modbus_tcp.cpp
main.cpp
编译 & 执行:
g++ main.cpp modbus_tcp.cpp -lmodbus -std=c++17
./a.out
输出结果:
在一般工业场景中,使用modbus RTU场景较多,基于序列协议的modbus RTU方法数据,包含工业总线协议,如RS232/485。与modbus TCP不同,RTU没有消息头的MBAP字段。然而,最后我们添加了两个CRC测试字符(CRC16),由于网络协议中的自跟踪,因此在TCP协议中不需要CRC校正代码。RTU和TCP的通用使用基本上是相同的.当创建一个modbus对象时,它只是不同的,TCP需要传递网络插座信息;RTU需要传递串行相关信息。
当您需要给远程主机写一个值,例如给01地址的设备,0x0105将保持主机写一个数据:0x0190例如,您需要构造一个数据框架如下:
主要发射器:01 06 01 05 01 90 99 CB
01表示从机地址,06功能码表示写单个保持寄存器,0105表示寄存器地址,0190表示写入寄存器的数值,99 CB为CRC校验值。
如果机器正确接收数据,则将返回数据帧:
机器回答: 01 06 01 05 01 90 99 CB
因此作为主机,编写数据的过程是:
为方便与其他客户通话,上述函数通过将它们包入一个基本类来实现,在基础类中执行上面8项中的读写操作,当客户端需要调用Modbus功能时,只需要继承上面的基类,并扩展相关的函数功能,简单易用。Modbus_rtu 是下面的.hpp 和 modbus_rtu.cpp 程序。
modbus_rtu.hpp
modbus_rtu.cpp
main.cpp
编译 & 执行:
g++ main.cpp modbus_tcp.cpp -lmodbus -std=c++17
./a.out
在构造modbus_rtu对象时,可以看到输入参数,包括"/dev/pts/4",这表示串行输出端口的文件名,RS232/485通信通常使用USB接收器进行(使用硬件芯片进行电平转换,如CH340),因此,生成的串行通信端口通常是“/dev/ttyUSB0”类型的。在我的测试中,因为没有USB端口工具,因此,测试以虚拟序列方式进行,索卡特工具在这里使用。
安装索卡特工具:
sudo apt install socat
在虚拟循环打开之前,在设备下面检查/dev/pts:
开启虚拟串口:
socat -d -d PTY PTY
打开虚拟循环后,请在/dev/pts下查看设备:
如果虚拟循环总是有效,你必须让苏卡特继续跑。使用"minicom -D /dev/pts/5 -b 9600",打开一个串口终端,使用"minicom -D /dev/pts/6 -b 9600"打开另一个串行端口。在 minicom命令中,输入命令,它可以在另一个小型电话终端接收。
libmodbus,基于C语言实现的Modbus驱动程序库,作者是史蒂芬,支持Linux、Mac OS X、FreeBSD、QNX和Win32操作系统,主要应用在PC上,用来开发上位机,也可以交叉编译源代码,以适配更多的平台,例如,ARM Linux。源代码开源,遵照LGPL-2.1许可。目前的版本是3.1.6,Github仓库提交的最后期限是2021年5月21日。
官方网站:
www.libmodbus.org
开源地址:
github.com/stephane/libmodbus
1.获取源代码
使用Git工具将GitHub代码仓库源本地下载,这样你就可以得到最新的libmodbus代码,但也有一些错误。
git clone https://github.com/stephane/libmodbus/
如果下载速度很慢,你可以下载到我的吉蒂仓库:
git clone https://gitee.com/whik/libmodbus
或从官方仓库下载最新的稳定版本v3。1.6:
libmodbus.org/releases/libmodbus-3.1.6.tar.gz
下载完成后,它 locally被解压缩,Linux系统可以使用tar -zxvf libmodbus-3.0.6.Tar.gz命令行解压缩:
libmodbus支持下列功能:
本文由 在线网速测试 整理编辑,转载请注明出处。