STM32--MODBUS 通讯篇

STM32–MODBUS 通讯篇


文章目录

  • STM32--MODBUS 通讯篇
  • 一、MODBUS简介
  • 二、MODBUS功能码详解
    • 1. 寄存器分类
    • 2. 常用功能码
    • 2. 常用功能码说明
      • ①读线圈寄存器——01H
      • ②读离散输入寄存器——02H
      • ③读保持寄存器——03H
      • ④读输入寄存器——04H
      • ⑤写单个线圈寄存器——05H
      • ⑥写单个保持寄存器——06H
      • ⑦写多个线圈寄存器——0FH
      • ⑧写多个保持寄存器——10H
    • 3.小结
  • 三、MODBUS协议详解
    • 1.两种串行传输模式
      • ①.ASCII模式
      • ②.RTU模式
      • ③小结
    • 2. ModbusTCP
      • ①结构帧MBAP
      • ②结构帧PDU
      • ②小结
  • 四、基于STM32-MODBUS实现


一、MODBUS简介

①Modbus协议是一种请求/应答的串行链路协议,是一种工业现场总线协议标准。是一项应用层报文传输协议,用于在通过不同类型的总线或网络连接的设备之间的客户机/服务器通信。

②Modbus协议是一项应用层报文传输协议,包括ASCII、RTU、TCP三种报文类型。

③标准的Modbus协议物理层接口有RS232、RS422、RS485和以太网接口,采用master/slave方式通信。

④MODBUS 是一项应用层报文传输协议,用于在通过不同类型的总线或网络连接的设备之间的客户机/服务器通信。

MODBUS 通用帧如图:STM32--MODBUS 通讯篇_第1张图片


二、MODBUS功能码详解

1. 寄存器分类

Modbus寄存器分为四种,如表

寄存器种类 数据类型 访问类型 功能码 PLC地址 寄存器地址
线圈寄存器 读写 01H 05H 0FH 00001-09999 0000H-FFFFH
离散输入寄存器 只写 02H 10001-19999 0000H-FFFFH
输入寄存器 只写 04H 30001-39999 0000H-FFFFH
保持寄存器 读写 03H 06H 10H 40001-49999 0000H-FFFFH

2. 常用功能码

Modbus中常用功能码有8个,可以分为位操作和字操作两类,如表所示:

功能码 描述 PLC地址 寄存器地址 位/字操作 操作数量
01H 读线圈寄存器 00001-09999 0000H-FFFFH 位操作 单个或多个
02H 读离散输入寄存器 10001-19999 0000H-FFFFH 位操作 单个或多个
03H 读保持寄存器 40001-49999 0000H-FFFFH 字操作 单个或多个
04H 读输入寄存器 30001-39999 0000H-FFFFH 字操作 单个或多个
05H 写单个线圈寄存器 00001-09999 0000H-FFFFH 位操作 单个
06H 写单个保持寄存器 40001-49999 0000H-FFFFH 字操作 单个
0FH 写多个线圈寄存器 00001-09999 0000H-FFFFH 位操作 多个
10H 写多个保持寄存器 40001-49999 0000H-FFFFH 字操作 多个

2. 常用功能码说明

①读线圈寄存器——01H

●功能码01H读取Modbus从机中线圈寄存器的状态,可以是单个寄存器,或者多个连续的寄存器。

●假设从机地址为01H,读取的线圈寄存器的起始地址为0017H,读取38个寄存器,指令如表所示:
发送读线圈寄存器指令:

从机地址 功能码 起始地址高位 起始地址低位 寄存器数量高位 寄存器数量低位 CRC高位 CRC低位
01 01 00 17 00 26 0D D4

●响应:各线圈的状态与数据内容的每个bit对应,1代表ON,0代表OFF。如果查询的线圈数量不是8的倍数,则在最后一个字节的高位补0。

读线圈寄存器状态响应:

从机地址 功能码 返回字节数 数据1 数据2 数据3 数据4 数据5 CRC高位 CRC低位
01 01 05 CD 6B B2 0E 1B 44 EA

●其中,第一个字节CDH对应线圈0017H到001E的状态,转为二进制是11001101,其中bit0对应0017H,bit7对应001E,如表所示:

线圈0017H到001EH的状态:

001EH 001DH 001CH 001BH 001AH 0019H 0018H 0017H
ON ON OFF OFF ON ON OFF ON

●最后一个字节为1BH,对应线圈0037H到003CH的状态,转为二进制是00011011,其中bit0对应0037H,bit5对应003CH,其余两位用0填充,如表所示:

线圈0037H到003CH的状态:

