前言:
眼前咱们对“crc检验算法”大概比较关心,看官们都想要了解一些“crc检验算法”的相关资讯。那么小编同时在网络上汇集了一些对于“crc检验算法””的相关知识,希望看官们能喜欢,看官们一起来了解一下吧!循环冗余校验(Cyclic Redundancy Check,简写CRC),是一种常用的、检错能力相当强的校验算法。
本文不详细介绍CRC算法的理论,直接给出计算结果为2个字节的计算流程及实现代码。
计算流程
定义一个16位无符号类型的变量,并初始化为0xFFFF,称之为CRC变量;把数据包中的第一个字节与CRC变量中的低字节进行异或运算,结果存回CRC变量;将CRC变量向右移一位,最高位填以0,最低位移出并检测;如果最低位为0:重复第3步(进行下一次移位);如果最低位为1:将CRC变量与固定值0xA001进行异或运算;重复第3步和第4步直到8次移位,这样就完成了对数据包中第一个字节的处理;重复第2步到第5步来处理数据包中的下一个字节,直到数据包中所有的字节都处理完;最终CRC变量的值就是CRC的值。
用C语言实现
/* 代码片段,摘自:plat_lib.c *//****************************************************************************** * @fn uint16_t calc_crc16(uint8_t const *p_data, int32_t data_len) * * @brief 计算16位的crc校验码 * * @param p_data 待校验数据的首地址 * @param data_len 数据长度 * * @return CRC value, 0x0000 ~ 0xFFFF */uint16_t calc_crc16(uint8_t const *p_data, int32_t data_len){ int32_t i; uint16_t crc_value = 0xFFFF; /* 定义一个16位无符号类型的变量,并初始化为0xFFFF */ while (data_len--) { /* 数据包中的字节与CRC变量中的低字节进行异或运算,结果存回CRC变量 */ crc_value ^= *p_data++; for (i = 0; i < 8; i++) { if (crc_value & 0x0001) { /* 如果最低位为1:将CRC变量与固定值0xA001进行异或运算 */ crc_value = (crc_value >> 1) ^ 0xA001; } else { /* 如果最低位为0:重复第3步(配合计算流程来阅读代码) */ crc_value >>= 1; } } } /* 最终CRC变量的值就是CRC的值 */ return crc_value;}
测试代码:
/* 代码片段,摘自:test.c *//****************************************************************************** * @fn int main(int argc, char * argv[]) * * @brief 主函数 * * @param argc 命令函传入的参数数量 * @param argv 命令行传入的参数字符串数组 * * @return 0 */int main(int argc, char * argv[]){ uint8_t user_data1[] = {0x01, 0x02, 0x03, 0x04, 0x05}; uint8_t user_data2[] = {0x01, 0x03, 0x02, 0x04, 0x05}; uint16_t crc1, crc2; crc1 = calc_crc16(user_data1, sizeof(user_data1)); crc2 = calc_crc16(user_data2, sizeof(user_data2)); log_debug("crc1 = %04X, crc2 = %04X\n", crc1, crc2); return 0;}
Makefile
TARGET = testSOURCE := $(wildcard *.c) $(wildcard *.cpp)OBJS := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE)))$(TARGET): $(OBJS) gcc -o $@ $(OBJS)clean: rm -rf *.o $(TARGET)
测试结果
// 编译[root@localhost checksum]# makecc -c -o protocol.o protocol.ccc -c -o plat_lib.o plat_lib.ccc -c -o plat_log.o plat_log.ccc -c -o test.o test.cgcc -o test protocol.o plat_lib.o plat_log.o test.o// 运行测试程序[root@localhost checksum]# ./testcrc1 = BB2A, crc2 = 877A
优缺点
CRC算法比校验和算法复杂,计算过程会占用较多的计算机资源(比如CPU资源),其优点是检错能力强,举例说明如下,有2份元数据,如下:
虽然只是有2个字节的数据交换了一下位置,但得到了不同的CRC校验码,这是校验和算法或一些其他简单算法做不到的。
补充:
通信协议中,CRC校验码通常按如下方式使用:CRC校验码由发送方计算出来,然后附加到数据包中,接收方在接收数据时以同样的算法重新计算CRC值,然后与接收到的CRC校验码进行比较,如果这两个值不相等,就说明数据传输过程中出现了错误,数据不可靠,直接丢弃不做处理。
标签: #crc检验算法