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

arduinohardwaresoftware & coding更新于 2026/1/12 11:37:17

CRC 代表循环冗余校验 (CRC)。简而言之,它是一种用于检测接收消息中错误的算法。其原理类似于奇偶校验,但前者更加稳健。

如果发送方正在向接收方发送数据包,发送方将基于数据包上的一些多项式计算来计算 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() {
   // 在此处放置设置代码,以便运行一次:
   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() {
   // 在此处放置主代码,以便重复运行:
}

输出

串行监视器输出为

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

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


相关文章