CRC16查表法校验异常:追加校验值后计算结果非0
CRC16查表法校验结果不为0的问题排查
问题描述
已实现基于查表法的CRC16算法(多项式0xA001),执行以下操作后预期校验值为0,但实际结果不符:
- 创建测试数组
data[6] = {0x10,0x20,0x30,0x40,0,0},取前4字节以初始值0xFFFF计算CRC,存入变量crc - 将
crc追加到数组末尾,再用整个数组计算新的校验值crc_2,预期crc_2为0
代码中的错误点
1. CRC值拷贝错误
代码中误用memcpy((void*)&data[4], (void*)&crc_2, 2);,但crc_2初始值为0,实际应该拷贝的是计算得到的crc变量,正确写法:
memcpy((void*)&data[4], (void*)&crc, 2);
2. 第二次CRC计算的初始值错误
第二次计算时,应使用和第一次相同的初始值0xFFFF,而非传入之前得到的crc。CRC校验的标准逻辑是:原始数据+CRC校验码,用标准初始值计算,结果应为0。因此第二次调用应改为:
crc_2 = fast_crc16(0XFFFF, data, 6);
修正后的完整代码
#include <stdio.h> #include <string.h> #include <stdint.h> uint16_t crc16_tab[256] = { 0x0000, 0xA001, 0xE003, 0x4002, 0x6007, 0xC006, 0x8004, 0x2005, 0xC00E, 0x600F, 0x200D, 0x800C, 0xA009, 0x0008, 0x400A, 0xE00B, 0x201D, 0x801C, 0xC01E, 0x601F, 0x401A, 0xE01B, 0xA019, 0x0018, 0xE013, 0x4012, 0x0010, 0xA011, 0x8014, 0x2015, 0x6017, 0xC016, 0x403A, 0xE03B, 0xA039, 0x0038, 0x203D, 0x803C, 0xC03E, 0x603F, 0x8034, 0x2035, 0x6037, 0xC036, 0xE033, 0x4032, 0x0030, 0xA031, 0x6027, 0xC026, 0x8024, 0x2025, 0x0020, 0xA021, 0xE023, 0x4022, 0xA029, 0x0028, 0x402A, 0xE02B, 0xC02E, 0x602F, 0x202D, 0x802C, 0x8074, 0x2075, 0x6077, 0xC076, 0xE073, 0x4072, 0x0070, 0xA071, 0x407A, 0xE07B, 0xA079, 0x0078, 0x207D, 0x807C, 0xC07E, 0x607F, 0xA069, 0x0068, 0x406A, 0xE06B, 0xC06E, 0x606F, 0x206D, 0x806C, 0x6067, 0xC066, 0x8064, 0x2065, 0x0060, 0xA061, 0xE063, 0x4062, 0xC04E, 0x604F, 0x204D, 0x804C, 0xA049, 0x0048, 0x404A, 0xE04B, 0x0040, 0xA041, 0xE043, 0x4042, 0x6047, 0xC046, 0x8044, 0x2045, 0xE053, 0x4052, 0x0050, 0xA051, 0x8054, 0x2055, 0x6057, 0xC056, 0x205D, 0x805C, 0xC05E, 0x605F, 0x405A, 0xE05B, 0xA059, 0x0058, 0xA0E9, 0x00E8, 0x40EA, 0xE0EB, 0xC0EE, 0x60EF, 0x20ED, 0x80EC, 0x60E7, 0xC0E6, 0x80E4, 0x20E5, 0x00E0, 0xA0E1, 0xE0E3, 0x40E2, 0x80F4, 0x20F5, 0x60F7, 0xC0F6, 0xE0F3, 0x40F2, 0x00F0, 0xA0F1, 0x40FA, 0xE0FB, 0xA0F9, 0x00F8, 0x20FD, 0x80FC, 0xC0FE, 0x60FF, 0xE0D3, 0x40D2, 0x00D0, 0xA0D1, 0x80D4, 0x20D5, 0x60D7, 0xC0D6, 0x20DD, 0x80DC, 0xC0DE, 0x60DF, 0x40DA, 0xE0DB, 0xA0D9, 0x00D8, 0xC0CE, 0x60CF, 0x20CD, 0x80CC, 0xA0C9, 0x00C8, 0x40CA, 0xE0CB, 0x00C0, 0xA0C1, 0xE0C3, 0x40C2, 0x60C7, 0xC0C6, 0x80C4, 0x20C5, 0x209D, 0x809C, 0xC09E, 0x609F, 0x409A, 0xE09B, 0xA099, 0x0098, 0xE093, 0x4092, 0x0090, 0xA091, 0x8094, 0x2095, 0x6097, 0xC096, 0x0080, 0xA081, 0xE083, 0x4082, 0x6087, 0xC086, 0x8084, 0x2085, 0xC08E, 0x608F, 0x208D, 0x808C, 0xA089, 0x0088, 0x408A, 0xE08B, 0x60A7, 0xC0A6, 0x80A4, 0x20A5, 0x00A0, 0xA0A1, 0xE0A3, 0x40A2, 0xA0A9, 0x00A8, 0x40AA, 0xE0AB, 0xC0AE, 0x60AF, 0x20AD, 0x80AC, 0x40BA, 0xE0BB, 0xA0B9, 0x00B8, 0x20BD, 0x80BC, 0xC0BE, 0x60BF, 0x80B4, 0x20B5, 0x60B7, 0xC0B6, 0xE0B3, 0x40B2, 0x00B0, 0xA0B1 }; uint16_t fast_crc16(uint16_t crc,uint8_t* buffer, uint32_t len) { while (len--) { crc = crc16_tab[(crc >> 8) ^ *buffer++] ^ (crc << 8); } return (crc); } int main() { /*DUMMY MESSAGE*/ uint8_t data[6] = {0x10,0x20, 0X30,0X40,0,0}; uint16_t crc = 0; uint16_t crc_2 = 0; /*FIRST CRC*/ crc = fast_crc16(0XFFFF,data, 4); /*COPY CRC INTO DATA - 修正:拷贝crc变量而非crc_2*/ memcpy((void*)&data[4], (void*)&crc, 2); /*SECOND CRC - 修正:使用初始值0xFFFF而非crc*/ crc_2 = fast_crc16(0XFFFF,data, 6); printf("%x\n", crc_2); // 此时输出应为0 return 0; }
验证说明
修正后,第一次计算前4字节得到的CRC会被正确追加到数组末尾,第二次用初始值0xFFFF计算整个6字节数据,结果将为0,符合CRC校验的预期逻辑。
内容的提问来源于stack exchange,提问作者Filippo_Col
相关产品推荐
相关产品推荐