001EH 001DH 001CH 001BH 001AH 0019H 0018H 0017H
ON ON OFF OFF ON ON OFF ON

②读离散输入寄存器——02H

●功能码02H读取Modbus从机中离散输入寄存器的状态,可以是单个寄存器,或者多个连续的寄存器。

●假设从机地址为01H,读取的离散输入寄存器的起始地址为00C4H,读取22个寄存器,指令如表所示:

发送读离散输入寄存器指令:

从机地址 功能码 起始地址高位 起始地址低位 寄存器数量高位 寄存器数量低位 CRC高位 CRC低位
01 02 00 C4 00 16 B8 39

●响应:各个离散输入寄存器的状态与数据内容的每个bit对应,1代表ON,0代表OFF。如果查询的线圈数量不是8的倍数,则在最后一个字节的高位补0

读离散输入寄存器的返回结果:

从机地址 功能码 返回字节数 数据1 数据2 数据3 CRC高位 CRC低位
01 02 03 AC DB 35 22 88

●其中,第一个字节ACH对应00C4H到00CBH寄存器的状态,转为二进制是10101100,其中bit0对应00C4H,bit7对应00CB,如表所示:

寄存器00C4H到00CBH的状态:

00CBH 00CAH 00C9H 00C8H 00C7H 00C6H 00C5H 00C4H
1 0 1 0 1 1 0 0
ON OFF ON OFF ON ON OFF OFF

●最后一个字节为35H,对应寄存器00D4H到00D9H的状态,转为二进制是00110101,其中bit0对应00D4H,bit5对应00D9H,其余两位用0填充,如表所示:

寄存器00D4H到00D9H的状态

00DBH 00DAH 00D9H 00D8H 00D7H 00D6H 00D5H 00D4H
0 0 1 1 0 1 0 1
ON OFF ON OFF ON ON OFF OFF

③读保持寄存器——03H

●功能码03H读取Modbus从机中保持寄存器的数据,可以是单个寄存器,或者多个连续的寄存器。
●假设从机地址为01H,读取的保持寄存器的起始地址为006BH,读取3个寄存器,指令如表所示:

发送读保持寄存器指令:

从机地址 功能码 起始地址高位 起始地址低位 寄存器数量高位 寄存器数量低位 CRC高位 CRC低位
01 03 00 6B 00 03 74 17

●响应:每个保持寄存器的长度为2个字节。保持寄存器之间,低地址寄存器先传输,高地址寄存器后传输。单个保持寄存器,高字节数据先传输,低字节数据后传输。

读保持寄存器的返回结果:

从机地址 功能码 字节数 006BH高位字节 006BH低位字节 006CH高位字节 006CH低位字节 006BH高位字节 006BH低位字节 CRC高位 CRC低位
01 03 06 00 6B 00 13 00 00 F5 79

④读输入寄存器——04H

●功能码04H读取Modbus从机中输入寄存器的数据,可以是单个寄存器,或者多个连续的寄存器。
●假设从机地址为01H,读取的保持寄存器的起始地址为0008H,读取2个寄存器,指令如表所示:

发送读输入寄存器指令:

从机地址 功能码 起始地址高位 起始地址低位 寄存器数量高位 寄存器数量低位 CRC高位 CRC低位
01 04 00 6B 00 02 00 17

●响应:每个输入寄存器的长度为2个字节。输入寄存器之间,低地址寄存器先传输,高地址寄存器后传输。单个输入寄存器,高字节数据先传输,低字节数据后传输。

读输入寄存器的返回结果:

从机地址 功能码 字节数 0008H高位字节 0008H低位字节 0009H高位字节 0009H低位字节 CRC高位 CRC低位
01 04 04 00 0A 00 0B 9A 41

⑤写单个线圈寄存器——05H

●功能码05H写单个线圈寄存器,FF00H请求线圈处于ON状态,0000H请求线圈处于OFF状态。
●假设从机地址为01H,线圈寄存器的地址为00ACH,使其处于ON状态的指令,如表所示:

发送写单个线圈指令:

从机地址 功能码 起始地址高位 起始地址低位 寄存器数量高位 寄存器数量低位 CRC高位 CRC低位
01 05 00 AC FF 00 4C 1B

●响应:如果写入成功,返回发送的指令,即010500ACFF004C1B。

从机地址 功能码 起始地址高位 起始地址低位 寄存器数量高位 寄存器数量低位 CRC高位 CRC低位
01 05 00 AC FF 00 4C 1B

⑥写单个保持寄存器——06H

●功能码06H写单个保持寄存器。
●假设从机地址为01H,保持寄存器的地址为0001H,数据位0003H,指令如表所示:

