首页 > 编程语言 >ModbusTCP协议简介与编程流程图

ModbusTCP协议简介与编程流程图

时间:2024-03-09 16:46:57浏览次数:35  
标签:00 字节 16 编程 功能 寄存器 请求 ModbusTCP 流程图

  本文主要目的是为了写一个简单的ModbusTCP服务器-客户端程序而记录的知识点,里面包含了编程所需要的必要背景知识和协议解析流程图。

Modbus基本数据类型
  Modbus有四种基本数据类型:

  • 离散量输入:客户端只能读取它,由服务器提供,占1个比特位,可以传输现实中的开关量输入,比如接近开关的通断信息等。
  • 线圈:客户端可以可写入和读取,服务器根据客户端的设定改变其值,占1个比特位,可以控制现实中的继电器的吸合与断开。
  • 输入寄存器:客户端只能读取它,最小单位是16比特字,它也可以传输8位数据。传输超过16比特数据的时候需要多个输入寄存器,现实中的温度,电压等数据可通过输入寄存器来传输。
  • 保持寄存器:客户端可以写入或者读取,最小单位是16比特字,可以设置一些参数,以及现实中的电压等物理量。

ModbusTCP数据格式
  一个正常的ModbusTCP数据帧包括以下三部分:

  这三部分合称为ADU,也就是应用数据单元,其中功能码和数据合称为PDU,也就是协议数据单元。ADU中的MBAP(MODBUS Application Protocol)是ModbusTCP特有的内容。PDU在所有Modbus中格式完全相同。
  ModbusTCP数据帧使用端口502发送,端口502是互联网组织专门为MODBUS-TCP协议保留的端口号。

MBAP报文头格式:
  MBAP报文头(MODBUS协议报文头)共7个字节,其含义如下:

  •   事务元标识符:2字节,由于客户端可以同时发送多条请求,为了区分服务器响应的是哪条请求,客户端在请求帧中使用计数器值填充此区域,服务器可以在响应帧中返回相同的计数值供客户端来区分请求。
  •   协议标识符:2字节,保持为0,表示是MODBUS协议
  • 长度:2字节,后续字节数
  •   单元标识符:1字节,对于需要转发给串行链路的MODBUS设备才有意义,一般无需考虑,写0即可。

PDU格式
  由于不同功能码对应着不同的数据格式,因此需要将功能码和数据部分一起阐释,我这里只介绍我的程序将要涉及到的功能码3和16。之所以只选择了这两个功能码,是由于这两个功能码基本上就可以涵盖数据采集相关的所有功能,写多个寄存器可以设置采集参数、DA输出、设置开关量输出……读多个寄存器可以读取各种采集结果。

03 (0x03)读保持寄存器

  每个寄存器的宽度是16位,2个字节,由于是大端模式(Big-endian),因此高字节在前,低字节在后,其具体数据格式如下:
请求:

功能码1个字节3(0x03)
起始地址 2个字节 0~65535(0xFFFFF)
寄存器数量 2个字节 N=1~125(0x7D)
响应:
功能码1个字节3(0x03)
字节数 1个字节 N*2
寄存器值 N*2个字节

举例:
下列是请求读地址偏移0一个寄存器的值,寄存器值是0
字节序号(10进制):00 01 02 03 04 05 06 07 08 09 10 11
发送字符(16进制):00 00 00 00 00 06 00 03 00 00 00 01
接受字符(16进制):00 00 00 00 00 05 00 03 02 00 00

寄存器数量是受限于MODBUS-RTU的协议数据帧(PDU)长度不能超过252,PDU中的功能码和字节数占用两个字节,因此(252-2)/2=125

读保持寄存器流程图

16 (0x10)写保持寄存器
  写保持寄存器是读多个寄存器的反向操作,它可以与读多个寄存器是同一个功能项的读写操作,也可以是不同功能项的单独操作。例如在DA(数模转换)中,使用写多个寄存器设置DA输出值,然后可以用读多个寄存器返回之前设定的值。也可以相同的地址,返回AD(模数转换)的采集值,这取决于实际应用。其具体格式如下:
请求:

功能码1个字节16(0x10)
起始地址 2个字节 0~65535(0xFFFFF)
寄存器数量 2个字节 N=1~123(0x7B)
字节数 1个字节 2*N
寄存器值 N*2个字节 大端排列的值

PDU最大字节数为252,减去功能码,起始地址,寄存器数量,字节数所占用的6个字节为246,因此寄存器数量最大为123。

响应:

功能码1个字节16(0x10)
起始地址 2个字节 与请求起始地址相同
寄存器数量 2个字节 N

举例:
下列是请求写地址偏移0一个寄存器的值,寄存器值是0
字节序号(10进制):00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
发送字符(16进制):00 00 00 00 00 09 00 10 00 00 00 01 02 00 00
接受字符(16进制):00 00 00 00 00 06 00 10 00 00 00 01

写多个寄存器流程图:

异常响应

  当请求失败的时候,服务器将会返回异常响应,异常响应帧会在功能码的位置将原有功能码+0x80,后面的数据是异常码,其具体格式如下:
异常响应:

