Arduino中的循环冗余校验 (CRC)


CRC 代表循环冗余校验 (Cyclic Redundancy Check)。简单来说,它是一种用于检测接收到的消息中错误的算法。其思想类似于奇偶校验,但它更加健壮。

如果发送器正在向接收器发送数据包,发送器将根据数据包上的一些多项式计算来计算 CRC 代码,并将其附加到数据包中。接收器将对数据包执行相同的计算,并检查生成的 CRC 是否与数据包中包含的 CRC 匹配。如果两者匹配,则传输中没有引入错误,并且可以安全地进一步处理数据包。如果不匹配,则接收到的数据包有错误,应将其丢弃。

CRC 的确切工作原理超出了本文的范围。有一些库可用于在 Arduino 中执行 CRC 计算。这里有一个示例。AVR 也有一个原生 CRC 库

示例

您可以随意探索这些库。但是,我们不会使用任何这些库。相反,我们将从头编写一个函数来返回字节数组的 16 位 CRC。该实现将使用 Fletcher 校验和。它非常健壮,甚至可以检测数据是否排序不正确。此外,该算法非常易于实现:

uint16_t checksumCalculator(uint8_t * data, uint16_t length)
{
   uint16_t curr_crc = 0x0000;
   uint8_t sum1 = (uint8_t) curr_crc;
   uint8_t sum2 = (uint8_t) (curr_crc >> 8);
   int index;
   for(index = 0; index < length; index = index+1)
   {
      sum1 = (sum1 + data[index]) % 255;
      sum2 = (sum2 + sum1) % 255;
   }
   return (sum2 << 8) | sum1;
}
void setup() {
   // put your setup code here, to run once:
   Serial.begin(9600);
   Serial.println();
   uint8_t buf[10] = {1,2,3,4,5,6,7,8,9,0};
   uint16_t crc = checksumCalculator(buf,10);
   Serial.print("Calculated CRC is: ");Serial.println(crc, HEX);
}
void loop() {
   // put your main code here, to run repeatedly:
}

输出

串口监视器输出为:

如您所见,我们使用了0x0000作为初始化值。您可以使用不同的初始值,前提是接收器和发送器都遵循相同的约定。

您将 sum1 初始化为初始值的低字节,将sum2初始化为高字节。然后,您继续将连续的数据字节添加到sum1中,并将sum1的值添加到sum2中,始终保持值小于 255(使用模运算符)。最后,您返回一个 16 位数字,其中sum2为高字节,sum1 为低字节。

更新于:2021年7月24日

4K+ 次浏览

开启您的职业生涯

完成课程获得认证

开始学习
广告