将 CRC16 CCITT 代码从 C 转换为 Python
Convert CRC16 CCITT code from C to Python
我想Python实现(实际上MicroPython)基于CRC16-CCITT的特定校验和计算。
它将在微控制器上用于通过串行连接检查数据完整性。
该算法可作为 C 实现使用。
校验和为 16 位,类型为 CCITT。校验和从消息的第一个字节开始。
C语言计算CRC16 CCITT的示例代码:
#include <stdint.h>
uint16_t crc_ccitt_update( uint16_t crc, uint8_t data ) {
uint16_t ret_val;
data ^= ( uint8_t )(crc) & (uint8_t )(0xFF);
data ^= data << 4;
ret_val = ((((uint16_t)data << 8) | ((crc & 0xFF00) >> 8))
^ (uint8_t)(data >> 4)
^ ((uint16_t)data << 3));
return ret_val;
}
uint16_t get_crc16z(uint8_t *p, uint16_t len) {
uint16_t crc16_data=0;
while(len--) {
crc16_data = crc_ccitt_update(crc16_data, p[0]); p++;
}
return(crc16_data);
}
要检查的数据包示例是:
0x3D 0x01 0x08 0x06 0x3A 0x00 0x98 0x81
最后两个字节携带校验和作为 LSB 和 MSB,因此预期校验和为(字节反转):
0x8198
我的 C 编码技能远不能将其转换为 Python 代码。所以我首先尝试在网上找到现有的功能。存在很多功能,但似乎总是有实现细节。所以我未能生成有效的 CRC 值。
示例在线位置:
Online CRC calculator, Sunshine's homepage
我试过的示例函数(众多之一):
def crc16(data : bytearray, offset , length):
if data is None or offset < 0 or offset > len(data)- 1 and offset+length > len(data):
return 0
crc = 0xFFFF
for i in range(0, length):
crc ^= data[offset + i] << 8
for j in range(0,8):
if (crc & 0x8000) > 0:
crc =(crc << 1) ^ 0x1021
else:
crc = crc << 1
return crc & 0xFFFF
packet = b'3D0108063A009881'
crc = crc16(packet, 0, int(len(packet)))
print('CRC:', crc)
checksum = int(b'8198', 16)
print('Check:', checksum)
我什至不确定我是否正确使用它们。很可能不会。
第二步是尝试使用现有的 C 代码实现 Ctypes。我使用以下命令在 Mac 上成功生成了一个共享库:
gcc -shared -Wl,-install_name,CRC16_CCITT.so -o CRC16_CCITT.so -fPIC crc16_ccitt.c
但是我的 C 技能又一次不允许我正确地 'populate' 共享库。当我放弃时,看看我失败的尝试(这可能甚至不是正确的 Python 代码):
from ctypes import *
#load the shared object file
crc16_ccitt = CDLL('./CRC16_CCITT.so')
data = b'3D0108063A009881'
pointer = byref(data, 0)
crc = crc16_ccitt.get_crc16z(pointer, len(data))
print('CRC16-CCITT:', crc)
第一个检查是编译,link 和 运行 现有的 C 代码,以查看它是否产生预期的结果。提供的代码已经被我修改过,因为在原始文档中有一些明显的拼写错误(函数调用不匹配)。但是我不知道如何在 C 中 运行 。需要添加一些主要功能,并且需要使用正确的数据类型放置参数。
我最后尝试的是阅读 CRC 算法的理论。这足以让我的头爆炸。
不得已Whosebug
因此,如果能帮助我将现有的 C 代码转换为纯代码,我将不胜感激 Python。
谢谢。
安德烈亚斯
提供的 Python 代码中实现的 CRC 不是 CCITT CRC-16。有趣的是,它被称为 false CCITT CRC-16 in this catalog. The CRC implemented in the provided C code is in fact the CCITT CRC-16.
Python 代码很容易修改以反映正确的定义:
def crc16(data : bytearray, offset , length):
if data is None or offset < 0 or offset > len(data)- 1 and offset+length > len(data):
return 0
crc = 0
for i in range(0, length):
crc ^= data[offset + i]
for j in range(0,8):
if (crc & 1) > 0:
crc = (crc >> 1) ^ 0x8408
else:
crc = crc >> 1
return crc
我想Python实现(实际上MicroPython)基于CRC16-CCITT的特定校验和计算。 它将在微控制器上用于通过串行连接检查数据完整性。
该算法可作为 C 实现使用。
校验和为 16 位,类型为 CCITT。校验和从消息的第一个字节开始。 C语言计算CRC16 CCITT的示例代码:
#include <stdint.h>
uint16_t crc_ccitt_update( uint16_t crc, uint8_t data ) {
uint16_t ret_val;
data ^= ( uint8_t )(crc) & (uint8_t )(0xFF);
data ^= data << 4;
ret_val = ((((uint16_t)data << 8) | ((crc & 0xFF00) >> 8))
^ (uint8_t)(data >> 4)
^ ((uint16_t)data << 3));
return ret_val;
}
uint16_t get_crc16z(uint8_t *p, uint16_t len) {
uint16_t crc16_data=0;
while(len--) {
crc16_data = crc_ccitt_update(crc16_data, p[0]); p++;
}
return(crc16_data);
}
要检查的数据包示例是:
0x3D 0x01 0x08 0x06 0x3A 0x00 0x98 0x81
最后两个字节携带校验和作为 LSB 和 MSB,因此预期校验和为(字节反转):
0x8198
我的 C 编码技能远不能将其转换为 Python 代码。所以我首先尝试在网上找到现有的功能。存在很多功能,但似乎总是有实现细节。所以我未能生成有效的 CRC 值。
示例在线位置: Online CRC calculator, Sunshine's homepage
我试过的示例函数(众多之一):
def crc16(data : bytearray, offset , length):
if data is None or offset < 0 or offset > len(data)- 1 and offset+length > len(data):
return 0
crc = 0xFFFF
for i in range(0, length):
crc ^= data[offset + i] << 8
for j in range(0,8):
if (crc & 0x8000) > 0:
crc =(crc << 1) ^ 0x1021
else:
crc = crc << 1
return crc & 0xFFFF
packet = b'3D0108063A009881'
crc = crc16(packet, 0, int(len(packet)))
print('CRC:', crc)
checksum = int(b'8198', 16)
print('Check:', checksum)
我什至不确定我是否正确使用它们。很可能不会。
第二步是尝试使用现有的 C 代码实现 Ctypes。我使用以下命令在 Mac 上成功生成了一个共享库:
gcc -shared -Wl,-install_name,CRC16_CCITT.so -o CRC16_CCITT.so -fPIC crc16_ccitt.c
但是我的 C 技能又一次不允许我正确地 'populate' 共享库。当我放弃时,看看我失败的尝试(这可能甚至不是正确的 Python 代码):
from ctypes import *
#load the shared object file
crc16_ccitt = CDLL('./CRC16_CCITT.so')
data = b'3D0108063A009881'
pointer = byref(data, 0)
crc = crc16_ccitt.get_crc16z(pointer, len(data))
print('CRC16-CCITT:', crc)
第一个检查是编译,link 和 运行 现有的 C 代码,以查看它是否产生预期的结果。提供的代码已经被我修改过,因为在原始文档中有一些明显的拼写错误(函数调用不匹配)。但是我不知道如何在 C 中 运行 。需要添加一些主要功能,并且需要使用正确的数据类型放置参数。
我最后尝试的是阅读 CRC 算法的理论。这足以让我的头爆炸。
不得已Whosebug
因此,如果能帮助我将现有的 C 代码转换为纯代码,我将不胜感激 Python。
谢谢。
安德烈亚斯
提供的 Python 代码中实现的 CRC 不是 CCITT CRC-16。有趣的是,它被称为 false CCITT CRC-16 in this catalog. The CRC implemented in the provided C code is in fact the CCITT CRC-16.
Python 代码很容易修改以反映正确的定义:
def crc16(data : bytearray, offset , length):
if data is None or offset < 0 or offset > len(data)- 1 and offset+length > len(data):
return 0
crc = 0
for i in range(0, length):
crc ^= data[offset + i]
for j in range(0,8):
if (crc & 1) > 0:
crc = (crc >> 1) ^ 0x8408
else:
crc = crc >> 1
return crc