PI-MBUS-300 Modbus Protocol
95
08 诊断
Modbus+网络统计
字 位 含义
35 LO 位图中由接收缓冲器,缓冲器1...8
HI 位图中由接收缓冲器,缓冲器9...16
36 LO 位图中由接收缓冲器,缓冲器17...24
HI 位图中由接收缓冲器,缓冲器25...32
37 LO 位图中由接收缓冲器,缓冲器33...40
HI 站管理命令开始计数器
38 LO 主机数据输出通道1 命令开始计数器、
HI 主机数据输出通道2 命令开始计数器
39 LO 主机数据输出通道3 命令开始计数器
HI 主机数据输出通道4 命令开始计数器
40 LO 主机数据输出通道5 命令开始计数器
HI 主机数据输出通道6 命令开始计数器
41 LO 主机数据输出通道7 命令开始计数器
HI 主机数据输出通道8 命令开始计数器
42 LO 从机数据输入通道41 命令处理计数器
HI 从机数据输入通道42 命令处理计数器
43 LO 从机数据输入通道43 命令处理计数器
HI 从机数据输入通道44 命令处理计数器
Modbus Protocol PI-MBUS-300
96
44 LO 从机数据输入通道45 命令处理计数器
HI 从机数据输入通道46 命令处理计数器
45 LO 从机数据输入通道47 命令处理计数器
HI 从机数据输入通道48 命令处理计数器
46 LO 主机数据输出通道81 命令开始计数器
HI 主机数据输出通道82 命令开始计数器
47 LO 主机数据输出通道83 命令开始计数器
HI 主机数据输出通道84 命令开始计数器
48 LO 主机程序命令开始计数器
HI 主机程序输出通道86 命令开始计数器
49 LO 主机程序输出通道87 命令开始计数器
HI 主机程序输出通道88 命令开始计数器
50 LO 从机程序输入通道C1 命令处理计数器
HI 从机程序输入通道C2 命令处理计数器
51 LO 从机程序输入通道C3 命令处理计数器
HI 从机程序输入通道C4 命令处理计数器
52 LO 从机程序输入通道C5 命令处理计数器
HI 从机程序输入通道C6 命令处理计数器
53 LO 从机程序输入通道C7 命令处理计数器
HI 从机程序输入通道C8 命令处理计数器
PI-MBUS-300 Modbus Protocol
97
附录A
不正常响应
¨ 不正常响应
¨ 不正常代码
Modbus Protocol PI-MBUS-300
98
不正常响应
除广播外,主机向从机设备发送查询并希望有一个正常响应,
主机查询中有可能产生4 种事件:
¨ 从机接收查询,通讯错误正常处理信息,则返回一个正常响
应事件。
¨ 由于通讯出错,从机不能接收查询数据,因而不返回响应。
此时,主机依靠处理程序给出查询超时事件。
¨ 若从机接收查询,发现有 (LRC 或CRC) 通讯错误,并返回响
应,此时,依靠主机处理程序给出查询超时事件。
¨ 从机接收查询,无通讯错误,但无法处理(如读不存在的线圈
和寄存器)时,向主机报告错误的性质。
不正常响应信息有2 个与正常响应不相同的区域:
功能代码区:正常响应时,从机的响应功能代码区,带原查
询的功能代码。所有功能代码的MSB 为0(其值低于80H)。不正常
响应时,从机把功能代码的MSB 置为1,使功能代码值大于80H,
高于正常响应的值。这样,主机应用程序能识别不正常响应事件,
能检查不正常代码的数据区。
数据区:正常响应中,数据区含有(按查询要求给出的) 数据
或统计值,在不正常响应中,数据区为一个不正常代码,它说明
从机产生不正常响应的条件和原因。
PI-MBUS-300 Modbus Protocol
99
例:主机发出查询,从机不正常响应。(为十六进制数据)。
QUERY
Byte Contents
1 Slave Address
2 Function
3 Starting Address Hi
4 Starting Address Lo
5 No. of Coils Hi
6 No. of Coils Lo
7 LRC
EXCEPTION RESPONSE
Byte Contents
1 Slave Address
2 Function
3 Exception Code
4 LRC
Example
0A
01
04
A1
00
01
4F
Example
0A
81
02
73
图46:主机发出查询,从机不正常响应
上例中,从机设备地址10(0AH),读线圈状态的功能代码(01),
主机请求线圈状态的地址为1245(04A1H)。注意:只读一个指定线
圈,地址为(0001).
若从机中不存在此线圈地址时,即以不正常代码(02),向主
机返回一个不正常响应。说明为不合法地址。
Modbus Protocol PI-MBUS-300
100
不正常代码
代码 名称 含义
01 不合法功能代码 从机接收的是一种不能执行功能代码。
发出查询命令后,该代码指示无程序功
能。
02 不合法数据地址 接收的数据地址,是从机不允许的地
址。
03 不合法数据 查询数据区的值是从机不允许的值。
04 从机设备故障 从机执行主机请求的动作时出现不可
恢复的错误。
05 确认 从机已接收请求处理数据,但需要较长
的处理时间,为避免主机出现超时错误
而发送该确认响应。主机以此再发送一
个“查询程序完成”未决定从机是否已
完成处理。
06 从机设备忙碌 从机正忙于处理一个长时程序命令,请
求主机在从机空闲时发送信息。
07 否定 从机不能执行查询要求的程序功能时,
该代码使用十进制13 或14 代码,向主
机返回一个“不成功的编程请求”信息。
主机应请求诊断从机的错误信息。
08 内存奇偶校验错误 从机读扩展内存中的数据时,发现有奇
偶校验错误,主机按从机的要求重新发
送数据请求。
PI-MBUS-300 Modbus Protocol
101
Modbus Protocol PI-MBUS-300
102
附录B
应用须知
¨ 本附录向您提供有关应用的资料和建议。
¨ ModiconPLC 的最大查询/响应参数。
¨ 估算串行传送时序
¨ 584 和984A/B/X PLC 的应用须知
PI-MBUS-300 Modbus Protocol
103
最大查询/响应参数
584
功能 说明 查询 响应
1 读线圈状态 2000 线圈 2000 线圈
2 读输入状态 2000 输入 2000 输入
3 读线圈状态 125 寄存器 125 寄存器
4 读输入状态 125 寄存器 125 寄存器
5 强置单线圈 1 线圈 1 线圈
6 预置单寄存器 1 寄存器 1 寄存器
7 读不正常状态 N/A 8 线圈
8 诊断 N/A N/A
9 程序484 不支持 不支持
10 查询484 不支持 不支持
11 获取通讯事件控制 N/A N/A
12 获取通讯事件记录 N/A 70 数据字节
13 编程控制器 33 数据字节 33 数据字节
14 查询控制器 N/A 33 数据字节
15 强置多线圈 800 线圈 800 线圈
16 预置多寄存器 100 寄存器 100 寄存器
17 报告从机 N/A N/A
18 编程884/M84 不支持 不支持
19 复位通讯连接Limk 不支持 不支持
20 读通用类型寄存器 (1) (1)
21 写通用类型寄存器 (1) (1)
Modbus Protocol PI-MBUS-300
104
最大查询/响应参数
984
功能 说明 查询 响应
1 读线圈状态 2000 线圈 2000 线圈
2 读输入状态 2000 输入 2000 输入
3 读线圈状态 125 寄存器 125 寄存器
4 读输入状态 125 寄存器 125 寄存器
5 强置单线圈 1 线圈 1 线圈
6 预置单寄存器 1 寄存器 1 寄存器
7 读不正常状态 N/A 8 线圈
8 诊断 N/A N/A
9 程序484 不支持 不支持
10 查询484 不支持 不支持
11 获取通讯事件控制 N/A N/A
12 获取通讯事件记录 N/A 70 数据字节
13 编程控制器 33 数据字节 33 数据字节
14 查询控制器 N/A 33 数据字节
15 强置多线圈 800 线圈 800 线圈
16 预置多寄存器 100 寄存器 100 寄存器
17 报告从机 N/A N/A
18 编程884/M84 不支持 不支持
19 复位通讯连接Limk 不支持 不支持
20 读通用类型寄存器 (1) (1)
21 写通用类型寄存器 (1) (1)
PI-MBUS-300 Modbus Protocol
105
估算串行处理时序
处理顺序
Modbus 串行传输时按如下顺序:括号中的字符。
1.Modbus 主机组织信息。
2.检查主机设备Modbus RTS 和CTS 的状态。(A)
3.向从机发送查询信息。(B)
4.从机处理查询数据。(C) (D)
5.从机计算一个错误校验区。(E)
6.检查从机设备RTS 和CTS,modem 的状态。(A)
7.向主机返回响应信息。(B)
8.主机按从机响应的数据处理。
Timing Notes
(A) 若RTS 和CTS 跳接在一起,可忽略该时间。
对J478 modem,该时间约5ms。
(B) 使用下述公式,估算传时间:
(C) 在PLC 扫描结束时,处理Modbus 信息,最坏情况延时是一个
扫描时间,若控制器刚开始一个新扫描时间。
控制器扫描结束时,Modbus 端口的分配时间取决控制器的型
号。
Modbus Protocol PI-MBUS-300
106
(D) Contiued:
584 和984 型控制器,每个Modbus 端口的工作时间约为1.5ms,
从端口1 开始,顺序进行。
有些低档控制器(184/384)该时间按处理的数量的大小而变
化。从0.5ms 至6.0ms(100 寄存器)或至7.0ms(800 个线圈)。
(E) Modbus 功能代码1-4,1.5 和16,可在从机工作的Modbus 端
口的分配时间内允许主机请求从机处理更多的数据:若从机
一时无法处理的话,可放入缓冲区。
Modbus 端口在一次服务期中能处理的数据量如下:
点数 寄存器
Micro84 16 4
184/384 800 100
484 32 16
584 64 32
984A/B/X 64 32
984-X8X 1000 125
注意:‘ 984-X8X ’ 指的是984 单独使用型
(984-835,-685,etc)。
(F) LRC 计算时间<1ms,CRC 计算时间约0.3ms(响应而返回的8
位
数据)
PI-MBUS-300 Modbus Protocol
107
584 和984A/B/X PLC 应用须知
本应用须知只适用Modicon 584 和984/A/B/X 控制器。
¨ 波特率:用Modbus 端口1 和端口2 时,最大允许的波特率为
19200。
¨ 端口封锁:使用ASCII,要送“零数据长度”的信息,或无设
备地址的信息,如下为一个不合法信息。
: CR LF (colon,CR,LF)
出现这类信息时,会随机封死端口。
¨ ASCII 信息终止:ASCII 信息一般用,CRLF 终止。584 和
984A/B/X 型控制器的一个信息,可在LRC 区后终止,而不需
发送CRLF 字符,如LRC 区后出现>IS 时间间隔则控制器认为
信息是正常终止。
Modbus Protocol PI-MBUS-300
108
附录C
LRC/CRC 生成
¨ LRC 校验
¨ CRC 校验
PI-MBUS-300 Modbus Protocol
109
LRC 纵向冗余校验
纵向冗余校验区为1 个字节,8 位二进制数据,由发送设备计
算LRC 值,并把计算值附到信息中。接收设备在接收信息时,重
新计算LRC 值,并把计算值与LRC 区中接收的实际值进行比较,
若两者不相同,则产生一个错误。
信息中的相邻2 个8 位字节相加,丢弃进位,然后进行二进
制补码,运算计算出LRC 值。LRC 是一个8 位数据区,因此每加一
个新字符,会产生大于十进制255 的数值而谥出,因为没有第9
位,自动放弃进位。
产生LRC 的过程:
1. 相加信息中的全部字节,包括起始“:”号和结束符CRLF.
并把结果送入8 位数据区,放弃进位。
2. 由FFH 减去最终的数据值,产生的补码。
3. 加“1”产生二进制补码。
把LRC 放入信息中
发送8 位LRC(2 个ASCII 字符)时,先送高位字符,后送低位
字符,如:LRC 值为61H(0110 0001):
Colon Addr Func Data
Count
Data Data Data Data LRC
Hi
LRC
Lo
CR
6 1
图47LRC 字符顺序
Modbus Protocol PI-MBUS-300
110
例:
用一个C语言功能码产生LRC值。
该功能码用2个自变量:
unsigned char *auchMsg ; 为生成LRC值,把指针指向含有二进
制数据的缓冲器
unsigned short usDataLen ; 缓冲器中的字节数。
该功能返回LRC作为一种类型“unsigned char”。
LRC产生的功能
static unsigned char LRC(auchMsg, usDataLen)
unsigned char *auchMsg ; /*按信息的字节计算LRC*/
unsigned short usDataLen ; /*按信息的字节计算LRC*/
{
unsigned char uchLRC = 0 ; /*初始化LRC字符 */
while (usDataLen––) /*通过数据缓冲器*/
uchLRC += *auchMsg++ ; /*加缓冲器字节无进位*/
return ((unsigned char)(–((char)uchLRC))) ; /*返回二进制补码*/
}
PI-MBUS-300 Modbus Protocol
111
CRC 循环冗余校验
循环冗余校验CRC区为2字节,含一个16位二进制数据。由发
送设备计算CRC值,并把计算值附在信息中,接收设备在接收信息
时,重新计算CRC值,并把计算值与接收的在CRC区中实际值进行
比较,若两者不相同,则产生一个错误。
CRC开始时先把寄存器的16位全部置成“1”,然后把相邻2个8
位字节的数据放入当前寄存器中,只有每个字符的8位数据用作产
生CRC,起始位,停止位和奇偶校验位不加到CRC中。
产生CRC期间,每8位数据与寄存器中值进行异或运算,其结
果向右移一位(向LSB方向),并用“0”填入MSB,检测LSB,若LSB
为“1”则与预置的固定值异或,若LSB为“0”则不作异或运算。
重复上述处过程,直至移位8次,完成第8次移位后,下一个8
位数据,与该寄存器的当前值异或,在所有信息处理完后,寄存
器中的最终值为CRC值。
产生CRC的过程:
1. 把16位CRC寄存器置成FFFFH.
2. 第一个8位数据与CRC寄存器低8位进行异或运算,把结果
放入CRC寄存器。
3. CRC寄存器向右移一位,MSB填零,检查LSB.
4. (若LSB为0):重复3,再右移一位。
(若LSB为1):CRC寄存器与Aool H 进行异或运算
5. 重复3和4直至完成8次移位,完成8位字节的处理。
6. 重复2至5步,处理下一个8位数据,直至全部字节处理完
毕。
Modbus Protocol PI-MBUS-300
112
7. CRC寄存器的最终值为CRC值。
8. 把CRC值放入信息时,高8位和低8位应分开放置。
把CRC值放入信息中
发送信息中的16 位CRC值时,先送低8位,后送高8位。
若CRC值为1241(0001 0010 0100 0001):
Addr Func Data
Count
Data Data Data Data CR
CLo
CR
CHi
41 12
图48:CRC字节顺序
例:
各种可能的CRC值,按两列装入,一列在16 位CRC的高8位区,
为(0-256的)CRC值,另一类为低8位区,为CRC的低位值。
用这种方法得到的CRC其执行速度快于计算缓冲器中每个新
字符得到一个新CRC值的方法。
. 注意:该功能内部交换CRC中的高/低字节,返回的CRC值
中,其字节已交换。
因此,由功能码返回的CRC值,能直接放在信息中传送。
PI-MBUS-300 Modbus Protocol
113
CRC生成
例:
功能取2个自变量:
unsigned char *puchMsg ; 为生成CRC值,把指针指向含有二进
制
的数据的缓冲器
unsigned short usDataLen ; 缓冲器中的字节数。
该功能返回CRC作为一种类型“unsigned short”。
CRC产生的功能
unsigned short CRC16(puchMsg, usDataLen)
unsigned char *puchMsg ; /*按信息的字节数计算CRC */
unsigned short usDataLen ; /* quantity of bytes in message */
{
unsigned char uchCRCHi = 0xFF ; /* 初始化高字节*/
unsigned char uchCRCLo = 0xFF ; /* 初始化低字节*/
unsigned uIndex ; /*把CRC表*/
while (usDataLen––) /*通过数据缓冲器*/
{
uIndex = uchCRCHi ^ *puchMsgg++ ; /*计算CRC */
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
uchCRCLo = auchCRCLo[uIndex] ;
}
return (uchCRCHi << 8 | uchCRCLo) ;
}
Modbus Protocol PI-MBUS-300
114
高位字节表
/* Table of CRC values for high–order byte */
static unsigned char auchCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40
} ;
低位字节表
/* Table of CRC values for low–order byte */
static char auchCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
0x40
} ;
PI-MBUS-300 Modbus Protocol
115