Modbus库开发笔记之一:实现功能的基本设计

摘要:
Modbus作为一种开放的工业通信协议,广泛应用于各种工业设备。现在,利用项目研究和开发的机会,开发您自己的Modbus协议栈。Modbus具有国际和国家标准,内容相同。事实上,作为应用层协议,Modbus协议对物理密钥没有特殊要求,可以实现光纤、无线等。在本次开发中,我们计划同时实现主站和从站的功能。异常事务处理流程2.操作设计根据我们对Modbus标准事务处理流程的理解,我们将设计主站和从站的具体操作流程。

Modbus作为开放式的工业通讯协议,在各种工业设备中应用极其广泛。本人也使用Modbus通讯很多年了,或者用现成的,或者针对具体应用开发,一直以来都想要开发一个比较通用的协议栈能在后续的项目中复用,而不必每次都写一遍。现在利用项目研发的机会,开发一个自己的Modbus协议栈。

Modbus有国际标准,也有国家标准,内容是完全一样的。在标准钟支持2种物理链路:一是基于RS485(RS232)的串行链路;二是基于以太网的TCP/IP链路。事实上,Modbus协议作为一种应用层协议对物理键子并没有特别的要求,光纤、无线等都是可以实现的。

本次主要是开发Modbus RTU和Modbus TCP两种标准协议方式,支持常用的功能码:

功能码

名称

实现

描述

0x01

读线圈

对可读写型的状态量进行读取

0x02

读离散输入

对只读型的状态量进行读取

0x03

读保持寄存器

对可读写型的寄存器量进行读取

0x04

读输入寄存器

对只读型的寄存器量进行读取

0x05

写单个线圈

对单个的读写型的状态量进行写入

0x06

写单个寄存器

对单个的读写型的寄存器量进行写入

0x0F

写多个线圈

对多个的读写型的状态量进行写入

0x10

写多个寄存器

对多个的读写型的寄存器量进行写入

Modbus协议是一种主从(或者说客户端/服务器)模式协议,有主站(客户端)发起事务请求,从站(服务器)响应事务请求。一般我们想要访问(或者说被访问)的设备即为从站(服务器),而我们通常去访问别人的设备就是主站(客户端)。通常在RTU时被称为主站和从站,而在TCP方式时被称为服务器和客户端。这种称呼只是叫法不同,但在本质上是没有区别我的。后续这两种称呼我们会同时使用。在这次开发中,我们计划同时实现主站和从站的功能。

1、标准流程

启动MODBUS 事务处理的客户机创建 MODBUS 应用数据单元。当从客户机向服务器设备发送报文时,功能码向服务器指示将执行哪种操作。

从客户机向服务器设备发送的报文数据域包括附加信息,服务器使用这个信息执行功能码定义的操作。如果在一个正确接收的 MODBUS ADU 中,不出现与请求 MODBUS 功能有关的差错,那么服务器至客户机的响应数据域包括请求数据。

Modbus库开发笔记之一:实现功能的基本设计第1张

正常事务处理流程

如果出现与请求 MODBUS 功能有关的差错,那么域包括一个异常码,服务器应用能够使用这个域确定下一个执行的操作。当服务器对客户机响应时,它使用功能码域来指示正常(无差错)响应或者出现某种差错(称为异常响应)。对于一个正常响应来说,服务器仅对原始功能码响应。

 Modbus库开发笔记之一:实现功能的基本设计第2张

异常事务处理流程

2、操作设计

根据我们对Modbus标准事务流程的理解,我们来设计主站和从站的具体操作过程。

主站操作流程:

(1)、初始化主站,站标识符,定时器、

(2)、生成访问命令

生成命令ADU分两层实现:网络层和链路层。

网络层实现与具体链路无关的PDU(包括功能码和数据,这里的数据指传送的数据,并非指变量的值,事实上数量和地址也包含在内)。对应的文件是mbpdu.c/.h,实现对pud单元的数据处理,包括命令和响应。

链路层实现ADU的封装。对应的文件是mbrtu.c/.h(和mbtcp.c/.h和mbascii.c/.h),实现ADU单元的封装;同时作为从站时,写操作的响应也在此处封装。

(3)、定时发送访问命令,读命令定是轮询,写命令具有更高的优先级。在有写命令时暂停读命令,

