1 代码:
crc_lib.h
/* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __crc_lib_H #define __crc_lib_H #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ /* USER CODE BEGIN Includes */ /* USER CODE END Includes */
/* USER CODE BEGIN Private defines */ /* USER CODE END Private defines */ void GHShell_CRC_Init(unsigned char crc_type) ; unsigned short GHShell_CRC_Calculate(unsigned int pBuffer[], unsigned int BufferLength) ; /* USER CODE BEGIN Prototypes */ #define CRC16_MODBUS 0 #define CRC16_X25 1 /* USER CODE END Prototypes */ #ifdef __cplusplus } #endif #endif /*__ crc_H */
crc_lib.c
/* Includes ------------------------------------------------------------------*/ #include "crc_lib.h" /* USER CODE BEGIN 0 */ #include "stm32g0xx_hal.h" /* USER CODE END 0 */ static CRC_HandleTypeDef hcrc; static unsigned char CRCType; static void CRC_Swap(uint8_t *pa, uint8_t *pb); typedef struct { uint8_t lsb8; uint8_t msb8; } Crc_data; typedef union { uint16_t reg; Crc_data val; }Crc_ElementType; /****************** Exported function ***********************/ /* CRC init function */ void GHShell_CRC_Init(unsigned char crc_type) { hcrc.Instance = CRC; hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE; hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_DISABLE; if(crc_type){ hcrc.Init.GeneratingPolynomial = 4129;
/*这个值对应多项式,多项式用2的N次方加起来后就是这个值。
设置不同的值就是不同的CRC校验多项式,STM32F4的硬件CRC只支持以太网的CRC校验*/
} else{ hcrc.Init.GeneratingPolynomial = 32773; } CRCType =crc_type; hcrc.Init.CRCLength = CRC_POLYLENGTH_16B; hcrc.Init.InitValue = 0xFFFF; hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE; hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE; hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES; if (HAL_CRC_Init(&hcrc) != HAL_OK) { // Error_Handler(); } } unsigned short GHShell_CRC_Calculate(uint32_t pBuffer[], uint32_t BufferLength) { Crc_ElementType Crc16; Crc16.reg =HAL_CRC_Calculate(&hcrc, pBuffer,BufferLength); CRC_Swap(&Crc16.val.lsb8,&Crc16.val.msb8); if(CRCType == CRC16_X25){ Crc16.reg ^=0xFFFF; } return (Crc16.reg); } /******************** private function *********************/ static void CRC_Swap(uint8_t *pa, uint8_t *pb) { uint8_t t; t =*pa; *pa =*pb; *pb =t; } void HAL_CRC_MspInit(CRC_HandleTypeDef* crcHandle) { if(crcHandle->Instance==CRC) { /* USER CODE BEGIN CRC_MspInit 0 */ /* USER CODE END CRC_MspInit 0 */ /* CRC clock enable */ __HAL_RCC_CRC_CLK_ENABLE(); /* USER CODE BEGIN CRC_MspInit 1 */ /* USER CODE END CRC_MspInit 1 */ } } void HAL_CRC_MspDeInit(CRC_HandleTypeDef* crcHandle) { if(crcHandle->Instance==CRC) { /* USER CODE BEGIN CRC_MspDeInit 0 */ /* USER CODE END CRC_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_CRC_CLK_DISABLE(); /* USER CODE BEGIN CRC_MspDeInit 1 */ /* USER CODE END CRC_MspDeInit 1 */ } }
2 知识拓展:
A CRC在线计算:
https://www.lammertbies.nl/comm/info/crc-calculation
http://www.ip33.com/crc.html
B CRC算法参数模型解释:
NAME:参数模型名称。如:CRC16/MODBUS等
WIDTH:宽度,即CRC比特数。
POLY:生成项的简写,以16进制表示。例如:CRC-32即是0x04C11DB7,忽略了最高位的"1",即完整的生成项是0x104C11DB7。
INIT:这是算法开始时寄存器(crc)的初始化预置值,十六进制表示。
REFIN:待测数据的每个字节是否按位反转,True或False。
REFOUT:在计算后之后,异或输出之前,整个数据是否按位反转,True或False。
XOROUT:计算结果与此参数异或后得到最终的CRC值。
常见CRC参数模型如下:
CRC算法名称 | 多项式公式 | 宽度 | 多项式 | 初始值 | 结果异或值 | 输入反转 | 输出反转 |
---|---|---|---|---|---|---|---|
CRC-4/ITU | x4 + x + 1 | 4 | 03 | 00 | 00 | true | true |
CRC-5/EPC | x5 + x3 + 1 | 5 | 09 | 09 | 00 | false | false |
CRC-5/ITU | x5 + x4 + x2 + 1 | 5 | 15 | 00 | 00 | true | true |
CRC-5/USB | x5 + x2 + 1 | 5 | 05 | 1F | 1F | true | true |
CRC-6/ITU | x6 + x + 1 | 6 | 03 | 00 | 00 | true | true |
CRC-7/MMC | x7 + x3 + 1 | 7 | 09 | 00 | 00 | false | false |
CRC-8 | x8 + x2 + x + 1 | 8 | 07 | 00 | 00 | false | false |
CRC-8/ITU | x8 + x2 + x + 1 | 8 | 07 | 00 | 55 | false | false |
CRC-8/ROHC | x8 + x2 + x + 1 | 8 | 07 | FF | 00 | true | true |
CRC-8/MAXIM | x8 + x5 + x4 + 1 | 8 | 31 | 00 | 00 | true | true |
CRC-16/IBM | x16 + x15 + x2 + 1 | 16 | 8005 | 0000 | 0000 | true | true |
CRC-16/MAXIM | x16 + x15 + x2 + 1 | 16 | 8005 | 0000 | FFFF | true | true |
CRC-16/USB | x16 + x15 + x2 + 1 | 16 | 8005 | FFFF | FFFF | true | true |
CRC-16/MODBUS | x16 + x15 + x2 + 1 | 16 | 8005 | FFFF | 0000 | true | true |
CRC-16/CCITT | x16 + x12 + x5 + 1 | 16 | 1021 | 0000 | 0000 | true | true |
CRC-16/CCITT-FALSE | x16 + x12 + x5 + 1 | 16 | 1021 | FFFF | 0000 | false | false |
CRC-16/X25 | x16 + x12 + x5 + 1 | 16 | 1021 | FFFF | FFFF | true | true |
CRC-16/XMODEM | x16 + x12 + x5 + 1 | 16 | 1021 | 0000 | 0000 | false | false |
CRC-16/DNP | x16 + x13 + x12 + x11 + x10 + x8 + x6 + x5 + x2 + 1 | 16 | 3D65 | 0000 | FFFF | true | true |
CRC-32 | x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 | 32 | 04C11DB7 | FFFFFFFF | FFFFFFFF | true | true |
CRC-32/MPEG-2 | x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 | 32 | 04C11DB7 | FFFFFFFF | 00000000 | false | false |