CRC循环冗余校验详解

本文主要介绍了CRC循环冗余校验的概念,包括手动计算、直观运算过程,并详细解析了一个CRC-4的C语言实现。通过在线计算网站分析了INIT、RefIn和RefOut参数的影响。同时提供了CRC数据预处理及结果处理的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

参考:
https://www.bilibili.com/video/BV1V4411Z7VA?from=search&seid=3373767585328853317&spm_id_from=333.337.0.0 [引用1]
这个视频里讲的很明了透彻,本文章前两节主要是对该视频内容做的笔记。

CRC循环冗余校验在线计算:http://www.ip33.com/crc.html [引用二]

https://blog.youkuaiyun.com/C_Silence_K/article/details/105791642?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163323676916780261969661%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=163323676916780261969661&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-2-105791642.first_rank_v2_pc_rank_v29&utm_term=crc%E5%88%9D%E5%A7%8B%E5%80%BC%E8%AF%A6%E7%BB%86%E8%A7%A3%E9%87%8A&spm=1018.2226.3001.4187 [引用三]
第三、四节以网上的CRC校验在线计算为例,进行详细分析和实现。

1、CRC手动演算

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、CRC的直观运算过程

在这里插入图片描述

3、在线计算网站界面各要素分析

在这里插入图片描述
在这里插入图片描述
INIT:这是算法开始时寄存器(crc)的初始化预置值,十六进制表示。 Init 的位数和多项式的位数相同,它的值为全0或者全F当全为0时,在算法开始前对数据(这个数据是根据RefIn的值得到的)后面补上CRC位数个0后就可以进行后续计算了。当全为1时,表示在算法开始前对数据的前CRC位数(高位)先和对应位数个1进行异或(即:前CRC位数的值按位取反),再在后面补上CRC位数个0,才进行后续计算。

RefIn为False表示,输入的原始数据的每个字节的第7位作为最高有效位,第0为作为最低有效位,即正常计算即可。
当RefIn为True时,输入的原始数据的每个字节需要做个逆序的处理,注意:针对的每个字节,而不是整个数据。
在这里插入图片描述
当Refout为False时,输出不做处理,当Refout为True,需要对输出数据做一次整个数据的逆序处理,注意:这里做的逆序和RefIn不同,它不是按字节逆序,而是整个逆序。
在这里插入图片描述参考自[引用三]

crc_4的代码实现

crc.h
#include <stdio.h>

#define DEBUG_CRC

uint8_t crc_4(uint32_t* pdata, uint32_t len);
uint8_t crc_8(uint32_t* pdata, uint32_t len);

enum CRC_NUM{
	CRC_DATA_FORMAT_ERROR = 0,
	
	CRC_SUCCESS
};
crc.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "crc.h"

uint32_t crc_polynomical_4[4] = {0,0,1,1};
uint32_t crc_polynomical_8[8] = {0,0,0,0,0,1,1,1};

uint8_t crc_4(uint32_t* pdata, uint32_t len){
	uint32_t i = 0,j = 0,k = 0,tmp = 0;
	uint8_t crc = 0;
	uint32_t crc_tmp[4] = {0};
	
	if((len-4) % 8 != 0) return CRC_DATA_FORMAT_ERROR;
#ifdef DEBUG_CRC
	printf("original bit stream:");
	for(i=0;i<len-4;i++){printf("%d ",pdata[i]);}
	printf("\n");
#endif
	for(i=0;i<(len-4)/8;i++){		/* reverse bit of input data in a byte */
		for(j=0;j<4;j++){
			tmp = pdata[i+j];
			pdata[i+j] = pdata[i+7-j];
			pdata[i+7-j] = tmp;
		}
	}
#ifdef DEBUG_CRC
	printf("reverse bit stream:");
	for(i=0;i<len-4;i++){printf("%d ",pdata[i]);}
	printf("\n");
#endif
	for (i=0;i<(len-4);i++)		/* crc calculate process */
	{
		if(pdata[i] == 1){
			for(j=i+1,k=0;j<=i+4,k<4;j++,k++){
				pdata[j] ^= crc_polynomical_4[k];
			}
		}
	}
	for(j=0;j<4;j++){		/* get result in byte */
		crc_tmp[j] = pdata[i+j];
	}
#ifdef DEBUG_CRC
	printf("original result:");
	for(j=0;j<4;j++){
		printf("%d ",crc_tmp[j]);
		if(j == 3) printf("\n");
	}
#endif
	for(i=0;i<2;i++){		/* reverse result,get final result */
		tmp = crc_tmp[i];
		crc_tmp[i] = crc_tmp[3-i];
		crc_tmp[3-i] = tmp;
	}
#ifdef DEBUG_CRC
	printf("reverse result:");
	for(j=0;j<4;j++){
		printf("%d ",crc_tmp[j]);
		if(j == 3) printf("\n");
	}
#endif
	return CRC_SUCCESS;
}

