Python实践——CAN数据CRC校验计算

一、代码功能概述

这段 Python 代码实现了多种不同 CRC(循环冗余校验)算法的计算功能。用户可以选择特定的 CRC 算法,然后输入数据,函数将返回该数据的 CRC 校验结果。可以选择以字节数组的形式(高位在前)或单个值的列表形式输出结果。

二、准备工作

  1. 确保你已经安装了 Python 环境。
  2. 理解 CRC 校验的基本概念和不同算法的参数含义,例如多项式、宽度、初始值、结果异或值以及输入输出反转标志等。
  3. 常见的CRC参考模型:参考网页资料:http://www.ip33.com/crc.html

三、代码结构解析

  1. 定义 CRC 参数字典

    crc_parameters = {
        "CRC-4TU": {
            "polynomial": 0x03,
            "width": 4,
            "initial_value": 0x00,
            "result_xor_value": 0x00,
            "input_reversed": True,
            "output_reversed": True
        },
        # 其他算法的参数...
    }
    

    这里使用字典存储了各种 CRC 算法的参数,每个算法对应一个字典条目,包含了该算法所需的多项式、宽度、初始值、结果异或值以及输入输出反转标志等信息。

  2. CRC 计算函数

    def crc_calculator(data, algorithm, by_byte=True):
        if algorithm not in crc_parameters:
            raise ValueError(f"Unknown algorithm: {algorithm}")
    
        params = crc_parameters[algorithm]
        polynomial = params["polynomial"]
        width = params["width"]
        initial_value = params["initial_value"]
        result_xor_value = params["result_xor_value"]
        input_reversed = params["input_reversed"]
        output_reversed = params["output_reversed"]
    
        crc = initial_value
        for byte in data:
            if input_reversed:
                byte = int('{:08b}'.format(byte)[::-1], 2)
            for _ in range(8):
                bit = (byte >> 7) & 1
                byte <<= 1
                crc <<= 1
                if (crc >> width) & 1 ^ bit:
                    crc ^= polynomial
            crc &= (1 << width) - 1
    
        if output_reversed:
            crc = int('{:0{width}b}'.format(crc, width=width)[::-1], 2)
    
        crc = crc ^ result_xor_value
    
        if by_byte:
            if crc == 0:
                return [0]
            crc_array = []
            while crc > 0:
                crc, remainder = divmod(crc, 256)
                crc_array.insert(0, remainder)
            return crc_array
        else:
            return [crc]
    
    • 首先,检查传入的算法名称是否在已知的参数字典中,如果不在,则抛出一个 ValueError 异常。
    • 然后,从参数字典中获取指定算法的参数,并初始化 CRC 值为初始值。
    • 对于输入数据中的每个字节,根据输入反转标志进行处理,如果需要反转,则先对字节进行反转。接着,在一个内层循环中,逐位处理字节,并根据 CRC 算法的规则更新 CRC 值。
    • 更新完所有字节后,根据输出反转标志对 CRC 值进行反转,并与结果异或值进行异或操作。
    • 最后,根据 by_byte 参数决定返回结果的形式。如果为 True,则将 CRC 值转换为字节数组形式并返回;如果为 False,则直接返回包含单个 CRC 值的列表。
  3. 示例用法

    # 用户选择一种校验算法
    algorithm = "CRC-16/CCITT-FALSE"
    # 数据可根据需要修改
    data = [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE]
    crc_result = crc_calculator(data, algorithm, True)
    print(crc_result)
    print([hex(byte) for byte in crc_result])
    

    这里展示了如何使用 crc_calculator 函数。用户选择一个特定的算法名称,并提供输入数据。然后,调用函数并将结果打印出来,包括字节数组形式的结果和十六进制形式的结果。

四、使用步骤

  1. 确定要使用的 CRC 算法名称。可以从代码中支持的算法列表中选择,例如 “CRC-16/CCITT-FALSE”。
  2. 准备输入数据。输入数据应该是一个字节列表,可以根据实际情况进行修改。
  3. 调用 crc_calculator 函数,传入输入数据、算法名称和输出形式的参数(如果需要字节数组形式的结果,则 by_byte=True;如果只需要单个校验值,则 by_byte=False)。
  4. 处理函数返回的结果。可以根据需要进行打印、进一步处理或在其他程序中使用。

