python生成crc校驗生成modbus16位校驗碼


CRC16 Modbus計算原理

  1. 預置 1 個 16 位的寄存器為十六進制FFFF(即全為 1) , 稱此寄存器為 CRC寄存器。

  2. 把第一個 8 位二進制數據 (通信信息幀的第一個字節) 與 16 位的 CRC寄存器的低 8 位相異或, 把結果放於 CRC寄存器。

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

  4. 如果移出位為 0, 重復第 3 步 ( 再次右移一位); 如果移出位為 1, CRC 寄存器與多項式A001 ( 1010 0000 0000 0001) 進行異或。

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

  6. 重復步驟 2 到步驟 5, 進行通信信息幀下一個字節的處理。

  7. 將該通信信息幀所有字節按上述步驟計算完成后,得到的16位CRC寄存器的高、低字節進行交換。

  8. 最后得到的 CRC寄存器內容即為 CRC碼。

python代碼實現

def one_byte_crc(data, crc_data):
    """
    處理一個字節的crc校驗環節
    :param data:待處理的數據
    :param crc_data:crc寄存器值,最初始的為0xffff
    :return:
    """
    # 把第一個8位二進制數據(通信信息幀的第一個字節)與16位的CRC寄存器的低8位相異或,把結果放於CRC寄存器。
    crc_data_tmp1 = (get_crc_low(crc_data) ^ data) + (0xff00 & crc_data)
    length = 8
    while True:
        # 把CRC寄存器的內容右移一位(朝低位)用0填補最高位,並檢查右移后的移出位。
        # 如果移出位為0,重復第3步(再次右移一位);如果移出位為1,CRC寄存器與多項式A001(1010000000000001)進行異或。
        if is_right_zero(crc_data_tmp1):
            crc_data_tmp2 = (crc_data_tmp1 >> 1)
            crc_data_tmp1 = crc_data_tmp2
            length -= 1
        else:
            crc_data_tmp2 = ((crc_data_tmp1 >> 1) ^ 0xA001)
            crc_data_tmp1 = crc_data_tmp2
            length -= 1
            pass
        if length == 0:
            break
    crc_data = crc_data_tmp1
    # 返回對一個8位數據的crc校驗
    return crc_data


def get_crc_low(crc_data):
    """
    16位數據 獲取低位數據
    :param crc_data:crc寄存器值
    :return:獲取16位數據的低位數據
    """
    return crc_data & 0x00ff


def is_right_zero(check_data):
    """
    測試最右方(最低位)是否為 0
    :param check_data: 待測試的數據
    :return: 0 -> True 1 -> False
    """
    if (check_data & 0x0001) == 0:
        return True
    else:
        return False


def do_crc(data_array, crc_data):
    """
    生成一個由 一個字節的16進制數 組成的列表的crc校驗結果
    ! 不是crc校驗碼
    :param data_array: 一個字節的16進制數 組成的列表
    :param crc_data: 初始的crc寄存器值,為modbus初始為: 0xffff
    :return: crc校驗結果
    """
    for data in data_array:
        crc_data = one_byte_crc(data, crc_data)
        pass
    return crc_data


def get_crc_verify_code(crc_data):
    """
    生成crc校驗碼
    :param crc_data: 16進制數據 列表的 crc校驗結果
    :return: crc校驗碼
    """
    return ((crc_data & 0x00ff) << 8) | ((crc_data & 0xff00) >> 8)


crc = 0xffff
datalist = [0x12, 0x34, 0x56, 0x78]
print('進行循環冗余校驗結果: 0x{:x}'.format(do_crc(datalist, crc)))
print('生成Modbus 循環冗余校驗碼: 0x{:x}'.format(get_crc_verify_code(do_crc(datalist, crc))))


免責聲明!

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



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