STM32 硬件CRC的使用

发布时间 2023-10-14 16:32:32作者: okyihu

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