標准的Modbus串行網絡采用兩種錯誤檢測方法。奇偶校驗對每個字符都可用,幀檢測(LRC和CRC)應用於整個消息。它們都是在消息發送前由主設備產生的,從設備在接收過程中檢測每個字符和整個消息幀。
用戶要給主設備配置一預先定義的超時時間間隔,這個時間間隔要足夠長,以使任何從設備都能作為正常反應。如果從設備檢測到一傳輸錯誤,消息將不會接收,也不會向主設備作出回應。這樣超時事件將觸發主設備來處理錯誤。發往不存在的從設備的地址也會產生超時。
1、奇偶校驗
如果指定了奇或偶校驗,“1”的位數將算到每個字符的位數中(ASCII模式7個數據位,RTU中8個數據位)。例如RTU字符幀中包含以下8個數據位:
1 1 0 0 0 1 0 1
整個”1“的數目是4個。如果使用了偶校驗,幀的奇偶校驗位將是0,便得整個”1“的個數仍是4個。如果使用了奇校驗,幀的奇偶校驗位將是1,便得整個”1“的個數是5個。
如果沒有指定奇偶校驗位,傳輸時就沒有校驗位,也不進行校驗檢測。代替一附加的停止位填充至要傳輸的字符幀中。
2、LRC檢測
使用ASCII模式,消息包括了一基於LRC方法的錯誤檢測域。LRC域檢測了消息域中除開冒號及結束的回車換行號外的內容。
LRC域是一個包含一個8位二進制的字節。LRC值由傳輸設備來計算並放到消息幀中,接收設備在接收消息的過程中計算LRC,並將它和接收到消息中LRC域中的值比較,如果兩值不等,說明有錯誤。
LRC方法是將消息中的8Bit的字節連續累加,丟棄了進位。
LRC簡單函數如下:
1 static unsiged char LRC(auchMsg,usDataLen) 2 unsigned char *auchMsg;/*要進行計算的消息*/
3 unsigned short usDataLen;/*LRC要處理的字節的數量*/
4 { 5 unsigned char uchLRC = 0; /*LRC字節初始化*/
6 while (usDataLen--) /*傳送消息*/
7 uchLRC += *auchMsg++; /*累加*/
8 return ((unsigned char)(-(char_uchLRC))); 9 }
LRC算法:
- 參與校驗數據:從地址碼到數據區的所有數據。
- 算法:相鄰2個16進制符相加求和。
- 校驗碼:取其和的低8位的補碼為校驗碼。
例如:
起始碼 | 地址碼 | 功能碼 | 數據區 | 校驗碼 | 停止碼 |
: | 01 | 03 | 21 02 00 02 | LRC | CR/LF |
求和:H01+H03+H21+H02+H00+02 = H29
求:H29的補碼:HD7
LRC校驗碼為:HD7
3、CRC檢測
使用RTU模式,消息包括了一基於CRC方法的錯誤檢測域。CRC域檢測了整個消息的內容。CRC域是兩個字節,包含一16位的二進制值。它由傳輸設備計算后加入到消息中。接收設備重新計算收到消息的CRC,並與接收到的CRC域中的值比較,如果兩值不同,則有誤。
CRC碼的計算方法是,先預置16位寄存器全為1。再逐步把每8位數據信息進行處理。在進行CRC碼計算時只用8位數據位,起始位及停止位,如有奇偶校驗位的話也包括奇偶校驗位,都不參與CRC碼計算。
在計算CRC碼時,8位數據與寄存器的數據相異或,得到的結果向低位移一字節,用0填補最高位。再檢查最低位,如果最低位為1,把寄存器的內容與預置數相異或,如果最低位為0,不進行異或運算。
這個過程一直重復8次。第8次移位后,下一個8位再與現在寄存器的內容相相異或,這個過程與以上一樣重復8次。當所有的數據信息處理完后,最后寄存器的內容即為CRC碼值。CRC碼中的數據發送、接收時低字節在前。
計算CRC碼的步驟為:
- 預置16位寄存器為十六進制FFFF(即全為1)。稱此寄存器為CRC寄存器;
- 把第一個8位數據與16位CRC寄存器的低位相異或,把結果放於CRC寄存器;
- 把寄存器的內容右移一位(朝低位),用0填補最高位,檢查最低位;
- 如果最低位為0:重復第3步(再次移位); 如果最低位為1:CRC寄存器與多項式A001(1010 0000 0000 0001)進行異或;
- 重復步驟3和4,直到右移8次,這樣整個8位數據全部進行了處理;
- 重復步驟2到步驟5,進行下一個8位數據的處理;
- 最后得到的CRC寄存器即為CRC碼。
參考:http://www.360doc.com/content/14/0120/10/7991404_346584755.shtml