CRC-15给出错误的值

时间:2017-04-14 22:32:25

标签: c return checksum crc

我正在尝试在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;
}

2 个答案:

答案 0 :(得分:1)

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

        if(divRemainder & 0x8000)

这个问题没有说明CRC是否被比特反映(xor数据转换为CRC的低阶位,右移为循环)(xor数据转换为CRC的高阶位,左移为循环),所以我无法为其余代码提供帮助。

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

传统CRC的逻辑是:

  • 将一个字节的数据写入CRC(高位或低位)
  • 循环CRC 8次(或进行表查找)

在为整个消息生成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,也没有提到结果是否补充,也没有其他标准,所以这个发布的代码只能作为指南。