CRC校验核心原理
CRC(Cyclic Redundancy Check)通过对数据多项式进行模2除法,生成固定位数的校验码。以下是实现中的五个关键参数:
-
Poly:生成多项式(决定校验强度)
-
Init:初始寄存器值
-
Refin:输入字节位反转
-
Refout:输出结果位反转
-
Xorout:最终异或掩码
CRC-3 校验函数
CRC-3 (直接位操作版)
应用:嵌入式寄存器
参数:Poly=0x07, Init=根据参数定, Refin=false, Refout=false
/**
* @brief CRC-3校验(位操作实现)
* @param data 待校验数据(需左对齐到最高位)
* @param bitlen 数据位数(不是字节数)
* @param poly 生成多项式(实际值需左移1位,如x³+x+1=0b1011→0x03)
* @param crcinit 初始值(常用0x05或0x07)
* @return 3位CRC校验值
* @note 适用于硬件寄存器等需要逐位处理的场景
* @example
* unsigned long data = 0xB2000000; // 10110010...
* crc_3(data, 8, 0x03, 0x05); // 计算8位数据的CRC3
*/
unsigned long crc_3(unsigned long data, unsigned long bitlen,
unsigned char poly, unsigned char crcinit)
{
unsigned long crc = (crcinit == 0x05) ? 0x04 :
(crcinit == 0x07) ? 0x02 : 0x00;
while (bitlen--)
{
int bit = (crc >> 2) ^ (data >> 31);
crc = (crc << 1) & 0x07;
if (bit) crc ^= poly;
data <<= 1;
}
return crc;
}
CRC-3 (x³+x+1)
应用:短帧通信校验
参数:Poly=0x03, Init=0x05, Refin=false, Refout=false, Xorout=0x00
/**
* @brief CRC-3校验(字节流优化实现)
* @param data 数据指针(字节数组)
* @param length 数据长度(字节数)
* @return CRC值(仅低3位有效)
* @note
* - 多项式: x³ + x + 1 (0x03)
* - 初始值: 0x07
* - 输出不反转
* @example
* uint8_t data[] = {0x12, 0x34};
* uint8_t crc = crc3(data, 2); // 计算2字节CRC3
*/
unsigned char crc3(unsigned char* data, unsigned short int length)
{
unsigned char crc = 0x07;
while (length--) {
crc ^= *data++;
for (int i = 0; i < 8; i++)
{
crc = (crc & 0x80) ? (crc << 1) ^ 0x06 : (crc << 1);
}
}
return crc >> 5;
}
CRC-4 校验函数
CRC-4/ITU (x⁴+x+1)
应用:E1通信线路
参数:Poly=0x03, Init=0x00, Refin=true, Refout=true, Xorout=0x00
/**
* @brief CRC-4/ITU校验(x⁴ + x + 1)
* @param data 数据指针
* @param length 数据长度(字节数)
* @return CRC值(低4位有效)
* @note
* - 多项式: 0x03 (x⁴ + x + 1)
* - 初始值: 0x00
* - 输入/输出: 反转
* - 典型应用: ITU-T G.704标准
* @example
* uint8_t data[] = {0x12, 0x34};
* uint8_t crc = crc4_itu(data, 2); // 应返回0xC
*/
uint8_t crc4_itu(uint8_t *data, uint16_t length)
{
uint8_t crc = 0;
while(length--)
{
crc ^= *data++;
for(int i=0; i<8; i++)
{
if(crc & 1) crc = (crc >> 1) ^ 0x0C;
else crc >>= 1;
}
}
return crc & 0x0F;
}
CRC-5 校验函数
CRC-5/EPC (x⁵+x³+1)
应用:EPC电子标签
参数:Poly=0x09, Init=0x09, Refin=false, Refout=false, Xorout=0x00
/**
* @brief CRC-5/EPC校验(x⁵ + x³ + 1)
* @param data 数据指针
* @param length 数据长度(字节数)
* @return CRC值(低5位有效)
* @note
* - 多项式: 0x48(左对齐表示)
* - 初始值: 0x09
* - 典型应用: EPC Gen2 RFID标签
* @example
* uint8_t epc[] = {0x01, 0x23};
* uint8_t crc = crc5_epc(epc, 2);
*/
uint8_t crc5_epc(uint8_t *data, uint16_t length)
{
uint8_t crc = 0x48;
while(length--)
{
crc ^= *data++;
for(int i=0; i<8; i++)
{
crc = (crc & 0x80) ? (crc << 1) ^ 0x48 : (crc << 1);
}
}
return crc >> 3;
}
CRC-5/ITU (x⁵+x⁴+x²+1)
应用:USB接口设备
参数:Poly=0x15, Init=0x00, Refin=true, Refout=true, Xorout=0x00
/**
* @brief CRC-5/ITU校验(x⁵ + x⁴ + x² + 1)
* @param data 数据指针
* @param length 数据长度
* @return CRC值(低5位有效)
* @note
* - 多项式: 0x15
* - 初始值: 0x00
* - 输入/输出: 反转
*/
uint8_t crc5_itu(uint8_t *data, uint16_t length)
{
uint8_t crc = 0;
while(length--)
{
crc ^= *data++;
for(int i=0; i<8; i++)
{
if(crc & 1) crc = (crc >> 1) ^ 0x15;
else crc >>= 1;
}
}
return crc;
}
CRC-5/USB (x⁵+x²+1)
应用:USB协议数据包
参数:Poly=0x05, Init=0x1F, Refin=true, Refout=true, Xorout=0x1F
/**
* @brief CRC-5/USB校验(x⁵ + x² + 1)
* @param data 数据指针
* @param length 数据长度
* @return CRC值(低5位有效)
* @note
* - 多项式: 0x05
* - 初始值: 0x1F
* - 输出异或值: 0x1F
* - 典型应用: USB令牌包校验
*/
uint8_t crc5_usb(uint8_t *data, uint16_t length)
{
uint8_t crc = 0x1F;
while(length--)
{
crc ^= *data++;
for(int i=0; i<8; i++)
{
if(crc & 1) crc = (crc >> 1) ^ 0x14;
else crc >>= 1;
}
}
return crc ^ 0x1F;
}
CRC-6 校验函数
CRC-6/ITU (x⁶+x+1)
应用:电信控制信道
参数:Poly=0x03, Init=0x00, Refin=true, Refout=true, Xorout=0x00
/**
* @brief CRC-6/ITU校验(x⁶ + x + 1)
* @param data 数据指针
* @param length 数据长度
* @return CRC值(低6位有效)
* @note
* - 多项式: 0x03
* - 初始值: 0x00
* - 输入/输出: 反转
*/
uint8_t crc6_itu(uint8_t *data, uint16_t length)
{
uint8_t crc = 0;
while(length--)
{
crc ^= *data++;
for(int i=0; i<8; i++)
{
if(crc & 1) crc = (crc >> 1) ^ 0x30;
else crc >>= 1;
}
}
return crc;
}
CRC-7 校验函数
CRC-7/MMC (x⁷+x³+1)
应用:SD存储卡
参数:Poly=0x09, Init=0x00, Refin=false, Refout=false, Xorout=0x00
/**
* @brief CRC-7/MMC校验(x⁷ + x³ + 1)
* @param data 数据指针
* @param length 数据长度
* @return CRC值(低7位有效)
* @note
* - 多项式: 0x09
* - 初始值: 0x00
* - 典型应用: MMC/SD卡命令校验
* @example
* uint8_t cmd[] = {0x40, 0x00, 0x00, 0x00, 0x00};
* uint8_t crc = crc7_mmc(cmd, 5); // SD卡CMD0的CRC
*/
uint8_t crc7_mmc(uint8_t *data, uint16_t length)
{
uint8_t crc = 0;
while(length--)
{
crc ^= *data++;
for(int i=0; i<8; i++)
{
if(crc & 0x80) crc = (crc << 1) ^ 0x12;
else crc <<= 1;
}
}
return crc >> 1;
}
CRC-8 校验函数
CRC-8 (x⁸+x²+x+1)
应用:基础通信协议
参数:Poly=0x07, Init=0x00, Refin=false, Refout=false, Xorout=0x00
/**
* @brief 标准CRC8校验(x⁸ + x² + x + 1)
* @param data 数据指针
* @param length 数据长度
* @return CRC8值
* @note
* - 多项式: 0x07
* - 初始值: 0x00
*/
uint8_t crc8(uint8_t *data, uint16_t length)
{
uint8_t crc = 0;
while(length--)
{
crc ^= *data++;
for(int i=0; i<8; i++)
{
crc = (crc & 0x80) ? (crc << 1) ^ 0x07 : (crc << 1);
}
}
return crc;
}
CRC-8/ITU (x⁸+x²+x+1)
应用:ATM网络传输
参数:Poly=0x07, Init=0x00, Refin=false, Refout=false, Xorout=0x55
/**
* @brief CRC-8/ITU校验(x⁸ + x² + x + 1)
* @param data 数据指针
* @param length 数据长度
* @return CRC8值
* @note
* - 多项式: 0x07
* - 输出异或值: 0x55
* - 别名: CRC-8/ATM
*/
uint8_t crc8_itu(uint8_t *data, uint16_t length)
{
uint8_t crc = 0;
while(length--)
{
crc ^= *data++;
for(int i=0; i<8; i++)
{
crc = (crc & 0x80) ? (crc << 1) ^ 0x07 : (crc << 1);
}
}
return crc ^ 0x55;
}
CRC-8/ROHC (x⁸+x²+x+1)
应用:物联网设备
参数:Poly=0x07, Init=0xFF, Refin=true, Refout=true, Xorout=0x00
/**
* @brief CRC-8/ROHC校验(x⁸ + x² + x + 1)
* @param data 数据指针
* @param length 数据长度
* @return CRC8值
* @note
* - 多项式: 0x07
* - 初始值: 0xFF
* - 输入/输出: 反转
* - 典型应用: 实时传输协议头校验
*/
uint8_t crc8_rohc(uint8_t *data, uint16_t length)
{
uint8_t crc = 0xFF;
while(length--)
{
crc ^= *data++;
for(int i=0; i<8; i++)
{
if(crc & 1) crc = (crc >> 1) ^ 0xE0;
else crc >>= 1;
}
}
return crc;
}
CRC-8/MAXIM (x⁸+x⁵+x⁴+1)
应用:DS18B20传感器
参数:Poly=0x31, Init=0x00, Refin=true, Refout=true, Xorout=0x0
/**
* @brief CRC-8/MAXIM校验(x⁸ + x⁵ + x⁴ + 1)
* @param data 数据指针
* @param length 数据长度
* @return CRC8值
* @note
* - 多项式: 0x31
* - 初始值: 0x00
* - 输入/输出: 反转
* - 典型应用: DS18B20温度传感器
*/
uint8_t crc8_maxim(uint8_t *data, uint16_t length)
{
uint8_t crc = 0;
while(length--)
{
crc ^= *data++;
for(int i=0; i<8; i++)
{
if(crc & 1) crc = (crc >> 1) ^ 0x8C;
else crc >>= 1;
}
}
return crc;
}
CRC-16 校验函数
CRC-16/IBM (x¹⁶+x¹⁵+x²+1)
应用:文件压缩
参数:Poly=0x8005, Init=0x0000, Refin=true, Refout=true, Xorout=0x0000
/**
* @brief CRC-16/IBM校验(x¹⁶ + x¹⁵ + x² + 1)
* @param data 数据指针
* @param length 数据长度
* @return CRC16值
* @note
* - 多项式: 0x8005
* - 初始值: 0x0000
* - 输入/输出: 反转
* - 别名: CRC-16/ARC, CRC-16/LHA
*/
uint16_t crc16_ibm(uint8_t *data, uint16_t length)
{
uint16_t crc = 0;
while(length--)
{
crc ^= *data++;
for(int i=0; i<8; i++)
{
if(crc & 1) crc = (crc >> 1) ^ 0xA001;
else crc >>= 1;
}
}
return crc;
}
CRC-16/MAXIM (x¹⁶+x¹⁵+x²+1)
应用:工业传感器
参数:Poly=0x8005, Init=0x0000, Refin=true, Refout=true, Xorout=0xFFFF
/**
* @brief CRC-16/MAXIM校验(x¹⁶ + x¹⁵ + x² + 1)
* @param data 数据指针
* @param length 数据长度
* @return CRC16值
* @note
* - 输出异或值: 0xFFFF
* - 典型应用: Maxim 1-Wire总线
*/
uint16_t crc16_maxim(uint8_t *data, uint16_t length)
{
uint16_t crc = 0;
while(length--)
{
crc ^= *data++;
for(int i=0; i<8; i++)
{
if(crc & 1) crc = (crc >> 1) ^ 0xA001;
else crc >>= 1;
}
}
return ~crc;
}
CRC-16/USB (x¹⁶+x¹⁵+x²+1)
应用:USB协议栈
参数:Poly=0x8005, Init=0xFFFF, Refin=true, Refout=true, Xorout=0xFFFF
/**
* @brief CRC-16/USB校验(x¹⁶ + x¹⁵ + x² + 1)
* @param data 数据指针
* @param length 数据长度
* @return CRC16值
* @note
* - 初始值: 0xFFFF
* - 输出异或值: 0xFFFF
*/
uint16_t crc16_usb(uint8_t *data, uint16_t length)
{
uint16_t crc = 0xFFFF;
while(length--)
{
crc ^= *data++;
for(int i=0; i<8; i++)
{
if(crc & 1) crc = (crc >> 1) ^ 0xA001;
else crc >>= 1;
}
}
return ~crc;
}
CRC-16/MODBUS (x¹⁶+x¹⁵+x²+1)
应用:工业控制器
参数:Poly=0x8005, Init=0xFFFF, Refin=true, Refout=true, Xorout=0x0000
/**
* @brief CRC-16/MODBUS校验(x¹⁶ + x¹⁵ + x² + 1)
* @param data 数据指针
* @param length 数据长度
* @return CRC16值
* @note
* - 初始值: 0xFFFF
* - 输出异或值: 0x0000
* - 典型应用: Modbus RTU协议
* @example
* uint8_t frame[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x01};
* uint16_t crc = crc16_modbus(frame, 6); // 应返回0x840A
*/
uint16_t crc16_modbus(uint8_t *data, uint16_t length)
{
uint16_t crc = 0xFFFF;
while(length--)
{
crc ^= *data++;
for(int i=0; i<8; i++)
{
if(crc & 1) crc = (crc >> 1) ^ 0xA001;
else crc >>= 1;
}
}
return crc;
}
CRC-16/CCITT (x¹⁶+x¹²+x⁵+1)
应用:XMODEM协议
参数:Poly=0x1021, Init=0x0000, Refin=true, Refout=true, Xorout=0x0000
/**
* @brief CRC-16/CCITT校验(x¹⁶ + x¹² + x⁵ + 1)
* @param data 数据指针
* @param length 数据长度
* @return CRC16值
* @note
* - 多项式: 0x1021
* - 初始值: 0x0000
* - 别名: CRC-16/KERMIT
*/
uint16_t crc16_ccitt(uint8_t *data, uint16_t length)
{
uint16_t crc = 0;
while(length--)
{
crc ^= *data++;
for(int i=0; i<8; i++)
{
if(crc & 1) crc = (crc >> 1) ^ 0x8408;
else crc >>= 1;
}
}
return crc;
}
CRC-16/CCITT-FALSE (x¹⁶+x¹²+x⁵+1)
应用:5G通信
参数:Poly=0x1021, Init=0xFFFF, Refin=false, Refout=false, Xorout=0x0000
/**
* @brief CRC-16/CCITT-FALSE校验
* @param data 数据指针
* @param length 数据长度
* @return CRC16值
* @note
* - 初始值: 0xFFFF
* - 输入/输出: 不反转
* - 典型应用: Modbus ASCII协议
*/
uint16_t crc16_ccitt_false(uint8_t *data, uint16_t length)
{
uint16_t crc = 0xFFFF;
while(length--)
{
crc ^= (uint16_t)(*data++) << 8;
for(int i=0; i<8; i++)
{
if(crc & 0x8000) crc = (crc << 1) ^ 0x1021;
else crc <<= 1;
}
}
return crc;
}
CRC-16/X25 (x¹⁶+x¹²+x⁵+1)
应用:智能电表
参数:Poly=0x1021, Init=0xFFFF, Refin=true, Refout=true, Xorout=0xFFFF
/**
* @brief CRC-16/X25校验(x¹⁶ + x¹² + x⁵ + 1)
* @param data 数据指针
* @param length 数据长度
* @return CRC16值
* @note
* - 初始值: 0xFFFF
* - 输出异或值: 0xFFFF
* - 典型应用: X.25协议帧校验
*/
uint16_t crc16_x25(uint8_t *data, uint16_t length)
{
uint16_t crc = 0xFFFF;
while(length--)
{
crc ^= *data++;
for(int i=0; i<8; i++)
{
if(crc & 1) crc = (crc >> 1) ^ 0x8408;
else crc >>= 1;
}
}
return ~crc;
}
CRC-16/XMODEM (x¹⁶+x¹²+x⁵+1)
应用:卫星通信
参数:Poly=0x1021, Init=0x0000, Refin=false, Refout=false, Xorout=0x0000
/**
* @brief CRC-16/XMODEM校验(x¹⁶ + x¹² + x⁵ + 1)
* @param data 数据指针
* @param length 数据长度
* @return CRC16值
* @note
* - 初始值: 0x0000
* - 输入/输出: 不反转
* - 别名: CRC-16/ZMODEM
*/
uint16_t crc16_xmodem(uint8_t *data, uint16_t length)
{
uint16_t crc = 0;
while(length--)
{
crc ^= (uint16_t)(*data++) << 8;
for(int i=0; i<8; i++)
{
if(crc & 0x8000) crc = (crc << 1) ^ 0x1021;
else crc <<= 1;
}
}
return crc;
}
CRC-16/DNP(x¹⁶+x¹³+x¹²+x¹¹+x¹⁰+x⁸+x⁶+x⁵+x²+1)
应用:电网通信
参数:Poly=0x3D65, Init=0x0000, Refin=true, Refout=true, Xorout=0xFFFF
/**
* @brief CRC-16/DNP校验(x¹⁶ + x¹³ + x¹² + x¹¹ + x¹⁰ + x⁸ + x⁶ + x⁵ + x² + 1)
* @param data 数据指针
* @param length 数据长度
* @return CRC16值
* @note
* - 多项式: 0x3D65
* - 输出异或值: 0xFFFF
* - 典型应用: DNP3协议
*/
uint16_t crc16_dnp(uint8_t *data, uint16_t length)
{
uint16_t crc = 0;
while(length--)
{
crc ^= *data++;
for(int i=0; i<8; i++)
{
if(crc & 1) crc = (crc >> 1) ^ 0xA6BC;
else crc >>= 1;
}
}
return ~crc;
}
CRC-32 校验函数
CRC-32 (x³²+x²⁶+...+1)
应用:ZIP/RAR压缩
参数:Poly=0x04C11DB7, Init=0xFFFFFFFF, Refin=true, Refout=true, Xorout=0xFFFFFFFF
/**
* @brief CRC-32校验(x³² + x²⁶ + ... + 1)
* @param data 数据指针
* @param length 数据长度
* @return CRC32值
* @note
* - 多项式: 0x04C11DB7
* - 初始值: 0xFFFFFFFF
* - 输出异或值: 0xFFFFFFFF
* - 典型应用: ZIP/RAR/以太网帧校验
* @example
* uint8_t data[] = "123456789";
* uint32_t crc = crc32(data, 9); // 应返回0xCBF43926
*/
uint32_t crc32(uint8_t *data, uint16_t length)
{
uint32_t crc = 0xFFFFFFFF;
while(length--)
{
crc ^= *data++;
for(int i=0; i<8; i++)
{
if(crc & 1) crc = (crc >> 1) ^ 0xEDB88320;
else crc >>= 1;
}
}
return ~crc;
}
CRC-32/MPEG-2 (x³²+x²⁶+...+1)
应用:数字电视
参数:Poly=0x04C11DB7, Init=0xFFFFFFFF, Refin=false, Refout=false, Xorout=0x00000000
/**
* @brief CRC-32/MPEG-2校验
* @param data 数据指针
* @param length 数据长度
* @return CRC32值
* @note
* - 输入/输出: 不反转
* - 典型应用: MPEG-2传输流
*/
uint32_t crc32_mpeg_2(uint8_t *data, uint16_t length)
{
uint32_t crc = 0xFFFFFFFF;
while(length--)
{
crc ^= (uint32_t)(*data++) << 24;
for(int i=0; i<8; i++)
{
if(crc & 0x80000000) crc = (crc << 1) ^ 0x04C11DB7;
else crc <<= 1;
}
}
return crc;
}
关注微信公众号「芯动视界」,解锁代码世界的核心奥秘!获取更多资料!
🔧 深耕C语言精髓:从指针迷宫到内存管理,系统化讲解,助你夯实底层基础。
⚡️ 探索嵌入式实战:剖析项目案例,分享避坑指南,让开发效率翻倍。
无论你是初无论你是初探嵌入式的新手,还是寻求进阶的老兵,这里都有你需要的硬核干货与技术洞见。一起用代码“芯”动视界!