我正在尝试在c中创建CRC-15检查,并且输出对于文件的每一行都不正确。我试图在每一行旁边累加输出每行的CRC。我使用:#define POLYNOMIAL 0xA053作为除数和分红的文本。我需要将数字表示为32位无符号整数。我已经尝试打印出十六进制值以跟踪和翻转不同的移位。但是,我似乎无法弄明白!我觉得这与我填充东西的方式有关。我的逻辑有缺陷吗?
CRC用四个十六进制数表示,该序列将有四个前导0' s。例如,它看起来像0000xxxx,其中x是十六进制数字。我使用的多项式是0xA053。
我考虑过使用一个临时变量,并且每个XOR每行执行4个16位代码块,但是,我不太确定如何使用shift来实现这一点,所以我决定使用一个字母的校验和在线上,然后XORing,试图计算CRC码。
我正在使用以下输入和填充来测试我的代码。直到字符串的长度为504,因为这是填充字符需要通过给定的要求: "这是教训:永不屈服,永不屈服,永不,永不,永不,永不 - 无所不在,无论大小,大或小 - 除了荣誉和良好的信念外,绝不屈服。绝不屈服于力量;永远屈服于敌人显然压倒性的威力。"
第一个64字符线的CRC("这是教训:永不放弃,永不放弃,从不,永远,)应该是000015fa,我得到bfe6ec00。
我的逻辑:
在CRCCalculation中,我将每个字符添加到32位无符号整数中,并在64(一行的长度)之后将其发送到XOR函数。
如果顶部位不是1,我将数字移到左边 导致0填充右边并再次循环。
如果最高位为1,我将除数与除数进行异或,然后将被除数移到左边。
完成所有计算后,我将红利返回到左边四(向正面添加四个零)到计算功能
将结果添加到结果的运行总计
代码:
#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;
}
答案 0 :(得分:1)
我看到的第一个问题是最高位检查,它应该是:
if(divRemainder & 0x8000)
这个问题没有说明CRC是否被比特反映(xor数据转换为CRC的低阶位,右移为循环)(xor数据转换为CRC的高阶位,左移为循环),所以我无法为其余代码提供帮助。
问题没有说明CRC的初始值(0x0000或0x7fff),或者CRC是否后补充。
传统CRC的逻辑是:
在为整个消息生成CRC之后,可以将CRC附加到消息中。如果为具有附加CRC的消息生成CRC并且没有错误,则CRC将为零(或者如果CRC被后置补充则为常数值)。
答案 1 :(得分:1)
这是典型的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,逻辑会更加复杂,因为无法使用整个字节,所以会有很多位移和AND运算来提取所需的15位。
注意:OP没有提到CRC的初始值是0x0000还是0x7FFF,也没有提到结果是否补充,也没有其他标准,所以这个发布的代码只能作为指南。