CRC-15 给出了错误的值
CRC-15 giving wrong values
我正在尝试在 c 中创建 CRC-15 校验,但文件的每一行的输出都不正确。我正在尝试在每行旁边累积输出每行的 CRC。我使用:#define POLYNOMIAL 0xA053 作为除数,文本作为股息。我需要将数字表示为 32 位无符号整数。我尝试打印出十六进制值以跟踪并翻转不同的班次。但是,我似乎无法弄清楚!我觉得这与我填充东西的方式有关。我的逻辑有问题吗?
CRC 将用四个十六进制数表示,该序列将有四个前导 0。例如,它看起来像 0000xxxx,其中 x 是十六进制数字。我使用的多项式是 0xA053。
我考虑过使用一个临时变量,并在每个 XOR 中每行执行 4 个 16 位代码块,但是,我不太确定如何使用移位来完成此操作,所以我选择了字母校验和在线然后对其进行异或运算以尝试计算 CRC 代码。
我正在使用以下输入和填充来测试我的代码。直到字符串的长度为 504,因为根据给定的要求,这是填充字符需要的长度:
"This is the lesson: never give in, never give in, never, never, never, never - in nothing, great or small, large or petty - never give in except to convictions of honor and good sense. Never yield to force; never yield to the apparently overwhelming might of the enemy."
前 64 个字符行的 CRC(“这是教训:永不屈服,永不屈服,永不,永不,”)应该是 000015fa,我得到的是 bfe6ec00。
我的逻辑:
在CRCCalculation中我将每个字符添加到一个32位无符号整数并且在64(一行的长度)之后我将它发送到XOR函数中。
如果最高位不为1,我向左移一位
导致 0 向右填充并再次循环。
如果最高位为1,我将被除数与除数异或,然后将被除数左移
所有计算完成后,我return将被除数左移四位(在前面加四个零)到计算函数
将结果添加到 运行 结果总和
代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <ctype.h>
#define POLYNOMIAL 0xA053
void crcCalculation(char *text, int length)
{
int i;
uint32_t dividend = atoi(text);
uint32_t result;
uint32_t sumText = 0;
// Calculate CRC
printf("\nCRC 15 calculation progress:\n");
i = length;
// padding
if(i < 504)
{
for(; i!=504; i++)
{
// printf("i is %d\n", i);
text[i] = '.';
}
}
// Try calculating by first line of crc by summing the values then calcuating, then add in the next line
for (i = 0; i < 504; i++)
{
if(i%64 == 0 && i != 0)
{
result = XOR(POLYNOMIAL, sumText);
printf(" - %x\n",result);
}
sumText +=(uint32_t)text[i];
printf("%c", text[i]);
}
printf("\n\nCRC15 result : %x\n", result);
}
uint32_t XOR(uint32_t divisor, uint32_t dividend)
{
uint32_t divRemainder = dividend;
uint32_t currentBit;
// Note: 4 16 bit chunks
for(currentBit = 32; currentBit > 0; --currentBit)
{
// if topbit is 1
if(divRemainder & 0x80)
{
//divRemainder = (divRemainder << 1) ^ divisor;
divRemainder ^= divisor;
printf("%x %x\n", divRemainder, divisor);
}
// else
// divisor = divisor >> 1;
divRemainder = (divRemainder << 1);
}
//return divRemainder; , have tried shifting to right and left, want to add 4 zeros to front so >>
//return divRemainder >> 4;
return divRemainder >> 4;
}
我看到的第一个问题是top bit check,应该是:
if(divRemainder & 0x8000)
问题没有说明 CRC 是按位反映的(将数据异或到 CRC 的低位,循环右移)还是不是(将数据异或到 CRC 的高位,循环左移),所以我无法为其余代码提供帮助。
问题没有说明 CRC 的初始值(0x0000 或 0x7fff),或者 CRC 是否 post 补码。
常规 CRC 的逻辑是:
- xor 将一个字节的数据放入 CRC(高位或低位)
- 循环 CRC 8 次(或进行 table 查找)
为整个消息生成 CRC 后,可以将 CRC 附加到消息中。如果为带有附加 CRC 的消息生成 CRC 并且没有错误,则 CRC 将为零(如果 CRC 是 post 补码,则为常数值)。
这是一个典型的 CRC16,摘自:<www8.cs.umu.se/~isak/snippets/crc-16.c>
#define POLY 0x8408
/*
// 16 12 5
// this is the CCITT CRC 16 polynomial X + X + X + 1.
// This works out to be 0x1021, but the way the algorithm works
// lets us use 0x8408 (the reverse of the bit pattern). The high
// bit is always assumed to be set, thus we only use 16 bits to
// represent the 17 bit value.
*/
unsigned short crc16(char *data_p, unsigned short length)
{
unsigned char i;
unsigned int data;
unsigned int crc = 0xffff;
if (length == 0)
return (~crc);
do
{
for (i=0, data=(unsigned int)0xff & *data_p++;
i < 8;
i++, data >>= 1)
{
if ((crc & 0x0001) ^ (data & 0x0001))
crc = (crc >> 1) ^ POLY;
else crc >>= 1;
}
} while (--length);
crc = ~crc;
data = crc;
crc = (crc << 8) | (data >> 8 & 0xff);
return (crc);
}
由于您要计算 CRC15 而不是 CRC16,因此逻辑会更复杂,因为不能处理整个字节,因此需要进行大量位移和 ANDing 操作才能提取所需的 15 位。
注意:OP没有提到CRC的初始值是0x0000还是0x7FFF,也没有提到结果是否要补,也没有提到某些其他标准,所以这个发布的代码只能作为一个指南。
我正在尝试在 c 中创建 CRC-15 校验,但文件的每一行的输出都不正确。我正在尝试在每行旁边累积输出每行的 CRC。我使用:#define POLYNOMIAL 0xA053 作为除数,文本作为股息。我需要将数字表示为 32 位无符号整数。我尝试打印出十六进制值以跟踪并翻转不同的班次。但是,我似乎无法弄清楚!我觉得这与我填充东西的方式有关。我的逻辑有问题吗?
CRC 将用四个十六进制数表示,该序列将有四个前导 0。例如,它看起来像 0000xxxx,其中 x 是十六进制数字。我使用的多项式是 0xA053。
我考虑过使用一个临时变量,并在每个 XOR 中每行执行 4 个 16 位代码块,但是,我不太确定如何使用移位来完成此操作,所以我选择了字母校验和在线然后对其进行异或运算以尝试计算 CRC 代码。
我正在使用以下输入和填充来测试我的代码。直到字符串的长度为 504,因为根据给定的要求,这是填充字符需要的长度: "This is the lesson: never give in, never give in, never, never, never, never - in nothing, great or small, large or petty - never give in except to convictions of honor and good sense. Never yield to force; never yield to the apparently overwhelming might of the enemy."
前 64 个字符行的 CRC(“这是教训:永不屈服,永不屈服,永不,永不,”)应该是 000015fa,我得到的是 bfe6ec00。
我的逻辑:
在CRCCalculation中我将每个字符添加到一个32位无符号整数并且在64(一行的长度)之后我将它发送到XOR函数中。
如果最高位不为1,我向左移一位 导致 0 向右填充并再次循环。
如果最高位为1,我将被除数与除数异或,然后将被除数左移
所有计算完成后,我return将被除数左移四位(在前面加四个零)到计算函数
将结果添加到 运行 结果总和
代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <ctype.h>
#define POLYNOMIAL 0xA053
void crcCalculation(char *text, int length)
{
int i;
uint32_t dividend = atoi(text);
uint32_t result;
uint32_t sumText = 0;
// Calculate CRC
printf("\nCRC 15 calculation progress:\n");
i = length;
// padding
if(i < 504)
{
for(; i!=504; i++)
{
// printf("i is %d\n", i);
text[i] = '.';
}
}
// Try calculating by first line of crc by summing the values then calcuating, then add in the next line
for (i = 0; i < 504; i++)
{
if(i%64 == 0 && i != 0)
{
result = XOR(POLYNOMIAL, sumText);
printf(" - %x\n",result);
}
sumText +=(uint32_t)text[i];
printf("%c", text[i]);
}
printf("\n\nCRC15 result : %x\n", result);
}
uint32_t XOR(uint32_t divisor, uint32_t dividend)
{
uint32_t divRemainder = dividend;
uint32_t currentBit;
// Note: 4 16 bit chunks
for(currentBit = 32; currentBit > 0; --currentBit)
{
// if topbit is 1
if(divRemainder & 0x80)
{
//divRemainder = (divRemainder << 1) ^ divisor;
divRemainder ^= divisor;
printf("%x %x\n", divRemainder, divisor);
}
// else
// divisor = divisor >> 1;
divRemainder = (divRemainder << 1);
}
//return divRemainder; , have tried shifting to right and left, want to add 4 zeros to front so >>
//return divRemainder >> 4;
return divRemainder >> 4;
}
我看到的第一个问题是top bit check,应该是:
if(divRemainder & 0x8000)
问题没有说明 CRC 是按位反映的(将数据异或到 CRC 的低位,循环右移)还是不是(将数据异或到 CRC 的高位,循环左移),所以我无法为其余代码提供帮助。
问题没有说明 CRC 的初始值(0x0000 或 0x7fff),或者 CRC 是否 post 补码。
常规 CRC 的逻辑是:
- xor 将一个字节的数据放入 CRC(高位或低位)
- 循环 CRC 8 次(或进行 table 查找)
为整个消息生成 CRC 后,可以将 CRC 附加到消息中。如果为带有附加 CRC 的消息生成 CRC 并且没有错误,则 CRC 将为零(如果 CRC 是 post 补码,则为常数值)。
这是一个典型的 CRC16,摘自:<www8.cs.umu.se/~isak/snippets/crc-16.c>
#define POLY 0x8408
/*
// 16 12 5
// this is the CCITT CRC 16 polynomial X + X + X + 1.
// This works out to be 0x1021, but the way the algorithm works
// lets us use 0x8408 (the reverse of the bit pattern). The high
// bit is always assumed to be set, thus we only use 16 bits to
// represent the 17 bit value.
*/
unsigned short crc16(char *data_p, unsigned short length)
{
unsigned char i;
unsigned int data;
unsigned int crc = 0xffff;
if (length == 0)
return (~crc);
do
{
for (i=0, data=(unsigned int)0xff & *data_p++;
i < 8;
i++, data >>= 1)
{
if ((crc & 0x0001) ^ (data & 0x0001))
crc = (crc >> 1) ^ POLY;
else crc >>= 1;
}
} while (--length);
crc = ~crc;
data = crc;
crc = (crc << 8) | (data >> 8 & 0xff);
return (crc);
}
由于您要计算 CRC15 而不是 CRC16,因此逻辑会更复杂,因为不能处理整个字节,因此需要进行大量位移和 ANDing 操作才能提取所需的 15 位。
注意:OP没有提到CRC的初始值是0x0000还是0x7FFF,也没有提到结果是否要补,也没有提到某些其他标准,所以这个发布的代码只能作为一个指南。