十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CRC 计算单元:编码、校验与调试指南

CRC 计算单元:编码、校验与调试指南 文章目录1. 概述2. CRC 编码模式3. CRC 校验模式4. 代码示例4.1 bsp_crc.c4.2 bsp_crc.h5. 常见问题与调试建议5.1 常见问题概述5.2 初始值未设置5.3 数据位宽不匹配5.4 字节序错误5.5 数据长度不一致5.6 未使能 CRC 时钟5.7 常见问题对比表6. 总结7. 参考资料1. 概述循环冗余校验CRC计算单元是根据固定的生成多项式得到任意字节数据的 CRC 计算结果。在应用中CRC 技术主要应用于核实数据传输或者数据存储的正确性和完整性。本模块算法遵从 ISO/IEC 13239 的定义采用 16 位长度的 CRC计算多项式为x^16 x^12 x^5 x计算初始值为 0xFFFF。本模块功能包括CRC 编码和 CRC 校验3 种位宽访问方式8 位、16 位、32 位8 位位宽下输入数据示例为 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x7716 位位宽下输入数据示例为 0x1100, 0x3322, 0x5544, 0x776632 位位宽下输入数据示例为 0x33221100, 0x77665544下面是本模块的整体功能结构图CRC 计算单元CRC 编码模式CRC 校验模式8 位访问16 位访问32 位访问2. CRC 编码模式编码模式可以对原始数据编码以计算其 CRC 值操作流程如下所示向CRC_RESULT.RESULT写入0xFFFF初始化 CRC 计算。将待编码的原始数据按 8 位/16 位/32 位的组织方式依次写入CRC_DATA寄存器。读取CRC_RESULT.RESULT即为 CRC 值。下面是编码模式的操作流程图开始向 CRC_RESULT.RESULT 写入 0xFFFF按 8/16/32 位组织方式写入 CRC_DATA读取 CRC_RESULT.RESULT得到 CRC 值结束3. CRC 校验模式校验模式可以检验已编码的数据是否被篡改操作流程如下所示向CRC_RESULT.RESULT写入0xFFFF初始化 CRC 计算。将已编码的数据按 8 位/16 位/32 位的组织方式依次写入CRC_DATA寄存器。注按 8 位组织方式写 CRC 值到CRC_DATA寄存器时应先写入低 8 位后写入高 8 位。读取CRC_RESULT.FLAG以判定 CRC 校验是否成功。下面是校验模式的操作流程图是否开始向 CRC_RESULT.RESULT 写入 0xFFFF按 8/16/32 位组织方式写入 CRC_DATA读取 CRC_RESULT.FLAGFLAG 是否为 1?校验成功校验失败4. 代码示例4.1 bsp_crc.c/******************************************************************************** * file bsp_crc.c * author jianqiang.xue * version V1.0.0 * date 2021-04-15 * brief CRC校验 ********************************************************************************/#includeRTE_Components.h#includeCMSIS_device_header#includecx32l003_hal.hstaticCRC_HandleTypeDef g_crc_config{.InstanceCRC};voidbsp_crc_init(void){__HAL_RCC_CRC_CLK_ENABLE();HAL_CRC_Init(g_crc_config);}uint32_tbsp_crc_calculate(uint8_t*data,uint32_tlen){returnHAL_CRC_Calculate(g_crc_config,data,len);}4.2 bsp_crc.h/******************************************************************************** * file bsp_crc.h * author jianqiang.xue * version V1.0.0 * date 2021-04-15 * brief NULL ********************************************************************************/#ifndef__BSP_CRC_H#define__BSP_CRC_H/* Includes ------------------------------------------------------------------*/#includestdint.h/* Public Function Prototypes ------------------------------------------------*/voidbsp_crc_init(void);uint32_tbsp_crc_calculate(uint8_t*data,uint32_tlen);#endif5. 常见问题与调试建议5.1 常见问题概述CRC 校验失败通常表现为CRC_RESULT.FLAG始终为 0 或校验结果与预期不符。下面列举几种常见原因及对应的排查步骤。5.2 初始值未设置现象每次计算得到的 CRC 值都不稳定或与预期结果相差很大。原因在写入数据前没有向CRC_RESULT.RESULT写入0xFFFF导致计算基于上一次残留的中间状态进行。排查步骤确认在每次编码/校验前都执行了CRC_RESULT.RESULT 0xFFFF。检查初始化代码是否被放在循环外导致第二次计算时未重新初始化。代码修改示例voidbsp_crc_calculate(uint8_t*data,uint32_tlen){/* 每次计算前务必重新初始化 */CRC_RESULT.RESULT0xFFFF;returnHAL_CRC_Calculate(g_crc_config,data,len);}5.3 数据位宽不匹配现象发送端与接收端使用不同的位宽组织数据导致校验结果不一致。原因编码时按 32 位写入数据而校验时按 8 位写入或反之。CRC 计算对数据的组织方式敏感位宽不一致会得到完全不同的结果。排查步骤确认编码与校验两端使用相同的位宽8 位/16 位/32 位。检查数据写入CRC_DATA寄存器时的指针类型与长度参数是否匹配。代码修改示例/* 统一按 8 位方式写入 */uint32_tbsp_crc_calculate(uint8_t*data,uint32_tlen){CRC_RESULT.RESULT0xFFFF;for(uint32_ti0;ilen;i){CRC_DATA.DATA8data[i];/* 按 8 位写入 */}returnCRC_RESULT.RESULT;}5.4 字节序错误现象校验结果与预期值恰好相反或高低字节互换。原因按 8 位组织方式写入 CRC 值时应先写入低 8 位后写入高 8 位。若顺序颠倒会导致字节序错误。排查步骤检查写入顺序是否为「先低后高」。若使用 16 位/32 位写入确认大小端模式与对端一致。代码修改示例/* 按 8 位写入时先写低 8 位再写高 8 位 */CRC_DATA.DATA8(uint8_t)(crc_value0xFF);/* 低 8 位 */CRC_DATA.DATA8(uint8_t)((crc_value8)0xFF);/* 高 8 位 */5.5 数据长度不一致现象编码与校验时传入的数据长度不同导致校验失败。原因CRC 是对整段数据计算得到的任何一位数据的缺失或多余都会改变最终结果。排查步骤确认编码与校验时传入的len参数完全一致。检查数据缓冲区是否被意外修改例如越界写入破坏了原始数据。代码修改示例/* 编码与校验使用同一长度常量避免不一致 */#defineDATA_LEN8uint8_ttx_data[DATA_LEN]{0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};uint32_tcrc_sendbsp_crc_calculate(tx_data,DATA_LEN);uint32_tcrc_recvbsp_crc_calculate(rx_data,DATA_LEN);5.6 未使能 CRC 时钟现象调用HAL_CRC_Calculate后返回异常值或程序进入硬件错误中断。原因使用 CRC 外设前未调用__HAL_RCC_CRC_CLK_ENABLE()使能时钟。排查步骤确认bsp_crc_init()已在系统初始化阶段被调用。检查时钟使能代码是否被条件编译屏蔽。代码修改示例voidbsp_crc_init(void){__HAL_RCC_CRC_CLK_ENABLE();/* 必须先使能时钟 */HAL_CRC_Init(g_crc_config);}5.7 常见问题对比表下表汇总了上述 5 种常见问题的现象、原因与排查要点便于快速定位问题常见问题现象原因排查要点初始值未设置CRC 值不稳定或与预期相差很大计算前未向CRC_RESULT.RESULT写入0xFFFF基于残留中间状态计算每次编码/校验前重新初始化确认初始化代码未被放在循环外数据位宽不匹配发送端与接收端校验结果不一致编码与校验两端使用不同的位宽8/16/32 位组织数据两端使用相同位宽检查指针类型与长度参数是否匹配字节序错误校验结果与预期相反或高低字节互换按 8 位写入 CRC 值时未遵循「先低后高」顺序检查写入顺序16/32 位写入时确认大小端模式与对端一致数据长度不一致编码与校验结果不匹配编码与校验时传入的数据长度不同任何一位变化都会改变结果确认两端len参数完全一致检查缓冲区是否被越界写入破坏未使能 CRC 时钟HAL_CRC_Calculate返回异常值或进入硬件错误中断使用 CRC 外设前未调用__HAL_RCC_CRC_CLK_ENABLE()确认bsp_crc_init()已在系统初始化阶段调用检查时钟使能代码是否被条件编译屏蔽6. 总结本文介绍了基于 ISO/IEC 13239 标准的 16 位 CRC 计算单元核心功能包括 CRC 编码与 CRC 校验两种模式并支持 8 位、16 位、32 位三种位宽访问方式。编码模式用于对原始数据计算 CRC 值校验模式则用于检测数据在传输或存储过程中是否被篡改。在实际使用中CRC 校验失败多由以下几类问题引起初始值未设置计算前未向CRC_RESULT.RESULT写入0xFFFF导致结果不稳定。数据位宽不匹配编码与校验两端使用了不同的位宽组织数据。字节序错误按 8 位写入 CRC 值时未遵循「先低后高」的顺序。数据长度不一致编码与校验时传入的数据长度不同。未使能 CRC 时钟使用外设前未调用__HAL_RCC_CRC_CLK_ENABLE()。调试时建议遵循以下要点每次计算前务必重新初始化 CRC 寄存器。编码与校验两端保持相同的位宽、字节序和数据长度。确认 CRC 外设时钟已在系统初始化阶段使能。结合CRC_RESULT.FLAG与预期值对比逐步定位问题环节。下面是 CRC 校验失败的排查流程图否是否是否是否是否是CRC 校验失败初始值是否已设置?写入 0xFFFF 初始化数据位宽是否匹配?统一两端位宽字节序是否正确?按先低后高写入数据长度是否一致?统一 len 参数CRC 时钟是否使能?调用 __HAL_RCC_CRC_CLK_ENABLE检查硬件连接与寄存器配置7. 参考资料ISO/IEC 13239:2002, Information technology — Telecommunications and information exchange between systems — HDLC proceduresSTMicroelectronics, AN4187 — Using the CRC peripheral in STM32 family devicesSTMicroelectronics, RM0008 — STM32F101xx, STM32F102xx, STM32F103xx, STM32F105xx and STM32F107xx advanced ARM-based 32-bit MCUs Reference ManualCX32L003 系列微控制器参考手册
返回列表