发送写单个保持寄存器指令:

从机地址 功能码 起始地址高位 起始地址低位 寄存器数量高位 寄存器数量低位 CRC高位 CRC低位
01 06 00 01 00 03 98 0B

●响应:如果写入成功,返回发送的指令,即010600010003980B。

从机地址 功能码 起始地址高位 起始地址低位 寄存器数量高位 寄存器数量低位 CRC高位 CRC低位
01 06 00 01 00 03 98 0B

⑦写多个线圈寄存器——0FH

●功能码0FH写多个线圈寄存器。如果对应的数据位为1,表示线圈状态为ON;如果对应的数据位为0,表示线圈状态为OFF。线圈寄存器之间,低地址寄存器先传输,高地址寄存器后传输。单个线圈寄存器,高字节数据先传输,低字节数据后传输。如果写入的线圈寄存器的个数不是8的倍数,则在最后一个字节的高位补0。

●假设从机地址为01H,线圈寄存器的起始地址为0013H,写入10个寄存器,指令如表所示:

发送写入多个线圈寄存器指令:

从机地址 功能码 起始地址高位 起始地址低位 寄存器数量高位 寄存器数量低位 字节数 数据1 数据2 CRC高位 CRC低位
01 0F 00 13 00 0A 02 CD 01 72 CB

●其中,CDH对应线圈0013H到001AH的内容,01H对应线圈001B到001CH的内容,未使用位用0填充。

线圈寄存器0013H到001CH的内容:

001AH 0019H 0018H 0017H 0016H 0015H 0014H 0013H
1 1 0 0 1 1 0 1
0022H 0021H 0020H 001FH 001EH 001DH 001CH 001BH
0 0 0 0 0 0 0 1

●响应:如果写入成功,返回写入的寄存器数量,如表所示

写多个线圈寄存器的返回结果:

从机地址 功能码 起始地址高位 起始地址低位 寄存器数量高位 寄存器数量低位 CRC高位 CRC低位
01 0F 00 13 00 0A 24 09

⑧写多个保持寄存器——10H

●功能码10H写多个保持寄存器,其中每个保持寄存器的长度为两个字节。
●假设从机地址为01H,保持寄存器的起始地址为0001H,写入2个寄存器,指令如表所示:

发送写入多个保持寄存器指令:

从机地址 功能码 起始地址高位 起始地址低位 寄存器数量高位 寄存器数量低位 字节数 0001H高位 0001H低位 0002H高位 0002H低位 CRC高位 CRC低位
01 010 00 01 00 02 04 00 0A 01 02 92 30

●响应:如果写入成功,返回写入的寄存器数量,如表所示:

从机地址 功能码 起始地址高位 起始地址低位 寄存器数量高位 寄存器数量低位 CRC高位 CRC低位
01 10 00 01 00 02 10 08

3.小结

●功能码详解主要参考文献为:
https://blog.csdn.net/lakerszhy/article/details/68927178?locationNum=4&fps=1


三、MODBUS协议详解

1.两种串行传输模式

①.ASCII模式

编码系统:
十六进制,ASCII 字符 0-9, A-F。报文中每个 ASCII 字符含有 1 个十六进制字符

Bits per Byte:
1 起始位
7 数据位, 首先发送最低有效位
1 位作为奇偶校验
1 停止位

奇偶校验 :
●偶校验是要求的, 其它模式 ( 奇校验, 无校验 ) 也可以使用。 为了保证与其它产品的最大兼容性,同时支持无校验模式是建议的。默认校验模式模式 必须为偶校验。
注 : 使用无校验要求 2 个停止位。

字符串行传送:
●每个字符或字节均由此顺序发送(从左到右):
●最低有效位 (LSB) . . . 最高有效位 (MSB),数据传输如图:
●有奇偶检验
在这里插入图片描述
●无奇偶检验:
STM32--MODBUS 通讯篇_第2张图片

Modbus ASCII 报文帧:
在 ASCII 模式, 报文用特殊的字符区分帧起始和帧结束。一个报文必须以一个‘冒号’ ( : )(ASCII 十六进制 3A )起始,以 ‘回车-换行’ (CR LF) 对 (ASCII 十六进制 0D 和 0A) 结束。
注 : LF 字符可以通过特定的 Modbus 应用命令 (参见 Modbus 应用协议规范) 改变。

对于所有的域,允许传送的字符为十六进制 0–9, A–F (ASCII 编码)。 设备连续的监视总线上的 ‘冒号’ 字符。 当收到这个字符后,每个设备解码后续的字符一直到帧结束。