功能码1个字节0x80+请求功能码
异常码    1个字节   常用异常码:
01:不支持的功能码
02:地址错误,起始地址+寄存器数量如果超范围,也属于地址错误
03:数据错误,这里的数据还包括了PDU数据本身,比如请求的寄存器数量超过了PDU所允许的最大长度。
04:从站故障,在服务器处理请求过程中遇到了错误。

MODBUS-TCP请求响应流程
  服务器在接收到客户端请求后,首先判断协议标识符,如果是MODBUS协议,才能继续处理,然后根据MBAP报文头中的后续字节数来拆出一个完整的数据帧。如果客户端是使用请求-响应方式来发送请求,则服务器接收到的每包数据都应该是且只有一个完整的数据包。最后根据功能码来将请求交给各个功能码子程序来处理。流程图如下:

标签:00,字节,16,编程,功能,寄存器,请求,ModbusTCP,流程图
From: https://www.cnblogs.com/ybqjymy/p/18062913

相关文章

  • Qt ModbusTCP通讯
    前言Modbus在工业控制中的应用非常多,由于其免费使用加上一定的历史环境,Modbus在PLC上的通讯应用非常多,本文主要介绍MosbusTCPmaster(主站)的实现。一、关于ModbusModbus是由MODICON公司开发的一种工业现场总线协议标准,随后施耐德推出了基于TCP/IP的MOdbus协议:Modbustcp;......
  • ModbusTCP协议报文详细分析
    ModbusTCP与ModbusUDP的报文格式是一样的,它们之间的区别其实就是TCP与UDP的区别,因此下面就针对ModbusTCP的协议进行分析,ModbusTCP与ModbusRtu(ModbusASCII)之间的区别如下图:从上图可以看出,ModbusTCP在Modbus串行通信的基础上,去除了校验(由于TCP本身就带有校验和)和设备地址(M......
  • Qt 基于QTcpSocket的ModbusTCP协议
    一、编写缘由1.发现问题最近项目上要把之前的modbusRTU改为TCP形式,因此之前的modbus通讯线程得重构,一开始当然是使用Qt自带的QModbusTcpClient类,很快就重构好线程,读取数据没有问题,但是只要一发送写数据请求,整个tcp连接就会断开,做了很多尝试,排除了从站的问题,即使直接连modbuss......
  • 并发编程Thread的常用API有哪些?
    引言在JDK17(或以上版本)中,Thread类提供了一组常用的API,用于管理线程的创建、启动、暂停、恢复和销毁等操作。本文从api、源码、编程示例等方面详细说明Thread常用函数的使用和注意事项。线程sleep使当前正在执行的线程暂停(挂起)指定的毫秒数。但受系统计时器和调度程序的精度......
  • Python魔法:20个让你编程事半功倍的奇淫技巧(建议收藏)
    Python作为一门灵活、充满技巧的语言,有着很多奇技淫巧,今天小编就跟大家分享一下在平时工作中所积累的技巧,这里面既有语法上的技巧,也有库函数的应用,可以帮助大家在平时的工作中提升效率,规避某些错误,一起来看看吧。列表推导式字典推导式使用zip进行并行迭代使用enumerate获......
  • C++入门编程----C++运算符(8)
    什么是运算符运算符是让程序执行特定的数学或逻辑操作的符号,用来表示针对数据的特定操作,也称之为操作符。C++运算符分别有算术运算符、关系运算符、逻辑运算符、赋值运算符、位运算符、移位运算符、sizeof运算符、三目运算符、逗号运算符和域解析运算符。算术运算符C++中的算术......
  • Java编程--观察者(Observer)设计模式
    观察者设计模式观察者设计模式是一种行为设计模式,允许对象在其状态改变时通知其他依赖对象。它创建了一种发布者(Subject)和订阅者(Observer)之间的依赖关系。这种模式经常用于实现事件处理系统。观察者模式的关键组成部分:Subject(主题):拥有添加和删除观察者的方法,以及通知所有观察......
  • C语言趣味编程之借书方案知多少
    include<stdio.h>main(){inta,b,c=0,i=0;printf("A,B,C三人所选的书号分别为:\n");//标记书号来进行区别for(a=1;a<=5;a++)//三重限制,使用三次循环来进行彼此限制,一人每轮只拿一本for(b=1;b<=5;b++)for(c=1;c<=5&&a!=b;c++)//此处提前进行前两......
  • C语言趣味编程之百钱百鸡
    //一只公鸡值5钱,一只母鸡值3钱,三只小鸡值1钱,实现百钱百鸡//不等式;cock+hen+chicken=100,5cock+3hen+chicken/3.0=100//#include<stdio.h>//头文件//main()//主函数,有且仅有一个//{/利用三层循环加条件语句实现不等式方程组:cock+hen+chicken=100,5*cock+3*hen+chic......
  • C语言趣味编程之抓交通肇事犯
    include<stdio.h>main(){inti,j,k,temp;//i,j,k,分别表示前两位车牌号、后两位车牌号和车牌号,temp为验证是否车牌号为某个数的平方for(i=0;i<=9;i++)for(j=0;j<=9;j++)//通过两个for循环来列举前两位和后两位车牌号{if(i!=j)//判断前两个相同车牌号和后两个车牌号是......