五、注意事项

  1. 确保选择的算法名称是正确的,并且在代码中支持。如果传入一个未知的算法名称,函数将抛出一个 ValueError 异常。
  2. 理解不同 CRC 算法的参数含义和特点,以便正确选择适合的算法。
  3. 输入数据应该是字节列表形式,如果数据不是以字节为单位的,可以根据需要进行转换。
  4. 注意输入输出反转标志的影响,这可能会改变 CRC 计算的结果。在某些情况下,可能需要根据具体的应用场景调整这些标志。

通过以上教程,你应该能够理解和使用这段代码进行 CRC 校验计算。根据实际需求,可以进一步扩展和优化代码,或者添加更多的 CRC 算法支持。

六、完整代码

# CRC校验,输出一个数组结果的CRC校验数据
def crc_calculator(data , algorithm, by_byte = True):

    crc_parameters = {
        "CRC-4TU": {
            "polynomial": 0x03,
            "width": 4,
            "initial_value": 0x00,
            "result_xor_value": 0x00,
            "input_reversed": True,
            "output_reversed": True
        },
        "CRC-5/EPC": {
            "polynomial": 0x09,
            "width": 5,
            "initial_value": 0x09,
            "result_xor_value": 0x00,
            "input_reversed": False,
            "output_reversed": False
        },
        "CRC-5ATU": {
            "polynomial": 0x15,
            "width": 5,
            "initial_value": 0x00,
            "result_xor_value": 0x00,
            "input_reversed": True,
            "output_reversed": True
        },
        "CRC-5/USB": {
            "polynomial": 0x05,
            "width": 5,
            "initial_value": 0x1F,
            "result_xor_value": 0x1F,
            "input_reversed": True,
            "output_reversed": True
        },
        "CRC-6/TU": {
            "polynomial": 0x03,
            "width": 6,
            "initial_value": 0x00,
            "result_xor_value": 0x00,
            "input_reversed": True,
            "output_reversed": True
        },
        "CRC-7/MMC": {
            "polynomial": 0x09,
            "width": 7,
            "initial_value": 0x00,
            "result_xor_value": 0x00,
            "input_reversed": False,
            "output_reversed": False
        },
        "CRC-8": {
            "polynomial": 0x07,
            "width": 8,
            "initial_value": 0x00,
            "result_xor_value": 0x00,
            "input_reversed": False,
            "output_reversed": False
        },
        "CRC-8ATU": {
            "polynomial": 0x07,
            "width": 8,
            "initial_value": 0x00,
            "result_xor_value": 0x55,
            "input_reversed": False,
            "output_reversed": False
        },
        "CRC-8/ROHC": {
            "polynomial": 0x07,
            "width": 8,
            "initial_value": 0xFF,
            "result_xor_value": 0x00,
            "input_reversed": True,
            "output_reversed": True
        },
        "CRC-8/MAXIM": {
            "polynomial": 0x31,
            "width": 8,
            "initial_value": 0x00,
            "result_xor_value": 0x00,
            "input_reversed": True,
            "output_reversed": True
        },
        "CRC-16/BM": {
            "polynomial": 0x8005,
            "width": 16,
            "initial_value": 0x0000,
            "result_xor_value": 0x0000,
            "input_reversed": True,
            "output_reversed": True
        },
        "CRC-16/MAXIM": {
            "polynomial": 0x8005,
            "width": 16,
            "initial_value": 0x0000,
            "result_xor_value": 0xFFFF,
            "input_reversed": True,
            "output_reversed": True
        },
        "CRC-16/USB": {
            "polynomial": 0x8005,
            "width": 16,
            "initial_value": 0xFFFF,
            "result_xor_value": 0xFFFF,
            "input_reversed": True,
            "output_reversed": True
        },
        "CRC-16/MODBUS": {
            "polynomial": 0x8005,
            "width": 16,
            "initial_value": 0xFFFF,
            "result_xor_value": 0x0000,
            "input_reversed": True,
            "output_reversed": True
        },
        "CRC-16/CCITT": {
            "polynomial": 0x1021,
            "width": 16,
            "initial_value": 0x0000,
            "result_xor_value": 0x0000,
            "input_reversed": True,
            "output_reversed": True
        },
        "CRC-16/CCITT-FALSE": {
            "polynomial": 0x1021,
            "width": 16,
            "initial_value": 0xFFFF,
            "result_xor_value": 0x0000,
            "input_reversed": False,
            "output_reversed": False
        },
        "CRC-16/X25": {
            "polynomial": 0x1021,
            "width": 16,
            "initial_value": 0xFFFF,
            "result_xor_value": 0xFFFF,
            "input_reversed": True,
            "output_reversed": True
        },
        "CRC-16/XMODEM": {
            "polynomial": 0x1021,
            "width": 16,
            "initial_value": 0x0000,
            "result_xor_value": 0x0000,
            "input_reversed": False,
            "output_reversed": False
        },
        "CRC-16/DNP": {
            "polynomial": 0x3D65,
            "width": 16,
            "initial_value": 0x0000,
            "result_xor_value": 0xFFFF,
            "input_reversed": True,
            "output_reversed": True
        },
        "CRC-32": {
            "polynomial": 0x04C11DB7,
            "width": 32,
            "initial_value": 0xFFFFFFFF,
            "result_xor_value": 0xFFFFFFFF,
            "input_reversed": True,
            "output_reversed": True
        },
        "CRC-32MPEG-2": {
            "polynomial": 0x04C11DB7,
            "width": 32,
            "initial_value": 0xFFFFFFFF,
            "result_xor_value": 0x00000000,
            "input_reversed": False,
            "output_reversed": False
        },
        "CRC-64/ECMA": {
            "polynomial": 0x42F0E1EBA9EA3693,
            "width": 64,
            "initial_value": 0xFFFFFFFFFFFFFFFF,
            "result_xor_value": 0xFFFFFFFFFFFFFFFF,
            "input_reversed": False,
            "output_reversed": False
        },
        "CRC-64/GO-ISO": {
            "polynomial": 0xFFFFFFFFFFFFFFFF,
            "width": 64,
            "initial_value": 0xFFFFFFFFFFFFFFFF,
            "result_xor_value": 0xFFFFFFFFFFFFFFFF,
            "input_reversed": False,
            "output_reversed": False
        }
    }

    if algorithm not in crc_parameters:
        raise ValueError(f"Unknown algorithm: {algorithm}")

    params = crc_parameters[algorithm]
    polynomial = params["polynomial"]
    width = params["width"]
    initial_value = params["initial_value"]
    result_xor_value = params["result_xor_value"]
    input_reversed = params["input_reversed"]
    output_reversed = params["output_reversed"]

    crc = initial_value
    for byte in data:
        if input_reversed:
            byte = int('{:08b}'.format(byte)[::-1], 2)
        for _ in range(8):
            bit = (byte >> 7) & 1
            byte <<= 1
            crc <<= 1
            if (crc >> width) & 1 ^ bit:
                crc ^= polynomial
        crc &= (1 << width) - 1

    if output_reversed:
        crc = int('{:0{width}b}'.format(crc, width=width)[::-1], 2)

    crc = crc ^ result_xor_value

    if by_byte:
        if crc == 0:
            return [0]
        crc_array = []
        while crc > 0:
            crc, remainder = divmod(crc, 256)
            crc_array.insert(0, remainder)
        return crc_array
    else:
        return [crc]


# 以下用户自行修改
# 用户选择一种校验算法
algorithm = "CRC-16/CCITT-FALSE"
#数据可根据需要修改
data = [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE]
crc_result = crc_calculator(data, algorithm, True)
print(crc_result)
print([hex(byte) for byte in crc_result])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

elvis_z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值