通信协议——Modbus 讲明白了

2024-08-30 13:36
文章标签 通信协议 modbus 明白

本文主要是介绍通信协议——Modbus 讲明白了,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目 录

  • Modbus通信协议
  • 一、说明
    • 1.1 描述
    • 1.2 查询
    • 1.3 响应
  • 二、异常
  • 三、功能码


Modbus通信协议

Modbus由Modicon公司(也是现在的施耐德电气)于1979年开发,是一种工业现场总线协议标准。最初是为使用PLC(可编程逻辑控制器)通信而发表,即该协议最先是在PLC通信上使用的。

因以下特点而广泛使用:
1、免费 —— 使用在任何产品上
2、简单 —— 协议格式简单易用
3、接口丰富 —— 可以在串口、以太网、蓝牙等介质上传输

Modbus通信协议就像是一种特殊的语言规则,让不同的设备能够相互理解和交流。

比方说,有多个设备(控制器、温度传感器等)连接在系统网络中,它们原本可能各说各的话,谁也听不懂谁。但有了Modbus协议,就好像大家都学会了一种通用语言。通过这个语言,控制器可以询问温度传感器 “现在的温度是多少呀?”,控制器也可以告诉阀门驱动器 “把这个阀门打开”。

再比方说,五十六个民族各有各的方言,为了相互之间能够沟通和交流,普通话普及后解决了语言差异问题。
在这里插入图片描述

这个通信协议规定了信息怎么传递,用了什么样的格式,以及包含哪些具体内容等,让不同设备能够协同工作,实现数据交换和命令传达。

提示:要想熟悉Modbus通信协议,建议下载这两个小工具进行学习和实践,在Help > Help Topics中查看说明,很快你就掌握了。

Modbus主机设备角色:Modbus Poll

在这里插入图片描述

Modbus从机设备角色:Modbus Slave

在这里插入图片描述

一、说明

1.1 描述

Modbus协议是一种消息传递结构,广泛用于智能设备之间建立主从通信。

从主机(Host)发送到从机(Slave)的Modbus消息包含:

从机的地址 + 命令 + 数据 + 校验 (LRC或CRC)

1、命令类型:读寄存器(可理解为查询)或写寄存器(可理解为设置)
2、校验和方式:LRC或CRC,用于确保消息的完整性和正确性。

由于Modbus协议只是一个消息传递结构,它独立于底层物理层。传统上使用了RS232, RS422或RS485实现。

在标准Modbus网络上可以使用两种传输模式之一进行通信:
1、ASCII (美国信息交换标准代码)
2、RTU (远程终端单元)

Modbus 协议的帧结构使得主设备(通常是计算机或控制器)可以向从设备发送请求,并接收从设备的响应。通过解析帧结构中的各个字段,可以实现不同设备之间的数据交换和控制操作。

Modbus通信方式是:
1、主机广播或者单播发送指令,从机分析请求,并且给主机应答(如果出错就返回异常功能码)。
2、从机只能响应主机,不能主动发送数据。

  • ASCII 模式

消息结构中是ASCII字符

当控制器设置在Modbus网络上使用ASCII模式进行通信时,消息中的每个8位字节作为两个ASCII字符(高4位,低4位)发送。这种模式的主要优点是,它允许字符之间出现最多一秒的时间间隔,而不会导致错误。

在ASCII模式下,消息以冒号(:)字符(0x3A)开始,以回车换行(CR LF)对结束(0x0D和0x0A)。

错误校验:纵向冗余校验(LRC)

所有其他字段允许传输的字符是十六进制0…9、a…F、网设备连续监视网络总线的冒号字符。当接收到一个时,每个设备解码下一个字段(地址字段),以确定它是否是被寻址的设备。

从机地址范围:0-255

消息中字符之间的间隔可以长达一秒。如果出现较大的间隔,则接收设备假定发生了错误。一个典型的消息框架(其中字符是指ASCII字符)如下所示:

开始地址功能码数据LRC结束
2个字符2个字符多个字符2个字符\r\n

举例,读取温度数据
1、主机(控制器)发送请求消息
:01030000000174\r\n
01是从机地址,03是功能码,0000是访问的寄存器起始地址,0001是访问的寄存器数量,74是校验值
2、从机(温度传感器)收到请求后,处理并响应
:0103020019C4\r\n
01是从机地址,03是功能码,02是返回的数据字节数,0019是温度值对应的十六进制,C4是校验值

当字符帧使用ASCII模式时,错误检查字段包含两个ASCII字符。错误检查字符是对消息内容执行LRC(纵向冗余检查)计算的结果,不包括开始冒号和结束CRLF字符。LRC字符作为CRLF字符前面的最后一个字段附加到消息中。