uint8_t crc_8(uint32_t* pdata, uint32_t len)
{
	
}
main.c
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
#include "crc.h"

/* mainly function */
uint8_t crc_original_data_analysize(char* data,uint32_t len,uint8_t* recv_data,uint32_t recv_len,uint32_t* real_len);
uint8_t crc_bit_int(uint8_t* bit_data,uint32_t bit_len,uint32_t* int_data,uint32_t int_len);

/* tool function */
uint8_t char2value_hex(char c){
	if(c >= '0' && c<= '9') return (c-'0');
	else if(c >= 'a' && c <= 'f') return (c-'a'+10);
	else if(c >= 'A' && c <= 'F') return (c-'A'+10);
	else return -1;
}

int main(){
	char crc_char[1024] = {0};
	uint8_t crc_data[1024] = {0};
	uint32_t real_len;
	uint32_t crc_int[1024*8] = {0};
	printf("Please input original data(hex):");
	scanf("%s",crc_char);
	crc_original_data_analysize(crc_char,strlen(crc_char),crc_data,1024,&real_len);
#ifdef DEBUG_CRC
	printf("the data(dec,previous length:%ld (char),real length:%d (uint8_t):",strlen(crc_char),real_len);
	for(uint32_t i=0;i<real_len;i++){
		printf("%02d ",crc_data[i]);
	}
	printf("\n");
#endif
	crc_bit_int(crc_data,real_len,crc_int,1024*8);
#ifdef DEBUG_CRC	
	printf("now every bit occupies a int:");
	for(uint32_t i=0;i<real_len * 8;i++){
		printf("%d ",crc_int[i]);	
	}
	printf("\n");
#endif
	/* '+4' mean that append four zero in the end,notice that real_len*8 must be smaller than 1024*8-4 */
	crc_4(crc_int,real_len*8+4);
	return 0;
}

uint8_t crc_original_data_analysize(char *data,uint32_t len,uint8_t* recv_data,uint32_t recv_len,uint32_t* real_len){
	uint32_t cnt=0,recv_cnt = 0;
	char data_tmp[2] = {0};
	uint8_t status = 0;
	if(recv_len < len) 
		return 1;
	while(cnt<len){
		if(data[cnt] == ' '){
			if(status == 0){cnt++;}
			else {return 2;}
		}
		else{
			if(status == 0){status = 1;data_tmp[0] = data[cnt];cnt++;continue;}
			if(status == 1){
				status = 0;
				data_tmp[1] = data[cnt];
				recv_data[recv_cnt] = char2value_hex(data_tmp[0])*16+char2value_hex(data_tmp[1]);
				cnt++;recv_cnt++;
			}
		}
	}
	*real_len = recv_cnt;
	return 0;
}

uint8_t crc_bit_int(uint8_t* bit_data,uint32_t bit_len,uint32_t* int_data,uint32_t int_len){
	if(int_len < bit_len*8) return 1;
	for(uint32_t i=0;i<bit_len;i++){
		for(uint32_t j=0;j<8;j++){
			int_data[i*8+j] |= (bit_data[i] >> (7-j)) & 0x01;
		}
	}
	return 0;
}

代码中我之所以把比特改为uint32_t类型进行处理,是因为4字节长度,现在的处理器更容易处理。
本来想把CRC-32的代码也写了,但是就是有点懒。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值