2. CRC24Q 校验算法实现
任务说明
RTCM 3.x 报文以 8 位十六进制前缀 D3 开头,随后是 6 位保留位与 10 位报文长度,最后附加 3 字节 CRC24Q 校验值。本案例实现 CRC24Q 的完整计算与验证函数,并给出可直接运行的测试入口,确保任意 RTCM 3.x 报文(含前缀与长度字段)能够正确生成和校验 CRC。
CRC24Q 算法定义
CRC24Q 采用生成多项式 0x1864CFB(即 x^24 + x^23 + x^18 + x^17 + x^14 + x^11 + x^10 + x^7 + x^6 + x^5 + x^4 + x^3 + x + 1),初始值为 0x000000,输入数据按位处理,不进行反射,输出不异或。RTCM 标准规定 CRC 覆盖从报文前缀 D3 开始到长度字段结束的所有字节,校验值以大端序追加在报文末尾。
核心代码实现
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
#define CRC24Q_INIT 0x000000u
#define CRC24Q_POLY 0x1864CFBu
#define CRC24Q_MASK 0xFFFFFFu
/* 计算 CRC24Q:data 指向报文起始字节(含 0xD3 前缀),len 为参与校验的字节数 */
uint32_t crc24q_compute(const uint8_t *data, size_t len) {
uint32_t crc = CRC24Q_INIT;
for (size_t i = 0; i < len; i++) {
crc ^= ((uint32_t)data[i]) << 16;
for (int bit = 0; bit < 8; bit++) {
crc <<= 1;
if (crc & 0x1000000u) {
crc ^= CRC24Q_POLY;
}
}
}
return crc & CRC24Q_MASK;
}
/* 验证 CRC:data 指向含 CRC 的完整报文,payload_len 为不含 CRC 的字节数 */
int crc24q_verify(const uint8_t *data, size_t payload_len) {
uint32_t calc = crc24q_compute(data, payload_len);
uint32_t recv = ((uint32_t)data[payload_len] << 16) |
((uint32_t)data[payload_len + 1] << 8) |
((uint32_t)data[payload_len + 2]);
return (calc == recv) ? 1 : 0;
}
/* 测试用例:RTCM 3.x 标准示例帧(来自 RTCM 标准文档) */
int main(void) {
/* 帧内容:D3 00 06 44 6B 01 9C 3C 0F,其中前 6 字节为报文头+长度,后 3 字节为 CRC */
uint8_t frame[] = {0xD3, 0x00, 0x06, 0x44, 0x6B, 0x01, 0x9C, 0x3C, 0x0F};
size_t header_len = 6; /* 前缀(1) + 保留/长度(2) + 消息体(3) = 6 字节参与 CRC */
uint32_t crc = crc24q_compute(frame, header_len);
printf("计算 CRC: %06X\n", crc);
printf("预期 CRC: 9C3C0F\n");
if (crc == 0x9C3C0F) {
printf("CRC 计算正确\n");
} else {
printf("CRC 计算错误\n");
return 1;
}
if (crc24q_verify(frame, header_len)) {
printf("CRC 校验通过\n");
} else {
printf("CRC 校验失败\n");
return 1;
}
return 0;
}
代码说明
crc24q_compute 函数逐字节处理输入数据,每字节通过 8 次移位与异或完成位级运算。CRC 寄存器为 32 位,但仅低 24 位有效,溢出位 0x1000000 用于判断是否需要与生成多项式异或。最终返回值掩去高 8 位,得到标准 24 位 CRC。crc24q_verify 函数先对不含 CRC 的报文部分重新计算,再与报文末尾 3 字节(大端序)比较,返回 1 表示匹配。
编译与运行
gcc -o crc24q crc24q.c
./crc24q
验证方法
测试帧 D3 00 06 44 6B 01 9C 3C 0F 取自 RTCM 标准参考数据,其中前 6 字节参与 CRC 计算,后 3 字节为已知正确校验值。程序输出应显示计算 CRC 为 9C3C0F,与预期一致,并打印“CRC 计算正确”与“CRC 校验通过”。若输出不符,说明实现存在位序或多项式错误。
判定标准
程序退出码为 0 且控制台输出包含“CRC 计算正确”和“CRC 校验通过”即视为实现正确。该测试向量覆盖了前缀字节 D3、长度字段与消息体组合的 CRC 计算,可验证位处理顺序与多项式是否正确。