一、学习Modbus的快速方法
1.1 寄存器速记
作为初学者,阅读Modbus协议时会发现它的概念别扭、重复、不易区分,比如线圈状态(Coil Status)、离散输入状态(Discrete Input Status)、保持寄存器(Holding Register)、输入寄存器(Input Register)。
回到事情的本质,在工业控制PLC领域,涉及数字信号的输入、输出,模拟信号的输入、输出,如下图所示:
对于软件开发而言:
- 想得到按键输入状态时,读取到的是一位数据;
- 想控制LED时,需要输出一位数据,想读取LED当前状态时,也可以读取到一位数据
- 想读取模拟信号时,读取到的是多位数据,比如16位数据
- 想输出模拟信号时,写入的是多位数据,比如16位数据;也可以读取“模拟量输出”的当前值。
在上图中,“数字量输入DI”是只读的,“数字量输出DO”是可读可写的,“模拟量输入AI”是只读的,“模拟量输出AO”是可读可写的。
上图里的“模拟量输入AI”、“模拟量输出AO”都表示“多位数值”,这些“多位数值”无需局限于只表示“模拟量”,也可以表示“多位数字量”。把AI、AO的含义扩展后,如下图所示:
对于软件开发而言:
- 想得到按键输入状态时,读取到的是一位数据;
- 想控制LED时,需要输出一位数据,想读取LED当前状态时,也可以读取到一位数据
- 想读取参数时,读取到的“输入寄存器”,得到多位数据,比如16位数据
- 想设置参数时,写的是“保存寄存器”,写入的是多位数据,比如16位数据;也可以读“保存寄存器”
在电子系统里,无论是单bit的数值、多bit的数值,都是保存在寄存器里。根据上图,这些寄存器可以分为4类:
寄存器种类 | 说明 | 与PLC类比 | 举例说明 |
---|---|---|---|
线圈状态(Coil Status) | 输出端口。可设定端口输出状态,也可以读取该位的输出状态。可分为两种不同的执行状态,列如保持型或边沿触发型 | DO(数字量输出) | 电磁阀输出、MOSFEF输出、LED显示等 |
离散输入状态(Discrete Input Status) | 输入端口。通过外部设定改变输入状态,可读但不可以写 | DI(数字量输入) | 拨码开关、接近开关等 |
保持寄存器(Holding Register) | 输出参数或保持参数,控制器运行时被设定的某些参数,可读可写 | AO(模拟量输出) | 模拟量输出设定值,PID运行参数,变量阀输出大小,传感器报警上限下限 |
输入寄存器(Input Register) | 输入参数。控制器运行时从外部设备获得的参数,但可读不可写 | AI(模拟量输入) | 模拟量输入 |
在Modbus中,多位操作时都是16位(2bytes)的,总结如下:
- bit操作涉及的寄存器有2类:线圈状态(可读可写)、离散输入状态(只读)
- 16bit操作的寄存器有2类:保存寄存器(可读可写)、输入寄存器(只读)
一个设备里,可能有多个“线圈状态”、多个“离散输入状态”、多个“保存寄存器”、多个“输入寄存器”。怎么分辨某类寄存器中的某一个?它们有“寄存器地址”,如下图所示:
寄存器种类 | PLC寄存器地址范围 | Modbus寄存器地址范围 | 简称 | 读写状态 |
---|---|---|---|---|
线圈状态 | 00001~09999 | 0000H~FFFFH | 0x | 可读可写 |
离散输入状态 | 10001~19999 | 0000H~FFFFH | 1x | 只读 |
保持寄存器 | 40001~49999 | 0000H~FFFFH | 4x | 可读可写 |
输入寄存器 | 30001~39999 | 0000H~FFFFH | 3x | 只读 |
在上表中,“线圈状态”的寄存器N、“离散输入状态”的寄存器N,是两个不同的寄存器。
简单记忆方法:“
- 偶数类的寄存器”是可读可写的,比如“0x”和“4x”;
- “奇数类的寄存器”是只读的,比如“1x”和“3x”;
- “0x”和“1x”是bit寄存器;
- “3x”和“4x”是16bit寄存器。
1.2 协议速记
Modbus是一主多从
的协议,如下图所示:
主控发出的数据里,必定含有如下信息:
- 设备地址:你要访问从设备1,还是访问从设备2(从设备识别到设备地址与自身地址匹配才会去处理主设备中的数据包)
- 访问哪类寄存器,是读还是写:这被称为功能码(比如读取离散输入寄存器)
- 起始寄存器地址、寄存器数量:这在数据里定义(与功能码相关:拿上面为例 这里就需要说明读取哪个离散输入寄存器 要读取一个还是多个)
- 为了保证数据传输的可靠,还附带有CRC检验码
以Modbus RTU协议为例,主控发出的数据包格式如下:
功能代码有哪些?常用的功能码如下:
- 读线圈状态(01)
- 读离散输入状态(02)
- 写单个线圈(05)、写多个线圈(15)
- 读保持寄存器(03)
- 读输入寄存器(04)
- 写单个保存寄存器(06)、写多个保存寄存器(16)
数据的格式,由功能代码确定。以“读线圈状态”为例,主控发出的请求、从设备返回的响应包,或者从设备返回的错误包,格式如下:
Fuction code 中的 0x01 表示读线圈。寄存器起始地址(“Starting Address”)是16位的,先传输高字节,再传输低字节。线圈数量(“Quantiti of coils”)也是16位的,先传输高字节,再传输低字节
。
响应包回复多少个数据呢(上图中N为多少)?N = Quantiti of coils / 8,如果余数不等于0,则N再加1。比如Quantiti of coils=9,则返回2个字节
。
在《Modbus_Application_Protocol_V1_1b3.pdf》中,列出了如下功能表。根据次表,在结合《5.5 Moubus功能码详解》的示例,就可以对Modbus RTU协议有很好的理解了。
二、初识Modbus
2.1 背景
Modbus诞生于1979年莫迪康(Modicon)公司,后来被施耐德电气公司收购。Modbus提供通用语言用于彼此通信的设备和设备,是全球第一个真正用于工业现场的总线协议。Modbus已经成为工业领域通信协议的业界标准,并且现在是工业电子设备之间常用的连接方式。Modbus作为目前工业领域应用最广泛的协议,之后为了更好地普及和推动Modbus基于以太网 (TCP/IP) 的分布式应用,施耐德公司已将Modbus协议的所有权移交给IDA (Interface for Distributed Automation,分布式自动化接口)组织,并成立了Modbus-IDA组织,此组织的成立和发展进一步推动了Modbus协议的广泛应用。
2.2 什么是Modbus?
2.2.1 Modbus简介
Modbus协议是一种已广泛应用于当今工业控制领域的通用通讯协议。通过此协议,控制器相互之间、或控制器经由网络(如以太网)可以和其它设备之间进行通信。Modbus协议使用的是主从通讯技术,即由主设备主动查询和操作从设备。一般将主控设备方所使用的协议称为Modbus Master,从设备方使用的协议称为Modbus Slave。典型的主设备包括工控机和工业控制器等;典型的从设备如PLC可编程控制器等。有了它,不同厂商生产的控制设备就可以连接成工业网络,进行集中监控。Modbus协议定义了一个控制器能够认识和使用的消息结构,而不管它们是经过何种网络进行通信的;而且描述了控制器请求访问其他设备的过程,如何应答来自其他设备的请求,以及怎样侦测错误并记录,并制定了统一的消息域的结构和内容。 当在Modbus网络上通信时,Modbus协议决定了每个控制器必须要知道它们的设备地址,识别按地址发来的消息决定要产生何种行为。如果需要回应,则控制器将生成反馈信息并通过Modbus协议发送。
Modbus通讯物理接口可以选用串口(包括RS232、RS485和RS422等),也可以选择以太网口。其通信遵循以下的过程:
- 主设备向从设备发送请求
- 从设备分析并处理主设备的请求,然后向主设备发送结果
- 如果出现任何差错,从设备将返回一个异常功能码
此协议定义了一个控制器能认识使用的消息结构,而不管它们是经过何种网络进行通信的。它描述了一控制器请求访问其它设备的过程,如何回应来自其它设备的请求,以及怎样侦测错误并记录。它制定了消息域格局和内容的公共格式。
当在Modbus网络上通信时,此协议决定了每个控制器须要知道它们的设备地址,识别按地址发来的消息,决定要产生何种行动。如果需要回应,控制器将生成反馈信息并用Modbus协议发出。在其它网络上,包含了Modbus协议的消息转换为在此网络上使用的帧或包结构。这种转换也扩展了根据具体的网络解决节地址、路由路径及错误检测的方法。
Modbus的工作方式是请求/应答,每次通讯都是主站先发送指令,可以是广播,或是向特定从站的单播;从站响应指令,并按要求应答,或者报告异常。当主站不发送请求时,从站不会自己发出数据,从站和从站之间不能直接通讯。
MODBUS 是一种应用层消息传递协议,位于 OSI 模型的第 7 层。它提供连接在不同类型总线或网络上的设备之间的客户端/服务器通信。
Modbus通信栈如下:
2.2.2 Modbus特点
Modbus通信协议具有以下几个特点:
- Modbus协议标准开放、公开发表且无版税要求。用户可以免费获取并使用Modbus协议,不需要交纳许可证费,也不会侵犯知识产权。
- Modbus协议支持多种电气接口,如RS232、RS485、TCP/IP等,还可以在各种介质上传输,如双绞线、光纤、红外、无线。
- Modbus协议消息帧格式简单、紧凑、通俗易懂。用户理解和使用简单,厂商容易开发和集成,方便形成工业控制网络。
- 可靠性: Modbus 是最古老的工业自动化通信协议。它使用和编程简单,因此学习曲线较低。
- 遗留基础设施:许多制造商在早期自动化方面投入了大量资金。Modbus 对于配置、DLR、节点、子站和其他基础设施非常友好,这些基础设施可能会被新的或更先进的协议所淘汰。
- 快速部署: Modbus 可以轻松、立即集成到 SCADA和其他控制系统中
- 灵活性: Modbus 已适应新兴技术。例如,Modbus TCP 可以通过话配器进行转换,以与LAN 和远程控制系统集成。它还可以利用基于网络和基于云的平台。
- 简单性:由于通信简单,因此可以轻松扩展到新技术。例如,Modbus TCP/P 由于指令集简单,部署速度很快。它还可以与以太网配合使用,无需添加芯片或板。
2.2.3 Modbus常用术语
名词 | 意义 |
---|---|
Master | 主(站) 设备 |
Slave | 从 (站) 设备 |
Client | 客户端 |
Server | 服务器端 |
ADU | 应用数据单元(Application Data Unit) |
PDU | 协议数据单元 (Protocol Data Unit) |
MSB | 最高有效位(Most Significant Bit) |
LSB | 最低有效位 (Least Significant Bit) |
MBAP | Modbus应用协议(Modbus Application Protocol) |
PLC | 可编程逻辑控制器(Programmable Logic Controller) |
2.2.4 Modbus事务处理
Modbus协议允许在各种网终体系结构内进行简单通信,每种设备 (包括PLC、HMI、控制面板、驱动程序、动作控制、输入/输出设备) 都能使用Modbus协议启动远程操作。在基于串行链路和以太网 (TCP/IP)的Modbus上可以进行相互通信。一些网关允许在几种使用MODBUS协议的总线或网络之间进行通讯。
MOUBUS网络体系结构的实例:
Modbus是一个请求、应答协议,并且提供统一的功能码用于数据传输服务。Modbus功能码是Modbus请求/应答PDU (Protocol Data Unit,协议数据单元)的元素之一,所谓的PDU其实就是Modbus协议定义的一个与基础通信层无关的简单协议数据单元。特定总线或网络上的Modbus协议映射能够在ADU (Application Data UInit ,应用数据单元)上引入一些附加域,从而实现完整而准确的数据传输。
为了寻求一种简洁的通信格式,Modbus协议定义了PDU模型,即功能码+数据的格式,而为了适应多种传输模式,又在PDU的基础上增加了必要的前缀 (如地址域)和后缀(如差错校验) ,形成了ADU模型(见下图)。
通用MODBUS帧如下:
Modbus事务处理过程:
-
主机设备 (或客户端)创建Modbus应用数据单元形成查询报文,其中功能码标识了向从机设备 (或服务器端)指示将要执行的操作。其中功能码占用1字节,有效的码字范围是十进制1 ~ 255 (其中128 ~255为异常响应保留) 。查询报文创建完毕,主机设备 (或客户端) 向从机设备 (或服务器端)发送报文,从机设备 (或服务器端)接收报文后根据功能码做出相应的动作,并将响应报文返回给主机设备 (或客户端),如图下所示:
MouBus事务处理(无异常)
-
如果在一个正确接收的Modbus ADU中不出现与请求Modbus功能有关的差错,那么从机设备 (或服务器端) 将返回正常的响应报文。如果出现与请求Modbus功能有关的差错,那么响应报文的功能码域将包括一个异常码,主机设备(或客户端)能够根据异常码确定下一步执行的操作;对于异常响应,服务器返回一个与原始功能码等同的码,设置该原始功能码的最高有效位为逻辑1,用于通知主设备(客户端)。如下图所示:
MouBus事务处理(异常响应)
三、Modbus软件与使用
3.1 Modbus软件简介
为了更好的学习和理解Modbus,这里推出三个软件Modbus Poll(主站设备)、Modbus Slave(从站设备)和虚拟串口软件,借助三款设备我们可以在PC上做一些基础实验,更加直观地观察通信数据,加深我们的理解,我们将它称为Modbus学习必备三件套,这是一个很好的入门方法。
3.2 Modbus Poll(主站设备)
3.2.1 Modbus Poll简介
Modbus Poll是Modbus主站设备仿真器,用于测试和调试Modbus从设备便于观察Modbus通信过程中的各种报文数据。该软件支持ModbusRTU、ASCII、TCP/IP。用来帮助开发人员测试Modbus从设备,或者其它Modbus协议的测试和仿真。它支持多文档接口,即,可以同时监视多个从设备/数据域。每个窗口简单地设定从设备ID,功能,地址,大小和轮询间隔。你可以从任意一个窗口读写寄存器和线圈。如果你想改变一个单独的寄存器,简单地双击这个值即可。或者你可以改变多个寄存器/线圈值。提供数据的多种格式方式,比如浮点、双精度、长整型(可以字节序列交换)。该软件支持Modbus RTU、ASCII、TCP/IP等协议模式。
Modbus Poll支持下列协议模式:
Modbus RTU | Modbus RTU Over TCP/IP |
---|---|
Modbus ASCII | Modbus ASCI Over TCP/IP |
Modbus TCP/IP | Modbus RTU Over UDP/IP |
Modbus UDP/IP | Modbus ASCII Over UDP/IP |
3.2.2 Modbus Poll 使用
点击链接获取软件,按照提示安装即可;链接:
https://pan.baidu.com/s/1SpTRz6Z1XlkoCZjDozwqog 提取码:timc
下载完界面如下:
状态栏:
- Tx = 0表示向主站发送数据帧次数,图中为0次;
- Err = 0表示通讯错误次数,图中为0次;
- ID = 1表示模拟的Modbus子设备的设备地址,图中地址为1;
- F = 03表示所使用的Modbus功能码,图中为03功能码;
- SR = 1000ms表示发送周期,1S一次。
- 红字部分,表示当前的错误状态,“No Connection”表示未连接状态。
建立连接:
点击Connection->Connect进入配置页面,选择我们想要的连接,选择我们虚拟出来的串口,选择模式,例如:我们选择串口的连接方式,选则RTU模式,对应我们的Modbus RTU协议;接下来在设置波特率、比特位、校验位、停止位,如下图所示:
设置参数:点击Setup->Read/Write Definition进入配置页面,配置从机地址、功能码、地址类型、寄存器地址、访问数量、轮询时间,具体配置如下图:
3.3 Modbus Slave(从站设备)
3.3.1 Modbus Slave简介
Modbus从设备仿真器,可以仿真32个从设备/地址域。每个接口都提供了对EXCEL报表的OLE自动化支持。主要用来模拟Modbus从站设备,接收主站的命令包,回送数据包。帮助Modbus通讯设备开发人员进行Modbus通讯协议的模拟和测试,用于模拟、测试、调试Modbus通讯设备,便于观察Modbus通信过程中的各种报文数据;可以32个窗口中模拟多达32个Modbus子设备。与Modbus Poll的用户界面相同,支持功能01, 02, 03, 04, 05, 06, 15, 16, 22和23,监视串口数据。
Modbus Slave支持下列协议模式:
Modbus RTU | Modbus RTU Over TCP/IP |
---|---|
Modbus ASCII | Modbus ASCI Over TCP/IP |
Modbus TCP/IP | Modbus RTU Over UDP/IP |
Modbus UDP/IP | Modbus ASCII Over UDP/IP |
3.3.2 Modbus Slave使用
获取软件链接同上,下载完后主页面如图所示:
建立连接:
点击Connection->Connect进入配置页面,选择我们想要的连接,选择我们虚拟出来的串口,选择模式,接下来在设置波特率、比特位、校验位、停止位,如下图所示:
设置参数:点击Setup->Read/Write Definition进入配置页面,配置从机地址、功能码、地址类型、寄存器地址、访问数量,具体配置如下图:
这里有两点需要我们注意一下:
- 一是:Function列表框选择功能中的0x~4x,表示的是存储区0区、1区、3区、4区
- 输出线圈
- 输入线圈
- 保持寄存器
- 输入寄存器
Modbus协议规定了4个存储区 分别是0、1、3、4区 其中0区和4区是可读可写,1区和3区是只读。
区号 | 名称 | 读写 | 地址范围 |
---|---|---|---|
0区 | 输出线圈 | 可读可写布尔量 | 00001-09999 |
1区 | 输入线圈 | 只读布尔量 | 10001-19999 |
3区 | 输入寄存器 | 只读寄存器 | 30001-39999 |
4区 | 保持寄存器 | 可读可写寄存器 | 40001-49999 |
- 二是:Address项,这里需要特别强调一下,Address表示Modbus寄存器地址,其取值范围与设备寄存器地址存在映射关系,如下表所示:
Device address | Modbus address | Description | Function | R/W |
---|---|---|---|---|
1…10000 | address - 1 | Coils(outputs) | 01 | Read/Write |
10001…20000 | address - 10001 | Discrete Inputs | 02 | Read |
40001…50000 | address - 40001 | Holding Registers | 03 | Read/Write |
30001…40000 | address - 30001 | Input Registers | 04 | Read |
这里我们只简单介绍下地址和存储区,下面我们会详细展开。
3.4 虚拟串口软件
3.4.1 软件简介
虚拟串口工具,可以创建2个互联的串口,如下图所示:
比如Modbus Poll工具使用COM1发送数据给COM2,Modbus Slave从COM2读到数据。使用虚拟串口,就可以不使用开发板也可以体验Modbus Poll、Modbus Slave。
打开下图红框内软件:
3.4.2 虚拟串口的使用
安装后运行虚拟串口程序“Virtual Serial Port Tools”,点击免费版本,安装下图创建2个串口:
打开设备管理器,可以看到如下串口:
3.5 Modbus Poll 与 Modbus Slave互联/通
下面我们进行Modbus Poll 与 Modbus Slave互联互通实验,通过形象直观的方式展示Modbus数据流,根据前面的设定我们已将知道了如何运用Modbus学习必备三件套,下面我们就通过三件套来进行实验,首先打开VSPD虚拟串口软件,设置虚拟串口,我这里就以上面设订COM1,COM2为例,接下来我们再来配置我们的Modbus Poll 与 Modbus Slave;
我们首先打开Modbus Slave端,设置连接,连接方式我们选择Serial Port串口连接,选择我们设置的串口COM1,模式选择RTU模式,如下图所示:
- Modbus Slave连接设定
在设置参数,从机地址我们设定1(你也可以自己随意设定),Function项我们选择03 Holding Register(4x),地址类型我们选择DEC(十进制格式),Address首地址我们设置为0,访问寄存器数量设置为10,如下图所示:
- Modbus Slave参数设定
接下来我们再来设置Modbus Poll端,设置方法也是和Modbus Slave端一一对应的,连接设定,参数设定,如下图所示:
- Modbus Poll连接设定
注意这里串口要选择我们设定的COM20,其它串口参数必须一一对应。
- Modbus Poll参数设定
设置好后,我们主设备和从设备分别连接了我们设置的COM1,COM2,这样我们便可观察当前寄存器的读取情况。
我们双击Modbus Poll(主设备端)地址中的0值,便可打开值设置窗口如下图所示:
修改值为66,点击Send打开Modbus Slave(从设备端)便可发现也做出了改变,如下图所示:
我们还可以打开Modbus Poll,点击Display,选择Commuaction,查看发送的报文:
TX是我们主站发送的报文,RX是从站返回的报文。