(4)、解析接收到的数据,进行相应操作

从站操作流程:

(1)、协议栈初始化:从站地址设置,创建数据存储域,访问控制

(2)、从站接收消息并解析

解析消息后操作数据(读写对应对象的值)

生成响应

(3)、生成响应数据并回复

3、命令格式

不同的功能码具有不同的消息格式,我们只简单说一下我们将要实现的以上8中功能码的信息格式。

(1)功能码0x01:读线圈

在一个远程设备中,使用该功能码读取线圈的1至2000个连续状态。请求 PDU详细说明了起始地址,即指定的第一个线圈地址和线圈编号。从零开始寻址线圈。因此寻址线圈 1-16 为 0-15。

根据数据域的每个比特将响应报文中的线圈分成为一个线圈。指示状态为 1= ON 和 0= OFF。第一个数据字节的 LSB(最低有效位)包括在询问中寻址的输出。其它线圈依次类推,一直到这个字节的高位端为止,并在后续字节中从低位到高位的顺序。

如果返回的输出数量不是八的倍数,将用零填充最后数据字节中的剩余比特(一直到字节的高位端)。字节数量域说明了数据的完整字节数。具体格式举例如下:

 Modbus库开发笔记之一:实现功能的基本设计第3张

(2)功能码0x02:读离散量输入

在一个远程设备中,使用该功能码读取离散量输入的 1 至 2000 连续状态。请求 PDU 详细说明了起始地址,即指定的第一个输入地址和输入编号。从零开始寻址输入。因此寻址输入 1-16 为 0-15。

根据数据域的每个比特将响应报文中的离散量输入分成为一个输入。指示状态为1=ON 和0=OFF。第一个数据字节的 LSB(最低有效位)包括在询问中寻址的输入。其它输入依次类推,一直到这个字节的高位端为止,并在后续字节中从低位到高位的顺序。

如果返回的输入数量不是八的倍数,将用零填充最后数据字节中的剩余比特(一直到字节的高位端)。字节数量域说明了数据的完整字节数。具体格式举例如下:

 Modbus库开发笔记之一:实现功能的基本设计第4张

事实上,功能码0x01和0x02的数据格式是完全一样的,操作方式也是完全一样的,所不同只是操作的对象不同。

(3)功能码0x03:读保持寄存器

在一个远程设备中,使用该功能码读取保持寄存器连续块的内容。请求 PDU 说明了起始寄存器地址和寄存器数量。从零开始寻址寄存器。因此,寻址寄存器 1-16 为 0-15。

将响应报文中的寄存器数据分成每个寄存器有两字节,在每个字节中直接地调整二进制内容。

对于每个寄存器,第一个字节包括高位比特,并且第二个字节包括低位比特。具体的格式举例如下:

 Modbus库开发笔记之一:实现功能的基本设计第5张

响应信息的长度与具体读取的数据量有关。

(4)功能码0x04:读输入寄存器

在一个远程设备中,使用该功能码读取 1 至大约 125 的连续输入寄存器。请求 PDU 说明了起始地址和寄存器数量。从零开始寻址寄存器。因此,寻址输入寄存器 1-16 为 0-15。

将响应报文中的寄存器数据分成每个寄存器为两字节,在每个字节中直接地调整二进制内容。

对于每个寄存器,第一个字节包括高位比特,并且第二个字节包括低位比特。具体的格式举例如下:

 Modbus库开发笔记之一:实现功能的基本设计第6张

事实上,功能码0x03和0x04的数据格式是完全一样的,操作方式也是完全一样的,所不同只是操作的对象不同。响应信息的长度与具体读取的数据量有关。

(5)功能码0x05:写单个线圈

在一个远程设备上,使用该功能码写单个输出为 ON 或 OFF。

请求数据域中的常量说明请求的ON/OFF状态。十六进制值0xFF00请求输出为 ON。十六进制值0x0000 请求输出为OFF。其它所有值均是非法的,并且对输出不起作用。

请求 PDU 说明了强制的线圈地址。从零开始寻址线圈。因此,寻址线圈1为0。线圈值域的常量说明请求的 ON/OFF 状态。十六进制值 0XFF00 请求线圈为 ON。十六进制值 0X0000 请求线圈为OFF。其它所有值均为非法的,并且对线圈不起作用。

