【发布时间】:2021-07-10 21:26:37
【问题描述】:
我想做一个基于 CRC16-CCITT 的特定校验和计算的 Python 实现(实际上是 MicroPython)。 它将在微控制器上用于通过串行连接检查数据完整性。
该算法可作为 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 技能再次不允许我正确“填充”共享库。当我放弃时,看看我失败的尝试(可能甚至不是正确的 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)
第一个检查是编译、链接和运行现有的 C 代码,以查看它是否产生预期的结果。提供的代码已经被我修改过,因为在原始文档中有一些明显的拼写错误(函数调用不匹配)。但我不知道如何在 C 中运行它。需要添加一些主函数,并且需要使用正确的数据类型放置参数。
我尝试的最后一件事是阅读 CRC 算法的理论。这足以让我的头爆炸。
最后的手段stackoverflow
因此,如果能在将现有 C 代码转换为纯 Python 方面提供任何帮助,我将不胜感激。
谢谢。
安德烈亚斯
【问题讨论】:
标签: python c micropython crc16