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

CRC lookup table generated in C always gives different results

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

我只在"main"函数中添加

#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 值。

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

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

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