CRC校验原理及代码

部署运行你感兴趣的模型镜像

 参考:CRC校验原理及步骤https://blog.youkuaiyun.com/d_leo/article/details/73572373

什么是CRC校验?

CRC即循环冗余校验码:是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定。循环冗余检查(CRC)是一种数据传输检错功能,对数据进行多项式计算,并将得到的结果附在帧的后面,接收设备也执行类似的算法,以保证数据传输的正确性和完整性。

 

CRC校验原理:

其根本思想就是先在要发送的帧后面附加一个数(这个就是用来校验的校验码,但要注意,这里的数也是二进制序列的,下同),生成一个新帧发送给接收端。当然,这个附加的数不是随意的,它要使所生成的新帧能与发送端和接收端共同选定的某个特定数整除(注意,这里不是直接采用二进制除法,而是采用一种称之为“模2除法”)。到达接收端后,再把接收到的新帧除以(同样采用“模2除法”)这个选定的除数。因为在发送端发送数据帧之前就已通过附加一个数,做了“去余”处理(也就已经能整除了),所以结果应该是没有余数。如果有余数,则表明该帧在传输过程中出现了差错。

模2除法:

模2除法与算术除法类似,但每一位除的结果不影响其它位,即不向上一位借位,所以实际上就是异或。在循环冗余校验码(CRC)的计算中有应用到模2除法。

例:

CRC校验码计算示例:

现假设选择的CRC生成多项式为G(X) = X4 + X3 + 1,要求出二进制序列10110011的CRC校验码。下面是具体的计算过程:

①将多项式转化为二进制序列,由G(X) = X4 + X3 + 1可知二进制一种有五位,第4位、第三位和第零位分别为1,则序列为11001

②多项式的位数位5,则在数据帧的后面加上5-1位0,数据帧变为101100110000,然后使用模2除法除以除数11001,得到余数。

③将计算出来的CRC校验码添加在原始帧的后面,真正的数据帧为101100110100,再把这个数据帧发送到接收端。

④接收端收到数据帧后,用上面选定的除数,用模2除法除去,验证余数是否为0,如果为0,则说明数据帧没有出错。

CRC校验电路原理图

 对应的并行CRC代码

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    14:18:49 08/14/2018 
// Design Name: 
// Module Name:    crc16-papa 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module crc16papa (reset, gclk, soc, data_in, crc_out);
input reset,gclk,soc;
input [7:0] data_in;
output reg [15:0] crc_out;
reg temp;
reg [15:0] crc_temp;
parameter delay = 1'b1;
integer i,j,k,l;
//产生crc_out
always @(posedge gclk or negedge reset)
    begin
		if (!reset)
			crc_out <= #delay 16'b0;
		else if (soc)
			crc_out <= #delay 16'b0;
		else
			crc_out <= #delay crc_temp;
	end
//产生crc_temp
always @(crc_out or data_in)
	begin
		crc_temp = crc_out;
		for (i=7;i>=0;i=i-1)
			begin
				temp = data_in[i] ^crc_temp[15];
				for (j=15; j>12; j=j-1)
					crc_temp[j] = crc_temp[j-1];
				crc_temp[12] = temp ^ crc_temp[11];
				for (k=11; k>5; k=k-1)
					crc_temp[k] = crc_temp[k-1];
				crc_temp[5] = temp ^ crc_temp[4];
				for (l=4; l>0; l=l-1)
					crc_temp[l] = crc_temp[l-1];
				crc_temp[0] = temp;
		end
	end
endmodule	

 

 

 

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