报文帧包括:起始、地址、功能码、数据、LRC校验位、结束。如图:

在这里插入图片描述
注:每个字符子节需要用两个字符编码。因此,为了确保 ASCII 模式 和 RTU 模式在 Modbus 应用级兼容,ASCII
数据域最大数据长度为 (2x252) 是 RTU 数据域 (252) 的两倍。
必然的, Modbus ASCII 帧的最大尺寸为 513 个字符。

ASCII 传输模式状态如图:

STM32--MODBUS 通讯篇_第3张图片
帧检验域:
①帧检验方式为::纵向冗余校验 (LRC - Longitudinal Redundancy Checking)

②LRC 域检验不包括起始“冒号”和结尾 CRLF 对的整个报文的内容。不管报文有无奇偶校验,均执行此检验。

③LRC 域为一个子节,包含一个 8 位二进制值。LRC 值由发送设备计算,然后将 LRC 附在报文后面。接收设备在接收报文时重新计算 LRC 的值,并将计算结果于实际接收到的 LRC 值相比较。如果两个值不相等,则为错误。LRC 的计算, 对报文中的所有的连续 8 位字节相加,忽略任何进位,然后求出其二进制补码。执行检验针对不包括起始“冒号”和结尾 CRLF 对的整个 ASCII 报文域的内容。在 ASCII 模式,LRC 的结果被 ASCII 编码为两个字节并放置于 ASCII 模式报文帧的结尾, CRLF 之前。


②.RTU模式

RTU模式:报文中每个 8 位字节含有两个 4 位十六进制字符。这种模式的主要优点是较高的数据密度,在相同的波特率下比ASCII 模式有更高的吞吐率。每个报文必须以连续的字符流传送。

编码系统:

8–位二进制报文中每个 8 位字节含有两个 4 位十六进制字符(0–9, A–F)

Bits per Byte:

1 起始位
8 数据位, 首先发送最低有效位
1 位作为奇偶校验
1 停止位

奇偶校验 :
●偶校验是要求的, 其它模式 ( 奇校验, 无校验 ) 也可以使用。 为了保证与其它产品的最大兼容性,同时支持无校验模式是建议的。默认校验模式模式 必须为偶校验。
注 : 使用无校验要求 2 个停止位。

字符串行传送:
●每个字符或字节均由此顺序发送(从左到右):
●最低有效位 (LSB) . . . 最高有效位 (MSB),数据传输如图:
●有奇偶校验:
STM32--MODBUS 通讯篇_第4张图片
●无奇偶校验:
STM32--MODBUS 通讯篇_第5张图片

Modbus RTU 报文帧:

RTU 报文帧描述如图 :
STM32--MODBUS 通讯篇_第6张图片
注意: Modbus RTU 帧最大为 256 字节。

●在 RTU 模式,报文帧由时长至少为 3.5 个字符时间的空闲间隔区分。在后续的部分,这个时间区间被称作 t3.5。如果两个字符之间的空闲间隔大于 1.5 个字符时间,则报文帧被认为不完整应该被接收节点丢弃。传输格式如图:

STM32--MODBUS 通讯篇_第7张图片
STM32--MODBUS 通讯篇_第8张图片
注 :
RTU 接收驱动程序的实现,由于 t1.5 和 t3.5 的定时,隐含着大量的对中断的管理。在高通信速率下,这导致 CPU 负担加重。因此,在通信速率等于或低于 19200 Bps 时,这两个定时必须严格遵守;对于波特率大于 19200 Bps 的情形,应该使用 2 个定时的固定值:建议的字符间超时时间(t1.5)为 750µs,帧间的超时时间 (t1.5) 为 1.750ms。

●下图表示了对 RTU 传输模式状态图的描述。 “主节点” 和 “子节点” 的不同角度均在相同的图中表示:
STM32--MODBUS 通讯篇_第9张图片
上面状态图的一些解释:
● 从 “初始” 态到 “空闲” 态转换需要 t3.5 定时超时: 这保证帧间延迟
● “空闲” 态是没有发送和接收报文要处理的正常状态。
●在 RTU 模式, 当没有活动的传输的时间间隔达 3.5 个字符长时,通信链路被认为在 “空闲”
态。
●当链路空闲时, 在链路上检测到的任何传输的字符被识别为帧起始。 链路变为 “活动” 状态。
然后, 当链路上没有字符传输的时间间个达到 t3.5 后,被识别为帧结束。
● 检测到帧结束后,完成 CRC 计算和检验。然后,分析地址域以确定帧是否发往此设备,如果不是,则丢弃此帧。 为了减少接收处理时间,地址域可以在一接到就分析,而不需要等到整个帧结束。这样,CRC 计算只需要在帧寻址到该节点 (包括广播帧) 时进行。

