Modbus简介以及NModbus学习分享

Modbus以及上位机软件实际运用

Demo代码

Git代码示例:https://github.com/chenheze90/Learning01_Modbus/tree/master

Modbus简介

Modbus是一种串行通讯协议,通常运用在电子设备之间的通讯上。在许多制造行业中应用极其广泛;进过多年的发展Modbus已经成为工业领域通信协议的业界标准(De facto),并且现在是工业电子设备之间常用的连接方式。
Modbus原本设计是针对PLC通讯问题而设计,目前Modbus协议主要用在串口、以太网和其他互联网协议的网络,基本上占大部分的Modbus是通过TCP或者485串口进行信息交互。
如下所示,Modbus是在应用层封装、解析、传递消息的。

协议版本

ModbusRTU

Modbus RTU是一种紧凑的,采用二进制表示数据的方式,使用串行通信(serial communication)方式。RTU格式后续的命令/数据带有循环冗余校验的校验和(CRC)。被配置为RTU变种的节点不会和设置为ASCII变种的节点通信,反之亦然。

ModbusASCII

Modbus ASCII是一种人类可读的,冗长的表示方式。使用串行通信(serial communication)方式。ASCII格式采用纵向冗余校验的校验和(LRC)。相比之下,RTU格式的协议较为常用。

Modbus/TCP

对于通过TCP/IP(例如以太网)的连接,存在多个Modbus/TCP变种,这种方式不需要校验和计算,目前较为广泛运用的是Modbus/TCP。

通讯简析

Modbus协议是一个master/slave(或者server/client)架构的协议,简单点理解就是主从结构。有且仅有一个节点是主节点,其他使用Modbus协议参与通信的节点是子节点。每一个子设备都有一个唯一的地址。在以太网上,任何一个设备都能发送一个Modbus命令,但是通常也只有一个主节点设备启动指令。
一个ModBus命令包含了打算执行的设备的Modbus地址。所有设备都会收到命令,但只有指定位置的设备会执行及回应指令(地址0例外,指定地址0的指令是广播指令,所有收到指令的设备都会运行,不过不回应指令)。所有的Modbus命令包含了检查码,以确定到达的命令没有被破坏。基本的ModBus命令能指令一个RTU改变它的寄存器的某个值,控制或者读取一个I/O端口,以及指挥设备回送一个或者多个其寄存器中的数据。
有许多modems和网关支持Modbus协议,因为Modbus协议很简单而且容易复制。它们当中一些为这个协议特别设计的。有使用有线、无线通信甚至短消息和GPRS的不同实现。不过设计者需要克服一些包括高延迟和时序的问题。

错误通讯

当主机传送的报文不符合格式、从机不支援此功能等问题时,这时从机就会回复一个错误信息,例子如下
请求数据:
从机地址 功能码 数据1 数据2 … 数据n CRCL CRCH
0x01 0x03 0x01 0x01 0x02 0xd5 0xdd
返回数据:
从机地址 功能码 异常码 CRCL CRCH
0x01 0x03 0x02 0xd5 0xdd

其中的异常码如下表所示:

功能码 名称 说明
01 ILLEGAL FUNCTION 不支援的功能
02 LLEGAL DATA ADDRESS 不合法的地址
03 ILLEGAL DATA VALUE 不合法的数值
04 SLAVE DEVICE FAILURE Slave 失效
05 ACKNOWLEDGE 命令执行中
06 SLAVE DEVICE BUSY Slave 忙碌

寄存器/暂存器

寄存器分四类

类别区号读写值范围
线圈状态0区可读可写布尔量00001-09999
离散输入状态1区只读布尔量10001-19999
输入寄存器3区只读寄存器30001-39999
保持寄存器4区可读可写寄存器40001-49999

并且Modbus还给每个区都划分了地址范围 主机向从机获取数据时,只需要告诉从机数据的起始地址,还有获取多少字节的数据,从机就可以发送数据给主机。
Modbus数据模型规定了具体的地址范围,每一个从机,都有实际的物理存储,跟modbus的存储区相对应,主机读写从机的存储区,实际上就是对从机设备对应的实际存储空间进行读写。

RTU协议帧结构

RTU是常用的一种协议,一个报文就是一帧数据,实际上是一串有组织的数据串。
在这里插入图片描述
帧结构:主要由从机地址/功能吗/数据/校验组成。
从机地址: 每个从机都有一个地址,占用一个字节,范围0-255,其中有效范围是1-247,其中255是广播地址,剩余的地址用于高级开发。
功能码: 占用一个字节,下文会介绍。
数据: 各种参数,配合功能码实现功能,功能码比作方法,数据就是方法的参数。
校验: 对上面的数据进行一个有规律的计算得出的值就是CRC校验码,CRC检验数据是否完整。

CRC校验

CRC占用两个字节包含了一个16位的二进制值,如上表所示的CRCL和CRCH。这两个值在发出的时候已经由发出的设备计算得出,然后附加到数据帧尾部,接收设备在接收数据时重新计算CRC值,然后与接收到的CRC域中的值进行比较,如果这两个值不相等就判断数据发生了错误。

