⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 modbus通信协议.txt

📁 Modbus通信协议
💻 TXT
📖 第 1 页 / 共 2 页
字号:
2003-9-3 


Modbus 通信协议页码,6/10 
如果没有指定奇偶校验位,传输时就没有校验位,也不进行校验检测。代替一附加的停止位填充
至要传输的字符帧中。
2、LRC 检测
使用ASCII 模式, 消息包括了一基于LRC 方法的错误检测域。LRC 域检测了消息域中除开始的冒号及
结束的回车换行号外的内容。
LRC 域是一个包含一个8位二进制值的字节。LRC 值由传输设备来计算并放到消息帧中,接收设备在
接收消息的过程中计算LRC,并将它和接收到消息中LRC 域中的值比较,如果两值不等,说明有错
误。
LRC 方法是将消息中的8Bit 的字节连续累加,丢弃了进位。
LRC 简单函数如下: 
static unsigned char LRC(auchMsg,usDataLen) 
unsigned char *auchMsg ; /* 要进行计算的消息 */ 
unsigned short usDataLen ; /* LRC 要处理的字节的数量*/ 
{ unsigned char uchLRC = 0 ; /* LRC 字节初始化 */ 
while (usDataLen--) /* 传送消息 */ 
uchLRC += *auchMsg++ ; /* 累加*/ 
return ((unsigned char)(-((char_uchLRC))) ; 
} 
3、CRC 检测
使用RTU 模式, 消息包括了一基于CRC 方法的错误检测域。CRC 域检测了整个消息的内容。
CRC 域是两个字节,包含一16位的二进制值。它由传输设备计算后加入到消息中。接收设备重新计
算收到消息的CRC,并与接收到的CRC 域中的值比较,如果两值不同,则有误。
CRC 是先调入一值是全“1”的16位寄存器,然后调用一过程将消息中连续的8位字节各当前寄存器
中的值进行处理。仅每个字符中的8Bit 数据对CRC 有效,起始位和停止位以及奇偶校验位均无
效。
CRC 产生过程中,每个8位字符都单独和寄存器内容相或(OR) ,结果向最低有效位方向移动,最
高有效位以0填充。LSB 被提取出来检测,如果LSB 为1,寄存器单独和预置的值或一下,如果LSB 为
0,则不进行。整个过程要重复8次。在最后一位(第8位)完成后,下一个8位字节又单独和寄存
器的当前值相或。最终寄存器中的值, 是消息中所有的字节都执行之后的CRC 值。
CRC 添加到消息中时,低字节先加入,然后高字节。
CRC 简单函数如下: 
unsigned short CRC16(puchMsg, usDataLen) 
unsigned char *puchMsg ; /* 要进行CRC 校验的消息 */ 
unsigned short usDataLen ; /* 消息中字节数 */ 
{ 
unsigned char uchCRCHi = 0xFF ; /* 高CRC 字节初始化 */ 
file://F:\CONTROL\Modbus 通信协议.htm 2003-9-3 


Modbus 通信协议

unsigned char uchCRCLo = 0xFF ; /* 低CRC 字节初始化 */ 
unsigned uIndex ; /* CRC 循环中的索引 */ 
while (usDataLen--) /* 传输消息缓冲区 */ 
{ 
uIndex = uchCRCHi ^ *puchMsgg++ ; /* 计算CRC */ 
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex} ; 
uchCRCLo = auchCRCLo[uIndex] ; 
} 
return (uchCRCHi << 8 | uchCRCLo) ; 
} 


/* CRC 高位字节值表 */ 
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 
} ; 
/* CRC 低位字节值表*/ 
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, 


页码,7/10 

file://F:\CONTROL\Modbus 通信协议.htm 

2003-9-3 


Modbus 通信协议页码,8/10 

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 
} ;
ModBus 网络是一个工业通信系统,由带智能终端的可编程序控制器和计算机通过公用线路或局部


专用线路连接而成。其系统结构既包括硬件、亦包括软件。它可应用于各种数据采集和过程监

控。下表1是ModBus 的功能码定义。
表1 ModBus 功能码

01 READ COIL STATUS 
02 READ INPUT STATUS 
03 READ HOLDING REGISTER 
04 READ INPUT REGISTER 
05 WRITE SINGLE COIL 
06 WRITE SINGLE REGISTER 
15 WRITE MULTIPLE COIL 
16 WRITE MULTIPLE REGISTER 


ModBus 网络只是一个主机,所有通信都由他发出。网络可支持247 个之多的远程从属控制器,但实

际所支持的从机数要由所用通信设备决定。采用这个系统,各PC可以和中心主机交换信息而不影

