一、代码功能概述
这段 Python 代码实现了多种不同 CRC(循环冗余校验)算法的计算功能。用户可以选择特定的 CRC 算法,然后输入数据,函数将返回该数据的 CRC 校验结果。可以选择以字节数组的形式(高位在前)或单个值的列表形式输出结果。
二、准备工作
- 确保你已经安装了 Python 环境。
- 理解 CRC 校验的基本概念和不同算法的参数含义,例如多项式、宽度、初始值、结果异或值以及输入输出反转标志等。
- 常见的CRC参考模型:
三、代码结构解析
-
定义 CRC 参数字典:
crc_parameters = { "CRC-4TU": { "polynomial": 0x03, "width": 4, "initial_value": 0x00, "result_xor_value": 0x00, "input_reversed": True, "output_reversed": True }, # 其他算法的参数... }
这里使用字典存储了各种 CRC 算法的参数,每个算法对应一个字典条目,包含了该算法所需的多项式、宽度、初始值、结果异或值以及输入输出反转标志等信息。
-
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 值的列表。
-
示例用法:
# 用户选择一种校验算法 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
函数。用户选择一个特定的算法名称,并提供输入数据。然后,调用函数并将结果打印出来,包括字节数组形式的结果和十六进制形式的结果。
四、使用步骤
- 确定要使用的 CRC 算法名称。可以从代码中支持的算法列表中选择,例如 “CRC-16/CCITT-FALSE”。
- 准备输入数据。输入数据应该是一个字节列表,可以根据实际情况进行修改。
- 调用
crc_calculator
函数,传入输入数据、算法名称和输出形式的参数(如果需要字节数组形式的结果,则by_byte=True
;如果只需要单个校验值,则by_byte=False
)。 - 处理函数返回的结果。可以根据需要进行打印、进一步处理或在其他程序中使用。
五、注意事项
- 确保选择的算法名称是正确的,并且在代码中支持。如果传入一个未知的算法名称,函数将抛出一个 ValueError 异常。
- 理解不同 CRC 算法的参数含义和特点,以便正确选择适合的算法。
- 输入数据应该是字节列表形式,如果数据不是以字节为单位的,可以根据需要进行转换。
- 注意输入输出反转标志的影响,这可能会改变 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])