<think>我们被要求解释GD32F系列单片机的CRC校验原理并提供代码示例。根据引用[1][2][3]的上下文,虽然它们主要讨论BootLoader、CAN总线和IAP编程,但我们可以推断GD32F的CRC模块与其他单片机类似。CRC(循环冗余校验)是一种错误检测机制,常用于通信和数据存储验证。###CRC校验原理CRC基于多项式除法,其核心是将数据视为多项式系数,然后用一个预设的生成多项式去除,得到的余数即为CRC值。GD32F系列通常提供硬件CRC计算单元,支持以下特性:-**固定生成多项式**:GD32F通常采用CRC-32(以太网标准)或CRC-16-CCITT等,具体取决于型号(需查阅数据手册确认)。-**输入输出反转**:可配置输入数据位序(如字节反转)和输出结果反转。-**初始值**:计算前可设置CRC寄存器的初始值(非零初始值可避免全零数据的CRC为零)。数学表达式:设数据多项式为$M(x)$,生成多项式为$G(x)$(阶次$r$),则CRC值为:$$\text{CRC}=(M(x)\cdotx^r)\modG(x)$$###GD32FCRC模块操作流程1.**使能CRC时钟**:通过RCU模块启用CRC外设时钟。2.**配置CRC**(可选):设置初始值、输入输出反转等(GD32F默认可能为CRC-32)。3.**写入数据**:将数据按字(32位)或字节写入CRC数据寄存器(`CRC_DATA`)。4.**读取结果**:计算完成后从`CRC_DATA`寄存器读取CRC值。###代码示例以下代码以GD32F4xx系列为例(假设使用默认CRC-32多项式):```c#include"gd32f4xx.h"//初始化CRC模块voidCRC_Init(void){rcu_periph_clock_enable(RCU_CRC);//使能CRC时钟//默认配置:CRC-32多项式,初始值0xFFFFFFFF,输入输出不反转}//计算数据的CRC32值uint32_tCalculate_CRC(uint32_t*data,uint32_tlen){CRC_DATA=0xFFFFFFFF;//复位为初始值(可选,因为每次计算后寄存器会保留结果)for(uint32_ti=0;i<len;i++){CRC_DATA=data[i];//写入数据字(每次写入32位)}returnCRC_DATA;//返回CRC计算结果}//示例:计算字节数组的CRC(需处理非4字节对齐)uint32_tCalculate_CRC_Bytes(uint8_t*bytes,uint32_tlen){CRC_DATA=0xFFFFFFFF;uint32_tword_len=len/4;uint32_t*words=(uint32_t*)bytes;for(uint32_ti=0;i<word_len;i++){CRC_DATA=words[i];}//处理剩余字节(如有)if(len%4){uint32_tlast=0;uint8_t*p=(uint8_t*)&last;for(uint32_ti=0;i<len%4;i++){p[i]=bytes[word_len*4+i];}CRC_DATA=last;}returnCRC_DATA;}```###注意事项1.**数据对齐**:硬件CRC通常要求32位字访问。若数据长度非4字节倍数,需填充处理(如补零)。2.**字节序**:GD32F默认按小端模式处理数据,若数据源为大端需转换。3.**多项式**:确认芯片使用的默认多项式(GD32F4xx默认为CRC-32:0x04C11DB7[^4])。4.**初始值**:不同协议要求不同初始值(如CRC-32为0xFFFFFFFF,CRC-16为0xFFFF)。###常见问题-**CRC值不匹配**:检查初始值、输入顺序(是否需反转字节)和多项式是否与对方一致。-**效率优化**:对于大量数据,直接使用字写入比字节写入快4倍。---###相关参考[^1]:GD32F4xx用户手册中CRC章节[^2]:通信协议中的CRC应用规范(如Modbus,Ethernet)---§§相关问题§§1.如何配置GD32F的CRC多项式为自定义值?2.GD32F的CRC模块支持DMA传输吗?3.CRC校验在通信协议(如CAN)中如何应用?4.如何验证GD32F硬件CRC计算的正确性?</think>### GD32F CRC校验原理详解 #### 一、CRC校验基本原理 CRC(循环冗余校验)是一种基于多项式除法的错误检测机制,其核心计算过程可表示为: $$ \text{CRC} = (D(x) \times x^n) \mod G(x) $$ 其中: - $D(x)$:数据多项式(输入数据) - $G(x)$:生成多项式(固定值) - $n$:CRC校验码位数 GD32F的硬件CRC模块特点: 1. **固定多项式**:默认使用CRC-32多项式(以太网标准): $$ G(x) = x^{32} + x^{26} + x^{23} + x^{22} + x^{16} + x^{12} + x^{11} + x^{10} + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 $$ 2. **硬件加速**:独立计算单元,不占用CPU资源 3. **数据格式**:支持32位字/8位字节操作 4. **初始值可配置**:CRC_DATA寄存器初始值默认为0xFFFF FFFF #### 二、完整代码示例 ##### 1. CRC模块初始化 ```c #include "gd32f30x.h" // 根据型号选择gd32f3xx/gd32f4xx void CRC_Init(void) { // 启用CRC外设时钟 rcu_periph_clock_enable(RCU_CRC); // 复位CRC计算单元(可选) CRC_CTL = CRC_CTL_RST; } ``` ##### 2. 计算32位数据CRC ```c uint32_t Calculate_CRC32(uint32_t *data, uint32_t length) { // 写入初始值(标准CRC32使用0xFFFFFFFF) CRC_DATA = 0xFFFFFFFF; for(uint32_t i = 0; i < length; i++) { // 写入32位数据触发计算 CRC_DATA = data[i]; } // 返回最终CRC结果(自动取反) return ~CRC_DATA; } ``` ##### 3. 计算字节流CRC(非对齐数据处理) ```c uint32_t Calculate_CRC8(uint8_t *bytes, uint32_t len) { CRC_DATA = 0xFFFFFFFF; // 重置初始值 // 处理完整32位字 uint32_t word_len = len / 4; for(uint32_t i = 0; i < word_len; i++) { uint32_t word = *(uint32_t*)(bytes + i*4); CRC_DATA = word; } // 处理剩余字节(1-3字节) uint32_t remainder = len % 4; if(remainder) { uint32_t last_word = 0; uint8_t *p = (uint8_t*)&last_word; for(uint32_t i = 0; i < remainder; i++) { p[i] = bytes[word_len*4 + i]; } CRC_DATA = last_word; } return ~CRC_DATA; } ``` ##### 4. CRC校验验证示例 ```c // 待校验数据 uint32_t test_data[] = {0x12345678, 0x9ABCDEF0}; int main(void) { CRC_Init(); // 计算CRC uint32_t crc_result = Calculate_CRC32(test_data, 2); printf("CRC32结果: 0x%08X\n", crc_result); // 验证数据完整性 uint32_t check_crc = Calculate_CRC32(test_data, 2); if(check_crc == crc_result) { printf("数据校验通过\n"); } else { printf("数据损坏!\n"); } return 0; } ``` #### 三、关键配置要点 1. **数据写入顺序**: ```c // 大端模式数据需转换 uint32_t data = __REV(input_data); CRC_DATA = data; ``` 2. **自定义多项式**(部分型号支持): ```c // 设置自定义多项式(如CRC16-CCITT) CRC_POL = 0x1021; // x^16 + x^12 + x^5 + 1 ``` 3. **输入反转配置**: ```c // 启用输入数据位反转(某些协议要求) CRC_CTL |= CRC_CTL_REV_IN; ``` #### 四、常见问题解决 1. **CRC结果不匹配**: - 检查数据端序(`__REV()`转换) - 验证初始值是否一致 - 确认多项式标准(CRC32 vs CRC32C) 2. **性能优化**: ```c // 使用DMA加速大数据传输 dma_channel_configure(DMA_CHx, &dma_config, (uint32_t)&CRC_DATA, src_addr, data_len); ``` 3. **字节对齐处理**: - 非4字节倍数数据需单独处理剩余字节 - 避免直接访问非对齐内存地址(引发硬件错误) #### 五、应用场景 1. 通信协议校验(CAN/USB/Ethernet)[^2] 2. 固件完整性验证(BootLoader/IAP)[^1][^3] 3. 存储介质错误检测(Flash/SD卡) > 参考: > [^1]: GD32 BootLoader中的CRC应用 > [^2]: CAN总线数据校验实现 > [^3]: IAP编程的固件验证机制 --- ### 相关问题 1. 如何配置GD32F的CRC多项式为自定义值? 2. GD32F的CRC模块支持DMA传输吗? 3. CRC校验在通信协议(如CAN)中如何应用? 4. 如何验证GD32F硬件CRC计算的正确性?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值