一、stm32的CRC
1.1 CRC的简介及MCU关联说明
STM32的CRC(Cyclic Redundancy Check,循环冗余校验)计算单元使用一个固定的多项式发生器,从一个32位的数据字产生一个CRC码。在业务开发应用中,会基于CRC的技术用于验证数据传输或存储完整性。在EN/IEC60335-1标准的范围内,它们提供了一种验证闪存(flash)完整性的方法。CRC计算单元帮助计算运行时软件的签名,并与在链接和生成该软件时产生的签名比较验证。
cubeIDE开发, stm32调试信息串口通信输出显示_py_free的博客-CSDN博客_调试信息输出到串口
现双击.ioc文件,打开CubeMX配置界面,开启CRC计算功能,参数保持默认设置。
保存及生成输出代码
2.2 CRC的HLA库分析
cubeMX生成代码时,会在Core源码目录下的Inc及Src目录,分别生成crc.h和crc.c驱动文件。
在crc.c文件中,主要定义了MX_CRC_Init函数和HAL_CRC_MspInit函数。MX_CRC_Init主要做两件事情,一是将CubeMX上配置的参数传递给CRC缓存Init和生成CRC句柄Instance(寄存器),二是调用HLA库的HAL_CRC_Init来实现真正的初始化设定。HAL_CRC_MspInit是HLA内的弱函数,根据实际配置CubeMX会生成新的函数,完成真正的MCU底层设置任务(MspInit,MCU Specific Package init,即指和MCU相关的初始化),覆盖原来的弱函数,而在HAL_CRC_Init函数中会调用到HAL_CRC_MspInit函数。
在stm32l4xx_hal_crc.c源文件中定义了HAL_CRC_Init函数,它做以下事情:诊断配置参数是否合规;调用HAL_CRC_MspInit函数完成CRC时钟开启;最后将依据参数写入CRC寄存器,如果采用默认多项式参数,写入默认多项式数值,否则调用多项式配置函数,写入用户定义数值。
再回到crc.c内,HAL_CRC_MspInit函数实现了CRC时钟启动设置。
另外HLA库提供了用户自定义设置多项式参数、输入数据反转及输入数据反转的函数,方便开发这在程序代码中按需变更CRC计算方式,这些函数作为扩展功能放置在stm32l4xx_hal_crc_ex.h/c内。
2.3 CRC计算功能及调用设计
在stm32l4xx_hal_crc.c源文件除了定义初始化功外,还定义了CRC计算功能函数HAL_CRC_Accumulate和HAL_CRC_Calculate,HAL_CRC_Accumulate函数使用先前的CRC值和新的CRC值的组合来计算8、16或32位数据缓冲器的7、8、16和32位CRC值;HAL_CRC_Calculate独立于先前的CRC值,计算8、16或32位数据缓冲器的7、8、16和32位CRC值,因此它不同于HAL_CRC_Accumulate的部分是每次计算一组数据前,都会进行数据寄存器重置
在main.c文件中,加入驱动文件支持
- /* Private includes ----------------------------------------------------------*/
- /* USER CODE BEGIN Includes */
- #include "../../ICore/key/key.h"
- #include "../../ICore/led/led.h"
- #include "../../ICore/print/print.h"
- #include "../../ICore/usart/usart.h"
- #include "../../ICore/delay/delay.h"
- /* USER CODE END Includes */
复制代码
在main.c文件中,加入CRC句柄(寄存器)声明
- /* Private user code ---------------------------------------------------------*/
- /* USER CODE BEGIN 0 */
- extern CRC_HandleTypeDef hcrc;
- /* USER CODE END 0 */
复制代码
在main函数中,加入外设驱动启用(主要是串口调试中断开启)及相关初始设置,添加了一组3个长度32bit宽的数据数组用于测试。
- /* Initialize all configured peripherals */
- MX_GPIO_Init();
- MX_LPUART1_UART_Init();
- MX_CRC_Init();
- /* USER CODE BEGIN 2 */
- ResetPrintInit(&hlpuart1);
- HAL_UART_Receive_IT(&hlpuart1,(uint8_t *)&HLPUSART_NewData, 1); //再开启接收中断
- HLPUSART_RX_STA = 0;
- //
- printf("app restart now!\r\n");
- uint32_t crc_input[3] = {0X12345678,0X23456789,0X34567890};
- uint32_t crc_output = 0x00;
- uint32_t crc_index = 0;
- uint8_t crc_mode = 0;
- /* USER CODE END 2 */
复制代码 在main函数循环体中,通过按钮调用CRC计算功能,并通过lpuar1串口输出显示计算结果。
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while (1)
- {
- if(HLPUSART_RX_STA&0xC000){//溢出或换行,重新开始
- //printf("%.*s\r\n",HLPUSART_RX_STA&0X0FFF, HLPUSART_RX_BUF);
- HLPUSART_RX_STA=0;//接收错误,重新开始
- HAL_Delay(100);//等待
- }
- if(KEY_0())
- {
- crc_output = HAL_CRC_Accumulate(&hcrc,crc_input,3);
- printf("crc_Accumulate_output:0X%08lX\r\n",crc_output);
- }
- if(KEY_1())
- {
- crc_output = HAL_CRC_Calculate(&hcrc,crc_input,3);
- printf("crc_Calculate_output:0X%08lX\r\n",crc_output);
- }
- if(KEY_2())
- {
- crc_mode = (crc_index)%6;
- switch(crc_mode){
- case 0:
- HAL_CRCEx_Output_Data_Reverse(&hcrc,CRC_OUTPUTDATA_INVERSION_ENABLE);
- printf("Output_Data_Reverse:0X%08lXU\r\n",CRC_OUTPUTDATA_INVERSION_ENABLE);
- break;
- case 1:
- HAL_CRCEx_Output_Data_Reverse(&hcrc,CRC_OUTPUTDATA_INVERSION_DISABLE);
- printf("Output_Data_Reverse:0X%08XU\r\n",CRC_OUTPUTDATA_INVERSION_DISABLE);
- break;
- case 2:
- HAL_CRCEx_Input_Data_Reverse(&hcrc,CRC_INPUTDATA_INVERSION_BYTE);
- printf("Input_Data_Reverse:0X%08lXU\r\n",CRC_INPUTDATA_INVERSION_BYTE);
- break;
- case 3:
- HAL_CRCEx_Input_Data_Reverse(&hcrc,CRC_INPUTDATA_INVERSION_HALFWORD);
- printf("Input_Data_Reverse:0X%08lXU\r\n",CRC_INPUTDATA_INVERSION_HALFWORD);
- break;
- case 4:
- HAL_CRCEx_Input_Data_Reverse(&hcrc,CRC_INPUTDATA_INVERSION_WORD);
- printf("Input_Data_Reverse:0X%08lXU\r\n",CRC_INPUTDATA_INVERSION_WORD);
- break;
- case 5:
- HAL_CRCEx_Polynomial_Set(&hcrc,DEFAULT_CRC32_POLY,CRC_POLYLENGTH_16B);
- printf("Polynomial_Set:0X%04XU\r\n",DEFAULT_CRC32_POLY);
- break;
- default:
- break;
- }
- crc_index++;
- }
- /* USER CODE END WHILE */
复制代码
三、编译及测试
3.1 编译下载
3.2 测试
程序开启时,默认多项式参数是0x04C11DB7U,无输入、输出反转。每按键一次KEY2改变输入反转模式或输出反转模式或多项式参数 ,然后各按键一次KEY0和KEY1, log输出如下:
案例只是抛砖引玉,更多CRC功能及应用拓展请自行上手代码实践。
————————————————
版权声明:py_free-物联智能
如有侵权请联系删除
|
感谢分享 我想请问一下怎么用自带的CRC计算CRC16 数组类型是uint8的