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。

我的逻辑:

代码:

#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,也没有提到结果是否要补,也没有提到某些其他标准,所以这个发布的代码只能作为一个指南。