帧检验域:
①帧检验方式为:循环冗余校验 (CRC)

②CRC 包含由两个 8 位字节组成的一个 16 位值。

③CRC 域作为报文的最后的域附加在报文之后。计算后,首先附加低字节,然后是高字节。CRC

④高字节为报文发送的最后一个子节。附加在报文后面的 CRC 的值由发送设备计算。接收设备在接收报文时重新计算 CRC 的值,
并将计算结果于实际接收到的 CRC 值相比较。如果两个值不相等,则为错误。CRC 的计算, 开始对一个 16 位寄存器预装全 1。 然后将报文中的连续的 8 位子节对其进行后续的计算。只有字符中的 8 个数据位参与生成 CRC 的运算,起始位,停止位和校验位不参与 CRC计算。

⑤CRC 的生成过程中, 每个 8–位字符与寄存器中的值异或。然后结果向最低有效位(LSB)方向移动(Shift) 1 位,而最高有效位(MSB)位置充零。 然后提取并检查 LSB:如果 LSB 为 1, 则寄存器中的值与一个固定的预置值异或;如果 LSB 为 0, 则不进行异或操作。
这个过程将重复直到执行完 8 次移位。完成最后一次(第 8 次)移位及相关操作后,下一个 8位字节与寄存器的当前值异或,然后又同上面描述过的一样重复 8 次。当所有报文中子节都运算之后得到的寄存器忠的最终值,就是 CRC。


③小结

MODBUS分为两种传输模式,ASCII方式、RTU方式。这两种模式的区别在于: 1、起始符,与结束符不一样;

●ASCII模式,起始符是一个冒号“:” ASCII码为3AH H是十六进制表示结束符是“回车换行符” ASCII码为0DH 0AH

●RTU 模式,起始符与结束符都是至少3.5倍字符传输时间的停顿间隔时间标定3.5倍字符的传输时间的计算方法,根据“通讯格式、传输方式及MODBUS协议简介”视频中介绍的一个字符的传输时间的计算方法,很容易计算出来。

2、校验和计算不一样;

●ASCII模式,是LRC校验
●RTU 模式,是CRC校验
3、发送格式不一样;
●ASCII模式,在消息中的每个字节都作为两个ASCII字符发送
●RTU 模式,在消息中的每个字节包含两个 4Bit的十六进制字符。


2. ModbusTCP

●ModbusTCP的数据帧可分为两部分:MBAP+PDU。

①结构帧MBAP

MBAP为报文头,长度为7字节,组成如下:

事务紧急处理标识 协议标识 长度 单元标识符
2字节 2字节 2字节 1字节

事务处理标识 : 可以理解为报文的序列号,一般每次通信之后就要加1以区别不同的通信数据报文。
协议标识符 : 00 00表示ModbusTCP协议。
长度 : 表示接下来的数据长度,单位为字节。
单元标识符 : 可以理解为设备地址。

②结构帧PDU

PDU由功能码+数据组成。功能码为1字节,数据长度不定,由具体功能决定。该处使用的url网络请求的数据。

②小结

modbus设备可分为主站(poll)和从站(slave)。主站只有一个,从站有多个,主站向各从站发送请求帧,从站给予响应。在使用TCP通信时,主站为client端,主动建立连接;从站为server端,等待连接。

●主站请求:功能码+数据
●从站正常响应:请求功能码+响应数据
●从站异常响应:异常功能码+异常码,其中异常功能码即将请求功能码的最高有效位置1,异常码指示差错类型
●注意:需要超时管理机制,避免无期限的等待可能不出现的应答

在linux下使用modbusTCP连接
IANA(Internet Assigned Numbers Authority,互联网编号分配管理机构)给Modbus协议赋予TCP端口号为502,这是目前在仪表与自动化行业中唯一分配到的端口号。
通信过程
1.connect 建立TCP连接
2.准备modbus报文
3.使用send命令发送报文
4.在同一连接下等待应答
5.使用recv命令读取报文,完成一次数据交换
6.通信任务结束时,关闭TCP连接


四、基于STM32-MODBUS实现

有点累了,改天再写。。。

如需要技术指导,小编QQ:271841502

如需要进入QQ技术交流群,电赛资料共享群:484040216

电赛资料共享群二维码如下:

STM32--MODBUS 通讯篇_第10张图片

你可能感兴趣的:(STM32,modbus通讯,自然语言处理,经验分享,其他)