我正在开发一个通过RS232或RS485连接提供简单可靠通信的库。此代码的一部分涉及对数据使用CRC 16校验和来检测线路噪声的损坏。我创建了一个函数来计算CRC 16校验和,但它似乎没有输出正确的值。
我写的相关代码如下(也可以在here中找到)。
#include <stdint.h>
#define CRC16 0x8005
uint16_t gen_crc16(const uint8_t *data, uint16_t size)
{
uint16_t out = 0;
int bits_read = 0, bit_flag;
/* Sanity check: */
if(data == NULL)
return 0;
while(size > 0)
{
bit_flag = out >> 15;
/* Get next bit: */
out <<= 1;
out |= (*data >> (7 - bits_read)) & 1;
/* Increment bit counter: */
bits_read++;
if(bits_read > 7)
{
bits_read = 0;
data++;
size--;
}
/* Cycle check: */
if(bit_flag)
out ^= CRC16;
}
return out;
}
我正在对照this online CRC calculator检查我的输出。
我得出的结论是,要么我对如何计算CRC 16的理解是错误的,要么在线计算器是错误的(前者似乎更有可能)。有人能告诉我我可能会错在哪里吗?
7条答案
按热度按时间6ju8rftf1#
对于特定的CRC实现,您需要“匹配”几个细节-即使使用相同的多项式,也可能会有不同的结果,因为数据位处理方式的微小差异,使用CRC的特定初始值(有时为零,有时为0xffff)和/或反转CRC的位。例如,有时一个实现将从数据字节的低阶位开始工作,而有时它们将从高阶位开始工作(就像您当前所做的那样)。
此外,您需要在运行所有数据位之后“推出”CRC的最后一位。
请记住,CRC算法被设计为在硬件中实现,因此从软件的Angular 来看,一些如何处理位排序的问题可能没有太大意义。
如果您想将CRC 16与多项式0x 8005匹配,如lammertbies.nl CRC计算器页面所示,则需要对CRC函数进行以下更改:
所以,你的函数可能看起来像这样:
当我传入
"123456789"
时,该函数返回0xbb3d
。rhfm7lfc2#
下面是计算crc16 CCITT的工作代码。我测试了它,结果与http://www.lammertbies.nl/comm/info/crc-calculation.html提供的结果相匹配。
jjhzyzn03#
crcany将为任何CRC生成有效的C代码,并包含超过一百个已知CRC定义的库。
高效的CRC代码使用表格而不是逐位计算。crcany生成字节方式例程和字方式例程,后者被调整到它们在其上生成的体系结构。智慧是最快的。字节方式仍然比位方式快得多,但这种实现更容易在架构上移植。
您似乎没有需要匹配的具有特定CRC定义的协议定义。在这种情况下,您可以在catalog中选择任何16位CRC,并且您将获得良好的性能。
如果你有一个相对较低的误码率,例如,每个数据包的错误数为个位数,并且您希望最大化错误检测性能,则需要查看要应用CRC的数据包大小(假设该大小为常数或有界),并查看Philip Koopman's extensive research中最佳多项式的性能。经典的CRC,如CCITT/Kermit 16位CRC或X.25 16位CRC并不是性能最好的。
在Koopman的表中,CRC-16/DNP是一种性能良好的16位CRC,它也在实践中使用的CRC目录中。它具有非常好的性能,可以检测数据包中高达6位的错误。以下是crcany为CRC定义生成的代码。这段代码假设了一个小端体系结构来进行逐字计算,例如:Intel x86和x86-64,并假设
uintmax_t
是64位。CRCANY可用于生成用于大端字节序和其它字大小的替换代码。dwbf0jvd4#
CRC-16有几个不同的品种。请参见wiki page。
每一个都将从相同的输入返回不同的结果。
所以你必须仔细选择一个正确的程序。
qnzebej05#
c90pui9n6#
我使用的代码示例来自:http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html#ch5
还有这个实用程序来验证:http://www.sunshine2k.de/coding/javascript/crc/crc_js.html
evrscar27#
为了生成数据包的校验和,例如该数据包“78781101086655103641220800002122000fdcfd0d0a”“dcfd”,这是错误校验和,这是由“1101086655103641220800002122000f”生成的,这些人误解了生成“dcfd”的响应校验和。但是校验和是通过使用其自己的分组数据来生成的。
7878和odoa是固定的,所以..
检查你的代码使用这个作为一个例子“78781101086655103641220800002122000fdcfd0d0a”通过它“1101086655103641220800002122000f”和它的答案是“dcfd”意味着你的代码工作正常
ignore 8a51这只是为了检查不要担心帮助:email protected(https://stackoverflow.com/cdn-cgi/l/email-protection)
在checksumExample和boom中导入此校验和
我的校验和是在org.traccar.helper文件夹..