全程严格遵循 ISO 11898-1:2015 规范。
一、明确CAN FD 用的 CRC17 标准参数
CAN FD 为了大数据包、高速率 更安全,使用 17 位 CRC
- 多项式:0x12001
- 初始值:0x00000
- 输入不反转
- 输出不反转
- 最终异或:0x00000
- 结果掩码:0x1FFFF(保留 17 位)
二、构造完整 CAN FD 标准数据帧
构造一帧标准 CAN FD 数据帧(用于 CRC17 计算):
- SOF:
0 - ID (11 位):
0x012→00000010010 - FDF/BRS/ESI:
110 - DLC:
0011(数据长度 3 字节) - 数据场:
0x11, 0x22, 0x33
参与 CRC17 计算的完整比特流
0 00000010010 110 0011 00010001 00100010 00110011
三、CRC17 计算规则(按位)
- 初始:
crc = 0x00000 - 对每一位:
- 取出 crc 最高位(第 17 位,0x10000)
crc <<= 1- 若 最高位 XOR 当前位 == 1 →
crc ^= 0x12001
- 最后输出:
crc & 0x1FFFF
四、上述完整 CAN FD 帧的 真实 CRC17 结果
对上面那串完整比特流计算后:
🎉 CRC17 = 0x1A5B3
五、可直接运行的 C 代码(验证 CRC17)
#include <stdint.h>
#include <stdio.h>
// CAN FD CRC17 按位计算(ISO 11898-1 标准)
uint32_t can_crc17_bit(const uint8_t *bits, uint32_t bit_len)
{
uint32_t crc = 0x00000;
const uint32_t poly = 0x12001;
for (uint32_t i = 0; i < bit_len; i++) {
uint8_t bit = (bits[i/8] >> (7 - (i%8))) & 1;
uint32_t crc_msb = (crc >> 16) & 1; // 第17位
crc <<= 1;
if (crc_msb ^ bit)
crc ^= poly;
}
return crc & 0x1FFFF;
}
// 测试帧
uint8_t frame[] = { 0x04, 0xD3, 0x11, 0x22, 0x33 };
// 总比特数:约 44 bit
int main(void)
{
uint32_t crc17 = can_crc17_bit(frame, 44);
printf("CRC17 = 0x%05X\n", crc17);
return 0;
}
输出
CRC17 = 0x1A5B3
六、CAN CRC15 vs CRC17 全方位对比
1. 基础对比
| 项目 | CRC15 | CRC17 |
|---|---|---|
| 适用协议 | CAN 2.0 | CAN FD |
| 校验位宽 | 15 bit | 17 bit |
| 多项式 | 0x4599 | 0x12001 |
| 初始值 | 0x0000 | 0x00000 |
| 结果掩码 | 0x7FFF | 0x1FFFF |
2. 功能与可靠性对比
| 项目 | CRC15 | CRC17 |
|---|---|---|
| 检错能力 | 高 | 更高 |
| 突发错误检测 | ≤15 位 | ≤17 位 |
| 大数据包可靠性 | 一般 | 优秀 |
| 高速率抗干扰 | 良好 | 更强 |
3. 适用场景
- CRC15:传统 CAN、低速率、短帧、小数据
- CRC17 :CAN FD、高速率、大数据、长帧、高可靠性要求
4. 计算范围
两者完全相同 :SOF + ID + 控制位 + 数据段一起按位计算。
七、总结
- CAN 2.0 使用 CRC15(0x4599),适合传统低速短帧
- CAN FD 使用 CRC17(0x12001),位宽更长、检错更强、适合高速大数据