响各PC执行本身的控制任务。表2是ModBus 各功能码对应的数据类型。
表2 Modbus 功能与数据类型对应表

file://F:\CONTROL\Modbus 通信协议.htm 

2003-9-3 


Modbus 通信协议页码,9/10 


(1)ModBus 的传输方式

在ModBus 系统中有2种传输模式可选择。这2种传输模式与从机PC通信的能力是同等的。选择时应
视所用ModBus 主机而定,每个ModBus 系统只能使用一种模式,不允许2种模式混用。一种模式是
ASCII(美国信息交换码),另一种模式是RTU(远程终端设备)这两种模式的定义见表3 

表3 ASCII 和RTU 传输模式的特性


ASCII 可打印字符便于故障检测,而且对于用高级语言(如Fortan)编程的主计算机及主PC很适
宜。RTU 则适用于机器语言编程的计算机和PC主机。

用RTU 模式传输的数据是8位二进制字符。如欲转换为ASCII 模式,则每个RTU 字符首先应分为高位
和低位两部分,这两部分各含4位,然后转换成十六进制等量值。用以构成报文的ASCII 字符都是
十六进制字符。ASCII 模式使用的字符虽是RTU 模式的两倍,但ASCII 数据的译玛和处理更为容易一
些,此外,用RTU 模式时报文字符必须以连续数据流的形式传送,用ASCII 模式,字符之间可产生
长达1s的间隔,以适应速度较快的机器。

(2)ModBus 的数据校验方式

CRC-16(循环冗余错误校验) 

CRC-16 错误校验程序如下:报文(此处只涉及数据位,不指起始位、停止位和任选的奇偶校验
位)被看作是一个连续的二进制,其最高有效位(MSB)首选发送。报文先与X↑16相乘(左移16 
位),然后看X↑16+X↑15+X↑2+1 除,X↑16+X↑15+X↑2+1 可以表示为二进制数
11000000000000101 。整数商位忽略不记,16位余数加入该报文(MSB 先发送),成为2个CRC 校验
字节。余数中的1全部初始化,以免所有的零成为一条报文被接收。经上述处理而含有CRC 字节的

file://F:\CONTROL\Modbus 通信协议.htm 

2003-9-3 


Modbus 通信协议页码,10/10 

报文,若无错误,到接收设备后再被同一多项式(X↑16+X↑15+X↑2+1)除,会得到一个零余数
(接收设备核验这个CRC 字节,并将其与被传送的CRC 比较)。全部运算以2为模(无进位)。

习惯于成串发送数据的设备会首选送出字符的最右位(LSB-最低有效位)。而在生成CRC 情况下, 
发送首位应是被除数的最高有效位MSB 。由于在运算中不用进位,为便于操作起见,计算CRC 时设
MSB 在最右位。生成多项式的位序也必须反过来,以保持一致。多项式的MSB 略去不记,因其只对
商有影响而不影响余数。

生成CRC-16 校验字节的步骤如下: 

①装如一个16位寄存器,所有数位均为1。
②该16位寄存器的高位字节与开始8位字节进行“异或”运算。运算结果放入这个16位寄存器。
③把这个16寄存器向右移一位。
④若向右(标记位)移出的数位是1,则生成多项式1010000000000001 和这个寄存器进行“异或” 
运算;若向右移出的数位是0,则返回③。
⑤重复③和④,直至移出8位。
⑥另外8位与该十六位寄存器进行“异或”运算。
⑦重复③~⑥,直至该报文所有字节均与16位寄存器进行“异或”运算,并移位8次。
⑧这个16位寄存器的内容即2字节CRC 错误校验,被加到报文的最高有效位。
另外,在某些非ModBus 通信协议中也经常使用CRC16 作为校验手段,而且产生了一些CRC16 的变
种,他们是使用CRC16 多项式X↑16+X↑15+X↑2+1 ,单首次装入的16位寄存器为0000;使用CRC16 
的反序X↑16+X↑14+X↑1+1,首次装入寄存器值为0000 或FFFFH 。

LRC(纵向冗余错误校验) 

LRC 错误校验用于ASCII 模式。这个错误校验是一个8位二进制数,可作为2个ASCII 十六进制字节传
送。把十六进制字符转换成二进制,加上无循环进位的二进制字符和二进制补码结果生成LRC 错误
校验(参见图)。这个LRC 在接收设备进行核验,并与被传送的LRC 进行比较,冒号(:)、回车
符号(CR)、换行字符(LF)和置入的其他任何非ASCII 十六进制字符在运算时忽略不计。

版权所有(C) 1999 [珠海市水业科技有限公司]。保留所有权利。
修订日期:2003 年05月26日。

file://F:\CONTROL\Modbus 通信协议.htm 

2003-9-3 



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -