CRC位序混淆

时间:2014-12-06 14:17:02

标签: c language-agnostic crc

我正在逐位计算CCITT CRC-16。我这样做是因为它是一个原型,以后应该移植到VHDL并最终用硬件来检查串行比特流。

在网上我找到了一位CRC-16更新步骤代码。写了一个测试程序,它的工作原理。除了一个奇怪的事情:我必须从最低位到最高位提供一个字节的位。如果我这样做,我会得到正确的结果。

在CRCITT的CCITT定义中,这些位应该是最高位到最低位。我想要计算CRC的数据流也是这种格式的,所以我现在的代码对我来说没什么用。

我很困惑。我不希望以错误的方式喂食这些钻头可能会起作用。

问题:为什么可以编写CRC来以两个不同的位顺序获取数据,以及如何转换它首先接受数据MSB的单位更新代码?

供参考,以下是相关代码。已删除初始化和最终检查以保持示例简短:

typedef unsigned char bit;

void update_crc_single_bit (bit * crc, bit data)
{
  // update CRC for a single bit:
  bit temp[16];
  int i;

  temp[0] = data ^ crc[15]; 
  temp[1] = crc[0]; 
  temp[2] = crc[1]; 
  temp[3] = crc[2]; 
  temp[4] = crc[3]; 
  temp[5] = data ^ crc[4] ^ crc[15]; 
  temp[6] = crc[5]; 
  temp[7] = crc[6]; 
  temp[8] = crc[7]; 
  temp[9] = crc[8]; 
  temp[10] = crc[9]; 
  temp[11] = crc[10]; 
  temp[12] = data ^ crc[11] ^ crc[15]; 
  temp[13] = crc[12]; 
  temp[14] = crc[13]; 
  temp[15] = crc[14];

  for (i=0; i<16; i++)
    crc[i] = temp[i];
}

void update_crc_byte (bit * crc, unsigned char data)
{
  int j;
  // calculate CRC lowest bit first
  for (j=0; j<8; j++)
  {
    bit b = (data>>j)&1;
    update_crc_single_bit(crc, b);
  }
}

编辑:由于这里有一些混淆:我必须逐位计算CRC,并且首先为每个字节MSB计算。我不能简单地存储这些位,因为上面显示的代码是最终硬件(没有内存)的原型。

如果按以下顺序输入比特流,则上面显示的代码会生成正确的结果(显示的是接收比特的索引。每个字节首先发送MSB):

|- first byte -|-   second byte     -|-  third byte 
7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8,....

我需要转换单个更新循环,它使用自然顺序生成相同的CRC(例如,已接收):

|- first byte -|-   second byte     -|-  third byte 
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,.... 

3 个答案:

答案 0 :(得分:5)

如果查看RevEng 16-bit CRC Catalogue,您会看到有两个不同的CRC称为“CCITT”,其中一个标记为“CCITT-False”。在某个地方,有人对CCITT 16位CRC的含义感到困惑,并且这种混乱被广泛传播。这样描述了两个CRC,第一个(KERMIT)是真正的CCITT CRC:

KERMIT

width=16 poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189 name="KERMIT"

CRC-16/CCITT-FALSE

width=16 poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1 name="CRC-16/CCITT-FALSE"

您将注意到真实的一个被反映,而假的一个没有被反映,并且初始化中存在另一个差异。在反射的CRC中,首先处理数据的最低位,因此您似乎正在尝试计算真正的CCITT CRC。

当反映CRC时,异或存储到寄存器中的位的顺序也是如此,因此0x1021变为0x8408。这是一个简单的C实现,您可以检查:

#include <stddef.h>

#define POLY 0x8408

unsigned crc16_ccitt(unsigned crc, unsigned char *buf, size_t len)
{
    int k;

    while (len--) {
        crc ^= *buf++;
        for (k = 0; k < 8; k++)
            crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
    }
    return crc;
}

我不知道你的意思“在CRCITT的CCITT定义中,这些位应该是最高位到最低位”。你指的是什么定义?

this Altera document中,您可以看到用于硬件实现的CRC的移位寄存器实现。这是图表的副本:

CCITT CRC shift register with taps at register 16, 10, and 3

对于您的代码,您需要撤消您的注册,temp[],索引。 temp[0]temp[15],依此类推。

答案 1 :(得分:0)

更新 - 如果你看一下:

RevEng 16-bit CRC Catalogue

有一个链接:

Online CRC calculator

标记为CRC-CCITT的前三个使用多项式0x11021对发送或接收MSB到LSB的数据进行操作。唯一的区别是起始值:

CRC-CCITT(XModem) - crc初始化为0x0000,与0x0000前缀相同。

CRC-CCITT(0xFFFF) - crc初始化为0xFFFF,与0x84CF前缀相同。

CRC-CCITT(0x1D0F) - crc初始化为0x1D0F,与0xFFFF前缀相同。

所以我的猜测是你要使用这三种中的一种。

答案 2 :(得分:0)

通常,首先在行最低有效位上传输位。所以,如果你有一个字节数组,第一个位是第一个字节的最低有效位,那么接下来是最低有效位...所以直到第一个字节的最高有效位然后是最低有效位下一个字节。这是您正在进行的多元分割中的比特(系数)的顺序。在https://github.com/mojadita/crc.git尝试我的例程(你有CRC16-CCITT表)