正常响应是请求的应答,在写入线圈状态之后返回这个正常响应。具体的格式举例如下:

 Modbus库开发笔记之一:实现功能的基本设计第7张

(6)功能码0x06:写单个寄存器

在一个远程设备中,使用该功能码写单个保持寄存器。

请求 PDU 说明了被写入寄存器的地址。从零开始寻址寄存器。因此,寻址寄存器1为0。

正常响应是请求的应答,在写入寄存器内容之后返回这个正常响应。具体的格式举例如下:

 Modbus库开发笔记之一:实现功能的基本设计第8张

(7)功能码0x0F:写多个线圈

在一个远程设备中,使用该功能码强制线圈序列中的每个线圈为ON或OFF。请求PDU说明了强制的线圈参考。从零开始寻址线圈。因此,寻址线圈1为0。

请求数据域的内容说明了被请求的ON/OFF状态。域比特位置中的逻辑“1”请求相应输出为ON。域比特位置中的逻辑“0”请求相应输出为 OFF。

正常响应返回功能码、起始地址和强制的线圈数量。具体的格式举例如下:

 Modbus库开发笔记之一:实现功能的基本设计第9张

(8)功能码0x10:写多个寄存器

在一个远程设备中,使用该功能码写连续寄存器块(1至约120个寄存器)。

在请求数据域中说明了请求写入的值。每个寄存器将数据分成两字节。

正常响应返回功能码、起始地址和被写入寄存器的数量。具体的格式举例如下:

 Modbus库开发笔记之一:实现功能的基本设计第10张

清楚了以上这些说明,我们就可以开始Modbus协议的开发之旅了。

免责声明:文章转载自《Modbus库开发笔记之一:实现功能的基本设计》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Oracle下批量将一个用户的所有表的select权限赋值给另外一个用户VBA工作表排序转载下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

uboot完全手册---14

1. u-boot介绍 本次移植采用的是U-Boot-1.2.0版本。 3. U-Boot源码分析 3.1 源码入口的解释 可能大多数的同学上网查资料后都了解到,stage1阶段的启动代码,主要就在start.s文件里。此start.s也是系统上电后执行的第一个代码。它全部由汇编编写。在讲述start.s之前,我们先来了解一下,系统怎么知道它要先去star...

[转]iOS高级调试&逆向技术-汇编寄存器调用

前言 本文翻译自Assembly Register Calling Convention Tutorial 序言 通过本教程,你会可以看到CPU使用的寄存器,并探索和修改传递给函数调用的参数。还将学习常见的苹果计算机架构以及如何在函数中使用寄存器。这就是所谓架构的调用约定。 了解汇编是如何工作的,以及特定架构调用约定是如何工作是一项极其重要的技能。它可以...

Modbus协议服务端(Netty)

pom.xml <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.0.21.Final...

STM32 USART整理说明(转)

  该接口通过3个引脚连接到另外的外部设备上。    任何USART双向通信都至少需要两个引脚:接收数据输入RX和发送数据输出TX。    当发送器禁能时输出引脚恢复到I/O端口配置。当发送器使能时且无数据发送,TX引脚为高电平。     字长可以通过设置USART_CR1寄存器中的M位来选择是8位还是9位。    TX引脚在起始位期间为低,停止位期间为高...

单片机中断的IE和IP寄存器(摘抄)

收藏 评论(0) 分享到 微博 QQ 微信 LinkedIn 一、中断允许寄存器IE    CPU对中断源的开放或中断屏蔽的控制是通过中断允许寄存器IE设置的,IE既可按字节地址寻址(其字节地址为A8H),又可按位寻址。AT89S52单片机中的6个中断矢量都是可屏蔽中断,通过对IE的某些位置位和清0,允许或禁止某个中断,当对IE的EA位清0时...

【Linux 驱动】第九章 与硬件通信

在学习有关I/O总线的内容时,最好先看看相关的知识:从PC总线到ARM的内部总线 一,I/O 端口和 I/O 内存 每种外设都是通过读写寄存器来进行控制。 大部分外设都有几个寄存器,不管是在内存地址空间还是在I/O地址空间,这些寄存器的访问地址都是连续的。在硬件层,内存区和 I/O 区域没有概念上的区别: 它们都是通过向在地址总线和控制总线发出电平信号来进...