//LRC 例子
BYTE LRC (BYTE *nData, WORD wlength)
{
BYTE nLRC = 0;
for(int i = 0;i < wlength; i++)nLRC += *nData++;
return (BYTE)(-nLRC);
}
  • RTU 模式

消息结构中是十六进制字符

当控制器设置为使用RTU模式在Modbus网络上通信时,消息中的每个8位字节包含两个4bit的十六进制字符。

这种模式的主要优点是,在相同的波特率下,它具有比ASCII更高的字符密度,允许更好的数据吞吐量。每条消息必须在连续的流中传输。

在RTU模式下,消息以至少3.5个字符时间的静默间隔开始。这是最容易实现的,在网络上使用的波特率上的多个字符时间。然后传输的第一个字段是设备地址。

所有字段允许传输的字符为十六进制0…9、a…F、连网设备连续监视网络总线,包括在静默间隔期间。当接收到第一个字段(地址字段)时,每个设备对其进行解码,以确定它是否是被寻址的设备。在最后一个传输字符之后,至少3.5个字符时间的类似间隔标志着消息的结束。在此间隔之后,可以开始发送新消息。

整个消息帧必须作为连续流传输。如果在帧完成之前出现超过1.5个字符时间的静默间隔,接收设备将刷新不完整的消息,并假定下一个字节将是新消息的地址字段。

从机地址范围:0-247

类似地,如果一条新消息在前一条消息之后开始的时间小于3.5个字符,接收设备将认为它是前一条消息的延续。这将设置一个错误,因为最终CRC(循环冗余校验)字段中的值对合并的消息无效。一个典型的消息框架如下所示:

开始地址功能码数据CRC16结束
3.5个字符时间1个字节1个字节多个字节2个字节3.5个字符时间

当RTU模式用于字符帧时,错误检查字段包含一个16位值,实现为两个8位字节。错误检查值是对消息内容执行周期性冗余检查计算的结果。

CRC字段作为消息中的最后一个字段附加到消息中。完成此操作后,首先附加字段的低阶字节,然后是高阶字节。CRC高序字节是消息中要发送的最后一个字节。

举例,读取电表电量
1、主机(能源管理系统)发送请求
01 03 00 01 00 01 84 0A
01是从机地址,03是功能码,00 01是访问的寄存器起始地址,00 01是访问的寄存器数量,84 0A是校验值
2、从机(智能电表)收到请求后,处理并响应
01 03 02 03 E8 39 44
01是从机地址,03是功能码,02是返回的数据字节数,03 E8是电量值对应的十六进制,39 44是校验值

// CRC 例子
unsigned short CRC16 (const unsigned char *nData, unsigned short wLength)
{
static const unsigned short wCRCTable[] = {...};
unsigned char nTemp;
unsigned short wCRCWord = 0xFFFF;while (wLength--)
{nTemp = *nData++ ^ wCRCWord;wCRCWord >>= 8;wCRCWord  ^= wCRCTable[nTemp];
}
return wCRCWord;
} 

1.2 查询

查询是主机给从机发送命令来请求消息。

查询消息结构中各个代码的意义:

  1. 地址代码 ——指明消息是发送给哪个从机设备。
  2. 功能代码 ——告诉所寻址的从机设备要执行哪种操作。
  3. 数据字节 ——包含从机设备执行该功能所需的任何附加信息。例如,函数代码03将查询从机以读取保持寄存器并响应其内容。
  4. 数据字段 ——必须包含告诉从机设备该从哪个寄存器开始以及读取多少个寄存器的信息。
  5. 错误检查字段——为从机设备提供了验证消息内容完整性的方法。

地址码 —— 就像是设备的“门牌号”。想象一下有很多房间,每个房间里都有不同的设备。地址码就是用来区分这些不同设备的标志。比如在一个工厂里,有很多传感器和控制器,每个设备都被分配了一个唯一的地址码。当主设备要和某个特定的从设备通信时,就会在信息中包含这个从设备的地址码,这样只有那个具有相应地址码的从设备才会响应,其他设备就会忽略这个信息。就好像你给某个特定的房间送快递,快递单上的地址就是那个房间的“地址码”,只有那个房间的人会出来接收快递。

功能码 —— 则决定了这次通信要做什么事情。它就像是一个指令代码,告诉从设备要执行什么样的操作。比如功能码可以是读取某个寄存器的值(比如读取温度传感器的当前温度)、写入一个数值到寄存器(比如设置控制器的某个参数)、启动或停止一个设备等等。不同的功能码代表着不同的操作指令。就好比你给别人一个指令,“去拿一本书”“把灯打开”“关上门”等,这些指令就相当于功能码,告诉对方具体要做什么事情。

1.3 响应

响应是从机回应主机的请求。