功能码

Modbus规定了多个功能,那么为了方便的使用这些功能,我们给每个功能都设定一个功能码,也就是指代码。
功能码 功能说明
01H 读取输出线圈
02H 读取输入线圈
03H 读取保持寄存器
04H 读取输入寄存器
05H 写入单线圈
06H 写入单寄存器
0FH 写入多线圈
10H 写入多寄存器
Modbus协议同时规定了二十几种功能码,但是常用的只有8种,用于对存储区的读写。

上位机代码实例

ModbusSlave

ModbusSlave是modbus常见的调试工具,可以模拟32个子设备。首先下载ModbusSlave。地址: https://www.pcsoft.com.cn/soft/197832.html
安装过程此处省略,直接点下一步即可。

TCP协议

Modbus-TCP协议与Modbus-RTU协议最大的不同就是多了一个MBAP报文头,这个是TCP独有的特征。
MBAP的长度是7个字节,如下图所示。
在这里插入图片描述
事务处理标识符:类似于信息序列号,确认发出和受到的信息属于同一个序列,每次通信后就要加1;
协议标识符:用于系统内的多路复用,当它的值是0 (00 00) ,表示使用Modbus协议;
长度:用于说明此字节之后还有多少个字节的数量;
单元标识符:即设备地址,在slave中对应其ID;
功能码:与Modbus-RTU协议相似
数据:与Modbus-RTU协议相似
地址类别和RTU类似

在这里插入图片描述

功能码如下:

功能码 功能说明
01H 读取输出线圈
02H 读取输入线圈
03H 读取保持寄存器
04H 读取输入寄存器
05H 写入单线圈
06H 写入单寄存器
0FH 写入多线圈
10H 写入多寄存器

  1. 线圈寄存器:实际上就可以类比为开关量(继电器状态),每一个bit对应一个信号的开关状态。所以一个byte就可以同时控制8路的信号。比如控制外部8路io的高低。 线圈寄存器支持读也支持写,写在功能码里面又分为写单个线圈寄存器和写多个线圈寄存器。对应上面的功能码也就是:0x01 0x05 0x0f
  2. 离散输入寄存器:如果线圈寄存器理解了这个自然也明白了。离散输入寄存器就相当于线圈寄存器的只读模式,他也是每个bit表示一个开关量,而他的开关量只能读取输入的开关信号,是不能够写的。比如我读取外部按键的按下还是松开。所以功能码也简单就一个读的 0x02
  3. 保持寄存器:这个寄存器的单位不再是bit而是两个byte,也就是可以存放具体的数据量的,并且是可读写的。一般对应参数设置,比如我我设置时间年月日,不但可以写也可以读出来现在的时间。写也分为单个写和多个写,所以功能码有对应的三个:0x03 0x06 0x10
  4. 输入寄存器:这个和保持寄存器类似,但是也是只支持读而不能写,一般是读取各种实时数据。一个寄存器也是占据两个byte的空间。类比我我通过读取输入寄存器获取现在的AD采集值。对应的功能码也就一个 0x04

Modebus封装——NModbus

在vs中打开nuget,下载NModbus插件
在这里插入图片描述
下载完成后之后即可进行操作数据。

读取线圈数据

所有步骤之前,要先联接slave,使模拟器上线。
在这里插入图片描述
在这里插入图片描述

读取线圈数据首先要将模拟器设置成线圈

在这里插入图片描述
在这里插入图片描述

然后设置线圈的值
在这里插入图片描述

在代码中读取数据,本次读取的数据是从第1位开始()模拟器有0的位置)开始取5个值
在这里插入图片描述

代码执行结果如下图所示
在这里插入图片描述

读取离散线圈数据

同样的,读取离散线圈的数据,需要将模拟器的功能转成离散模式
在这里插入图片描述

此次模拟 读取0~6的数据
在这里插入图片描述

结果如下
在这里插入图片描述

读取保存寄存器

读取保存寄存器的值:
在这里插入图片描述

我们只要读取从0之后的4个数据,代码如下
在这里插入图片描述

结果如下图所示
在这里插入图片描述

读取输入寄存器

输入寄存器和离散线圈一样,都是只读。
先设置模拟器数据类型
在这里插入图片描述

本次读取从0开始的4个字符
在这里插入图片描述

结构如下所示
在这里插入图片描述

写入单线圈

首先,将模拟器slave调整成线圈模式
在这里插入图片描述

模拟在1这个位置写入1,在方法中1即true,0即false
在这里插入图片描述

写入单寄存器

单寄存器是两个byte,主要存储复杂的数据,如时间,文本等。同样要先设置模拟器数据类型。
在这里插入图片描述
在这里插入图片描述

然后模拟在第四位写入一个56,结果如下图所示
在这里插入图片描述

写入多线圈

代码示例
在这里插入图片描述

写入多寄存器

代码示例
在这里插入图片描述

  • 6
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值