2017-04-14 127 views
0

我想在c中创建一个CRC-15检查,并且输出永远不会对文件的每一行都正确。我试图在每行旁边累积地输出每行的CRC。我使用#define POLYNOMIAL 0xA053作为除数和分红文本。我需要将数字表示为32位无符号整数。我试图打印出十六进制值来跟踪和翻转不同的转变。但是,我似乎无法弄清楚!我有一种感觉,它与我填充东西的方式有关。我的逻辑有缺陷吗?CRC-15给出错误的值

CRC将以四个十六进制数字表示,该序列将具有四个前导0。例如,它看起来像0000xxxx,其中x是十六进制数字。我使用的多项式是0xA053。

我想过使用一个临时变量,并且每个XOR每行都执行4个16位块的代码,但是,我不太确定如何使用班次来完成这个操作,所以我解决了字母校验和问题该行然后异或以尝试计算CRC码。

我正在测试我的代码,使用下面的输入和填充。直到字符串的长度为504,因为这是垫字符需要通过给定的要求: “这是一个教训:永不放弃,永不放弃,永不永远,永不绝望,绝不 - 永远 - 没有,伟大的或小的,大的或小的 - 除了要有荣誉和良好的判断力外,绝不要屈服,绝不屈服于力量,绝不屈服于敌人的压倒性力量。“

第64字符行的CRC(“这是教训:永远不要放弃,永不放弃,永远,永远,)应该是000015fa和我得到bfe6ec00

我的逻辑:

  • 在CRCCalculation我每个字符添加到一个32位无符号整数,64(一条线的长度)后,我将其发送到XOR函数。

  • 如果最高位是不1,我把号码移到左边的那个 ca使用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

你为什么总结每个64个字符的文字?这不是一个CRC。 – TrentP

+0

我试图获得每条线的CRC总数cummatively,我认为这个总结和XORing会得到该行的位,然后我会去并添加在下一行,并获得这些位...我是考虑将文本数组发送到XOR函数中,并创建一个临时变量来逐位移位,但是,我不太清楚如何将这些位移入临时数组。例如,如果我发送一行4个16位块进入异或,并根据需要移入另一位,直到数组为空,并将其用于异或事情,这会比求和更多的CRC吗? – starlight

+0

为什么你不计算16位CRC?每次使用一个完整的字节要容易得多,而不是部分字节/ – user3629249

回答

1

第一个问题,我看到的是顶位检查,它应该是:

 if(divRemainder & 0x8000) 

如果CRC比特反射(XOR数据转换成CRC的低位比特,用于循环向右移位)或未被(XOR数据转换成CRC的高位比特,用于循环左移位)的问题没有说明,所以我无法为其余的代码提供帮助。

这个问题没有说明CRC的初始值(0x0000或0x7fff),或者CRC是后缀补充的。

用于常规CRC的逻辑是:

  • XOR数据的一个字节到CRC(上或下位)
  • 循环的CRC的8倍(或执行表查找)

在为整个消息生成CRC后,可以将CRC附加到消息中。如果为具有附加CRC的消息生成CRC并且没有错误,则CRC将为零(或者如果CRC被后补充,则为恒定值)。

+0

我不太清楚CRC的初始值是什么意思,我设置结果= 0,然后将xor值加和到结果中。至于反映,我正在更新这篇文章,希望能回答这个问题。 – starlight

+0

@starlight - 我更新了我的答案。 – rcgldr

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,结果是补全还是其他条件,所以本发布代码只能作为指导。

+0

应该注意的是,预先计算CRC表可以使该代码更快得多,因为可以消除内部循环和位移。 – user3629249

+0

谢谢!我会研究一下。 – starlight