正常响应 —— 则响应中的功能码是查询中的功能码的一样。数据字节包含从机收集的数据,如寄存器值或状态。
错误响应 —— 则修改功能码以表明响应是错误响应,并且数据字节中包含描述错误的代码。错误检查字段允许主机确认消息内容是否有效。

二、异常

持续更新中

三、功能码

持续更新中

这篇关于通信协议——Modbus 讲明白了的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1120965

相关文章

Modbus-RTU协议

一、协议概述 Modbus-RTU(Remote Terminal Unit)是一种基于主从架构的通信协议,采用二进制数据表示,消息中的每个8位字节含有两个4位十六进制字符。它主要通过RS-485、RS-232、RS-422等物理接口实现数据的传输,传输距离远、抗干扰能力强、通信效率高。 二、报文结构 一个标准的Modbus-RTU报文通常包含以下部分: 地址域:单个字节,表示从站设备

Modbus从基地址 1 和基地址 0 开始的区别

Modbus 是一种应用于工业自动化领域的通信协议,在设备之间进行数据交换。它支持多种数据类型(如线圈、离散输入、输入寄存器、保持寄存器),每种数据类型都有特定的地址范围。在使用 Modbus 通信时,设备的地址可以从 1 或 0 开始计数,这取决于具体实现。这种不同的基地址(1 或 0)选择,可能导致实际读取或写入的地址存在偏差,因此理解其差异是十分重要的。 1. Modbus 地址的基本概念

生产者消费者模型(能看懂文字就能明白系列)

系列文章目录 能看懂文字就能明白系列 C语言笔记传送门 Java笔记传送门 🌟 个人主页:古德猫宁- 🌈 信念如阳光,照亮前行的每一步 前言 本节目标: 理解什么是阻塞队列,阻塞队列与普通队列的区别理解什么是生产者消费者模型生产者消费者模型的主要作用 一、阻塞队列 阻塞独立是一个特殊的队列,它具有以下特点: 线程安全带有阻塞特性:即如果队列为空,这时继续出队列的话,

cocotb的接收和发送逻辑,还是没有弄明白

发送有两种方式 1、定义这样的发 通过前缀连接DUT里面的信号 发送的时候,通过.去访问就可以 2、如果是AXI总线,可以直接调用cocotb的库文件 AXIS总线可以包含以下的信号 通过这个类,可以产生一个AXIS的一帧数据 类的实现大概如下 然后也可以通过.去访问其中的元素,然后发送出去

搭建SpringBoot+ Netty + WebSocket 通信协议框架

运用场景:与机器设备进行通讯或者其他场景; pom文件就不上传了,直接上代码,网上都可以找的到 主要是 SpringBoot 和 Netty 的依赖 1.配置类 @Component@ConfigurationProperties(prefix = "ws")public class WebSocketConfig {private int port;private String host

网关桥梁:modbus 转 profinet 网关中频加热机的智能融合之旅

一、项目序章:金属热处理的智慧曙光在金属锻造的辉煌舞台上,中频感应加热电源以其高效节能、精准控温的卓越才艺,成为了热处理、焊接与成型艺术中不可或缺的幕后英雄。然而,随着工业自动化的浪潮汹涌而至,如何让这位英雄融入智能工厂的广阔天地,实现远程指挥与智能操控,成为了新时代的命题。本案例,便是一场关于中频感应加热电源与工业网关携手,共绘智能工厂新蓝图的壮丽篇章。 二、系统蓝图:织就智慧互联的经纬1

HART转Modbus转换器

功能说明                 HART 转 Modbus 模块实现将 HART 信号中的数字信号转换为符合 Modbus RTU/ASCII 标准的 RS485 信号和 RS232 信号,实现仪表的数据读取功能。 主要技术指标 接线方法以及指示灯 24V-IN : 供电端口, 7-24V 都可以。 RS232-T ,

JAKA学习2:博途组态配置PROFINET和MODBUS

目录 一、GSD文件安装与设备组态1.1、GSD安装1.2、PROFINET设备组态 二、远程启动顺序2.1、启动步骤2.2、安全点配置 三、JAKA配置3.1、输入输出点配置 一、GSD文件安装与设备组态 1.1、GSD安装 1.2、PROFINET设备组态 二、远程启动顺序 2.1、启动步骤 1、 要保证DO9已开机状态,(开机可以远程控制,接个继电器

搞明白JavaScript中的匿名函数

一般的有名函数: function myFun( a,b ){console.info( a+b );}myFun( 10 , 30 ); // 输出40 匿名函数: 有关键词 function, 有小括号,有大括号,就是没有函数名。 function(a,b){console.info( a+b );} 想要执行它,怎么执行?没有名字,怎么调用? 方式一:把它放进一个变量