在C中生成的CRC查找表总是会给出不同的结果

时间:2017-10-05 03:42:18

标签: c memory crc lookup-tables

我正在尝试创建一个生成CRC查找表的函数。我正在使用8051微控制器,我宁愿做表查找方法,但同时,我宁愿让我的计算机生成值,然后我可以直接加载到微控制器。大部分源代码都来自:http://www.rajivchakravorty.com/source-code/uncertainty/multimedia-sim/html/crc8_8c-source.html

我只添加了“主要”功能

#include <stdio.h>
#define GP  0x107
#define DI  0x07

static unsigned char crc8_table[256];
static int made_table=0;

static void init_crc8()
{
  int i,j;
  unsigned char crc;
  if (!made_table) {
    for (i=0; i<256; i++) {
      crc = i;
      for (j=0; j<8; j++)
        crc = (crc << 1) ^ ((crc & 0x80) ? DI : 0);
      crc8_table[i] = crc & 0xFF;
    }
    made_table=1;
  }
}

void crc8(unsigned char *crc, unsigned char m)
{
  if (!made_table)
    init_crc8();
  *crc = crc8_table[(*crc) ^ m];
  *crc &= 0xFF;
}

int main()
{
  unsigned char crc[1];
  crc8(crc,'S');
  printf("S=%x\n",crc[0]); //different hex code almost every time
  crc8(crc,'T');
  printf("T=%x\n",crc[0]); //different hex code almost every time
  return 0;
}

当我执行程序时,我期望屏幕上显示相同的值,但是几乎每个程序执行时,打印的等号都会改变十六进制代码。

我该怎么做才能纠正这个问题?我不想收集不正确的CRC值。

2 个答案:

答案 0 :(得分:0)

主要是,crc [0]尚未初始化。因此,在crc8中,表达式(* crc)^ m 中的* crc未初始化,因此是您的随机值。

修复:初始化crc [0]。像

这样的东西
unsigned char crc[1] = { 0 };

答案 1 :(得分:0)

  1. crc[0]未初始化。在使用crc[0] = 0;致电*crc = 0;之前,您需要crc8()crc。然后,您将无法从crc[0]的随机初始内容中获得随机答案。
  2. 您不需要*crc &= 0xff;中的crc8()。如果char是8位,那么它什么都不做。如果你有一个奇怪的架构char超过8位,那么你需要*crc = crc8_table[((*crc) ^ m) & 0xff];来确保你不超出表的范围。 (在CRC计算中只使用m的低8位。)表的内容已限制为8位,因此无论如何您不需要最终& 0xff
  3. 您可能需要与零不同的初始值,并且您可能需要使用某些内容来排除或使用最终CRC值,具体取决于您想要的CRC-8的定义。在RevEng catalog of CRC's中,有两个具有该多项式的8位CRC未被反射。两者都恰好以初始值零开始,但最后一个与0x55排除。您也可以反映所需的CRC定义,在这种情况下,移位方向会发生变化并且多项式会被翻转。如果您的CRC-8需要与其他软件互操作,那么您需要找出正在使用的CRC的完整定义。
  4. 传递指针似乎是一个奇怪的选择。直接传递和返回CRC值会更有效。例如。 unsigned crc8(unsigned crc, unsigned ch) {,它会将ch中的8位应用于CRC crc,并返回新值。请注意,您不需要将CRC值设为charunsigned通常是C例程最有效地作为参数和返回的东西。事实上,通常第一个参数在寄存器中传递并返回到同一个寄存器中。
  5. 通常在由一系列字节组成的消息上计算CRC。使用循环执行整个消息的例程会更有效,这样您就不需要检查是否已为消息的每个字节构建了表。