modbus-crc16——c語言


為確保消息數據的完整性,除了驗證消息CRC之外,建議實現檢查串行端口(UART)成幀錯誤的代碼。如果接收消息中的CRC與接收設備計算的CRC不匹配,則應忽略該消息。下面的C語言代碼片段顯示了如何使用逐位移位和異或運算來計算Modbus消息CRC。使用消息幀中的每個字節計算CRC,除了包含CRC本身的最后兩個字節。

參考:https://www.cnblogs.com/skullboyer/p/8342167.html

一、CRC16校驗碼的使用

  現選擇最常用的CRC-16校驗,說明它的使用方法。

  根據Modbus協議,常規485通訊的信息發送形式如下:

  地址 功能碼 數據信息 校驗碼

  1byte 1byte nbyte 2byte

  CRC校驗是前面幾段數據內容的校驗值,為一個16位數據,發送時,低8位在前,高8為最后。

  例如:信息字段代碼為: 1011001,校驗字段為:1010。

  發送方:發出的傳輸字段為: 1 0 1 1 0 0 1 1 0 10

  信息字段 校驗字段

  接收方:使用相同的計算方法計算出信息字段的校驗碼,對比接收到的實際校驗碼,如果相等及信息正確,不相等則信息錯誤;或者將接受到的所有信息除多項式,如果能夠除盡,則信息正確。

 

三、CRC16常見幾個標准的算法

 

  CRC16常見的標准有以下幾種,被用在各個規范中,其算法原理基本一致,就是在數據的輸入和輸出有所差異,下邊把這些標准的差異列出,並給出C語言的算法實現。

 

  CRC16_CCITT:多項式x16+x12+x5+1(0x1021),初始值0x0000,低位在前,高位在后,結果與0x0000異或

 

  CRC16_CCITT_FALSE:多項式x16+x12+x5+1(0x1021),初始值0xFFFF,低位在后,高位在前,結果與0x0000異或

 

  CRC16_XMODEM:多項式x16+x12+x5+1(0x1021),初始值0x0000,低位在后,高位在前,結果與0x0000異或

 

  CRC16_X25:多項式x16+x12+x5+1(0x1021),初始值0x0000,低位在前,高位在后,結果與0xFFFF異或

 

  CRC16_MODBUS:多項式x16+x15+x5+1(0x8005),初始值0xFFFF,低位在前,高位在后,結果與0x0000異或

 

  CRC16_IBM:多項式x16+x15+x5+1(0x8005),初始值0x0000,低位在前,高位在后,結果與0x0000異或

 

  CRC16_MAXIM:多項式x16+x15+x5+1(0x8005),初始值0x0000,低位在前,高位在后,結果與0xFFFF異或

 

  CRC16_USB:多項式x16+x15+x5+1(0x8005),初始值0xFFFF,低位在前,高位在后,結果與0xFFFF異或

 

crc16幾種標准校驗算法及c語言代碼

 

四、CRC16的算法原理及程序

 

  1.根據CRC16的標准選擇初值CRCIn的值。

 

  2.將數據的第一個字節與CRCIn高8位異或。

 

  3.判斷最高位,若該位為 0 左移一位,若為 1 左移一位再與多項式Hex碼異或。

 

  4.重復3直至8位全部移位計算結束。

 

  5.重復將所有輸入數據操作完成以上步驟,所得16位數即16位CRC校驗碼。

 

  根據算法原理與標准要求就能簡單的寫出具體程序:

 

二、CRC16校驗碼計算方法

  常用查表法和計算法。計算方法一般都是:

  (1)、預置1個16位的寄存器值0xFFFF,稱此寄存器為CRC寄存器;

  (2)、把第一個8位二進制數據(既通訊信息幀的第一個字節)與16位的CRC寄存器的低

  8位相異或,把結果放於CRC寄存器,高八位數據不變;

  (3)、把CRC寄存器的內容右移一位(朝高位)用0填補最高位,並檢查右移后的移出位;

  (4)、如果移出位為0:重復第3步(再次右移一位);如果移出位為1,CRC寄存器與一多

  項式(A001)進行異或;

  (5)、重復步驟3和4,直到右移8次,這樣整個8位數據全部進行了處理;

  (6)、重復步驟2到步驟5,進行通訊信息幀下一個字節的處理;

  (7)、將該通訊信息幀所有字節按上述步驟計算完成后,得到的16位CRC寄存器的高、低

  字節進行交換;

  (8)、最后得到的CRC寄存器內容即為:CRC碼。

  以上計算步驟中的多項式A001是8005按位顛倒后的結果。

 

unsigned int CRC16_2(unsigned char *buf, int len)
{
    unsigned int crc = 0xFFFF;
    for (int pos = 0; pos < len; pos++)
    {
        crc ^= (unsigned int)buf[pos]; // XOR byte into least sig. byte of crc
        for (int i = 8; i != 0; i--)   // Loop over each bit
        {
            if ((crc & 0x0001) != 0)   // If the LSB is set
            {
                crc >>= 1; // Shift right and XOR 0xA001
                crc ^= 0xA001;
            }
            else // Else LSB is not set
            {
                crc >>= 1;    // Just shift right
            }
        }
    }

    //高低字節轉換
    crc = ((crc & 0x00ff) << 8) | ((crc & 0xff00) >> 8);
    return crc;
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

 

  

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM