?? modbus通信協議.txt
字號:
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 + -