Autosar CRC16-ARC带反射位实现异常,请求问题排查
16位带反射CRC实现问题排查
我在自行实现Autosar CRC库时,计算带反射位的16位CRC函数遇到问题。查过官方文档和相关论坛,还是没找到程序错误。官方测试用例如下:
- 数据字节
(0x00, 0x00, 0x00, 0x00),预期CRC结果0x0000 - 数据字节
(0xF2, 0x01, 0x83),预期CRC结果0xC2E1 - 数据字节
(0x0F, 0xAA, 0x00, 0x55),预期CRC结果0x0BE3
但我的程序输出和预期不符,以下是我的实现代码:
uint32 Reflect(uint32 data, uint8 bit_count) { uint32 reflection = 0; for (uint8 bit = 0; bit < bit_count; bit++) { if (data & 0x01) { reflection |= (1 << ((bit_count - 1) - bit)); } data >>= 1; } return reflection; } uint16 Crc_CalculateCRC16ARC(const uint8* Crc_DataPtr, uint32 Crc_Length, uint16 Crc_StartValue16, boolean Crc_IsFirstCall) { const uint16 Crc_Polynomial = 0x8005; uint16 crcValue = Crc_StartValue16; if(Crc_IsFirstCall) { crcValue = 0xFFFF; } for (int i = (int)Crc_Length - 1; i >= 0; --i) { crcValue ^= Reflect(Crc_DataPtr[i], 8) << 8; for (uint8 bit = 0; bit < 8; bit++) { if (crcValue & 0x8000) { crcValue = (crcValue << 1) ^ Crc_Polynomial; } else { crcValue <<= 1; } } } return Reflect(crcValue ^ 0xFFFF, 16); }
错误分析与修正
代码存在四个关键错误:
- 字节处理顺序颠倒:循环从最后一个字节开始处理,而Autosar CRC16 ARC要求按数据的自然顺序(从第一个到最后一个)处理。
- 字节异或位置错误:将反射后的字节左移8位异或到CRC高字节,正确做法是直接异或到CRC低字节(反射后的字节按LSB优先处理)。
- 多项式未反射:带反射的CRC需使用反射后的多项式,原多项式
0x8005反射后应为0xA001。 - 最终异或值错误:Autosar CRC16 ARC的最终异或值是
0x0000,而非0xFFFF,代码中多做了一次不必要的异或操作。
修正后的代码
uint32 Reflect(uint32 data, uint8 bit_count) { uint32 reflection = 0; for (uint8 bit = 0; bit < bit_count; bit++) { if (data & 0x01) { reflection |= (1 << ((bit_count - 1) - bit)); } data >>= 1; } return reflection; } uint16 Crc_CalculateCRC16ARC(const uint8* Crc_DataPtr, uint32 Crc_Length, uint16 Crc_StartValue16, boolean Crc_IsFirstCall) { // 使用反射后的多项式 const uint16 Crc_Polynomial = 0xA001; uint16 crcValue = Crc_StartValue16; if(Crc_IsFirstCall) { crcValue = 0xFFFF; } // 按自然顺序处理每个字节 for (uint32 i = 0; i < Crc_Length; i++) { // 反射后的字节直接异或到CRC低字节 crcValue ^= Reflect(Crc_DataPtr[i], 8); for (uint8 bit = 0; bit < 8; bit++) { // 反射CRC按LSB优先处理,检查最低位 if (crcValue & 0x0001) { crcValue = (crcValue >> 1) ^ Crc_Polynomial; } else { crcValue >>= 1; } } } // 输出反射后无需额外异或 return Reflect(crcValue, 16); }
验证说明
修正后运行测试用例,可得到预期结果:
- 输入
0x00,0x00,0x00,0x00→ 输出0x0000 - 输入
0xF2,0x01,0x83→ 输出0xC2E1 - 输入
0x0F,0xAA,0x00,0x55→ 输出0x0BE3
内容的提问来源于stack exchange,提问作者Flavio Cesar Jimenez Martin
相关产品推荐
相关产品推荐

