①Modbus协议是一种请求/应答的串行链路协议,是一种工业现场总线协议标准。是一项应用层报文传输协议,用于在通过不同类型的总线或网络连接的设备之间的客户机/服务器通信。
②Modbus协议是一项应用层报文传输协议,包括ASCII、RTU、TCP三种报文类型。
③标准的Modbus协议物理层接口有RS232、RS422、RS485和以太网接口,采用master/slave方式通信。
④MODBUS 是一项应用层报文传输协议,用于在通过不同类型的总线或网络连接的设备之间的客户机/服务器通信。
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 |
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 | 字操作 | 多个 |
●功能码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读取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读取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读取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写单个线圈寄存器,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写单个保持寄存器。
●假设从机地址为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写多个线圈寄存器。如果对应的数据位为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写多个保持寄存器,其中每个保持寄存器的长度为两个字节。
●假设从机地址为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 |
●功能码详解主要参考文献为:
https://blog.csdn.net/lakerszhy/article/details/68927178?locationNum=4&fps=1
编码系统:
十六进制,ASCII 字符 0-9, A-F。报文中每个 ASCII 字符含有 1 个十六进制字符
Bits per Byte:
1 起始位
7 数据位, 首先发送最低有效位
1 位作为奇偶校验
1 停止位
奇偶校验 :
●偶校验是要求的, 其它模式 ( 奇校验, 无校验 ) 也可以使用。 为了保证与其它产品的最大兼容性,同时支持无校验模式是建议的。默认校验模式模式 必须为偶校验。
注 : 使用无校验要求 2 个停止位。
字符串行传送:
●每个字符或字节均由此顺序发送(从左到右):
●最低有效位 (LSB) . . . 最高有效位 (MSB),数据传输如图:
●有奇偶检验
●无奇偶检验:
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 传输模式状态如图:
帧检验域:
①帧检验方式为::纵向冗余校验 (LRC - Longitudinal Redundancy Checking)
②LRC 域检验不包括起始“冒号”和结尾 CRLF 对的整个报文的内容。不管报文有无奇偶校验,均执行此检验。
③LRC 域为一个子节,包含一个 8 位二进制值。LRC 值由发送设备计算,然后将 LRC 附在报文后面。接收设备在接收报文时重新计算 LRC 的值,并将计算结果于实际接收到的 LRC 值相比较。如果两个值不相等,则为错误。LRC 的计算, 对报文中的所有的连续 8 位字节相加,忽略任何进位,然后求出其二进制补码。执行检验针对不包括起始“冒号”和结尾 CRLF 对的整个 ASCII 报文域的内容。在 ASCII 模式,LRC 的结果被 ASCII 编码为两个字节并放置于 ASCII 模式报文帧的结尾, CRLF 之前。
RTU模式:报文中每个 8 位字节含有两个 4 位十六进制字符。这种模式的主要优点是较高的数据密度,在相同的波特率下比ASCII 模式有更高的吞吐率。每个报文必须以连续的字符流传送。
编码系统:
8–位二进制报文中每个 8 位字节含有两个 4 位十六进制字符(0–9, A–F)
Bits per Byte:
1 起始位
8 数据位, 首先发送最低有效位
1 位作为奇偶校验
1 停止位
奇偶校验 :
●偶校验是要求的, 其它模式 ( 奇校验, 无校验 ) 也可以使用。 为了保证与其它产品的最大兼容性,同时支持无校验模式是建议的。默认校验模式模式 必须为偶校验。
注 : 使用无校验要求 2 个停止位。
字符串行传送:
●每个字符或字节均由此顺序发送(从左到右):
●最低有效位 (LSB) . . . 最高有效位 (MSB),数据传输如图:
●有奇偶校验:
●无奇偶校验:
Modbus RTU 报文帧:
RTU 报文帧描述如图 :
注意: Modbus RTU 帧最大为 256 字节。
●在 RTU 模式,报文帧由时长至少为 3.5 个字符时间的空闲间隔区分。在后续的部分,这个时间区间被称作 t3.5。如果两个字符之间的空闲间隔大于 1.5 个字符时间,则报文帧被认为不完整应该被接收节点丢弃。传输格式如图:
注 :
RTU 接收驱动程序的实现,由于 t1.5 和 t3.5 的定时,隐含着大量的对中断的管理。在高通信速率下,这导致 CPU 负担加重。因此,在通信速率等于或低于 19200 Bps 时,这两个定时必须严格遵守;对于波特率大于 19200 Bps 的情形,应该使用 2 个定时的固定值:建议的字符间超时时间(t1.5)为 750µs,帧间的超时时间 (t1.5) 为 1.750ms。
●下图表示了对 RTU 传输模式状态图的描述。 “主节点” 和 “子节点” 的不同角度均在相同的图中表示:
上面状态图的一些解释:
● 从 “初始” 态到 “空闲” 态转换需要 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。
●ASCII模式,起始符是一个冒号“:” ASCII码为3AH H是十六进制表示结束符是“回车换行符” ASCII码为0DH 0AH
●RTU 模式,起始符与结束符都是至少3.5倍字符传输时间的停顿间隔时间标定3.5倍字符的传输时间的计算方法,根据“通讯格式、传输方式及MODBUS协议简介”视频中介绍的一个字符的传输时间的计算方法,很容易计算出来。
2、校验和计算不一样;
●ASCII模式,是LRC校验
●RTU 模式,是CRC校验
3、发送格式不一样;
●ASCII模式,在消息中的每个字节都作为两个ASCII字符发送
●RTU 模式,在消息中的每个字节包含两个 4Bit的十六进制字符。
●ModbusTCP的数据帧可分为两部分:MBAP+PDU。
MBAP为报文头,长度为7字节,组成如下:
事务紧急处理标识 | 协议标识 | 长度 | 单元标识符 |
---|---|---|---|
2字节 | 2字节 | 2字节 | 1字节 |
事务处理标识 : 可以理解为报文的序列号,一般每次通信之后就要加1以区别不同的通信数据报文。
协议标识符 : 00 00表示ModbusTCP协议。
长度 : 表示接下来的数据长度,单位为字节。
单元标识符 : 可以理解为设备地址。
PDU由功能码+数据组成。功能码为1字节,数据长度不定,由具体功能决定。该处使用的url网络请求的数据。
●主站请求:功能码+数据
●从站正常响应:请求功能码+响应数据
●从站异常响应:异常功能码+异常码,其中异常功能码即将请求功能码的最高有效位置1,异常码指示差错类型
●注意:需要超时管理机制,避免无期限的等待可能不出现的应答
在linux下使用modbusTCP连接
IANA(Internet Assigned Numbers Authority,互联网编号分配管理机构)给Modbus协议赋予TCP端口号为502,这是目前在仪表与自动化行业中唯一分配到的端口号。
通信过程
1.connect 建立TCP连接
2.准备modbus报文
3.使用send命令发送报文
4.在同一连接下等待应答
5.使用recv命令读取报文,完成一次数据交换
6.通信任务结束时,关闭TCP连接
有点累了,改天再写。。。
如需要技术指导,小编QQ:271841502
如需要进入QQ技术交流群,电赛资料共享群:484040216
电赛资料共享群二维码如下: