STM32F7对串口数据进行硬件CRC16,DMA + CPU两种方式

2019-07-20 11:05发布

本帖最后由 火透 于 2017-11-11 17:18 编辑

之前公司485通信是采用软件CRC16,感觉在STM32F7这样的片子上有点浪费了,而且硬件算起来多快啊,手册上写32bit在4个AHB周期完成,16bit在2个AHB周期,8bit在1个AHB周期,如果需要校验的字节数,硬件CRC16带来的效率可高太多了。如果再使用DMA来进行传输,CPU还可以解放。在STM32Cube_FW_F7_V1.7.0ProjectsSTM32F767ZI-NucleoExamplesCRCCRC_UserDefinedPolynomialMDK-ARM工程基础上该的,串口数据以字节方式输入(DMA),如果使用CPU直接计算,需要将4个字节数据凑成32bit。测试了一组数据,与软件CRC16计算的结果一致,计算速度比软件计算快多了

[mw_shl_code=c,true]/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* aDataBuffer is 32 bit long*/
#define BUFFER_SIZE 7

/* The user defined polynomial*/
#define CRC_POLYNOMIAL_8B 0xA001

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* CRC handler declaration */
CRC_HandleTypeDef   CrcHandle;
DMA_HandleTypeDef DmaHandle;

/* Used for storing CRC Value */
__IO uint32_t uwCRCValue = 0;
__IO uint32_t uwCRCValue1 = 0;

/* Buffer containing the data on which the CRC will be calculated
  (one-word buffer in this example) */
static const uint32_t aDataBuffer[] = {0x02006D1D,0x0000007C};
static const uint8_t bDataBuffer[] = {0x1D,0x6D,0x00,0x02,0x7C,0x00,0x00};

int main(void)
{
  /* Enable the CPU Cache */
  CPU_CACHE_Enable();
  
  /* STM32F7xx HAL library initialization:
       - Configure the Flash prefetch
       - Systick timer is configured by default as source of time base, but user
         can eventually implement his proper time base source (a general purpose
         timer for example or other time source), keeping in mind that Time base
         duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
         handled in milliseconds basis.
       - Set NVIC Group Priority to 4
       - Low Level Initialization
     */
  HAL_Init();
  
  /* Configure the system clock to 216 MHz */
  SystemClock_Config();

  /* Configure LED1 and LED3 */
  BSP_LED_Init(LED1);
  BSP_LED_Init(LED3);

  /*##-1- Configure the CRC peripheral #######################################*/
  CrcHandle.Instance = CRC;

  /* The default polynomial is not used. It is required to defined it in CrcHandle.Init.GeneratingPolynomial*/  
  CrcHandle.Init.DefaultPolynomialUse    = DEFAULT_POLYNOMIAL_DISABLE;
  
  /* Set the value of the polynomial */
  CrcHandle.Init.GeneratingPolynomial    = 0x8005; //__RBIT(0xA001)
  
  /* The user-defined generating polynomial generates a
     8-bit long CRC */
  CrcHandle.Init.CRCLength               = CRC_POLYLENGTH_16B;

  /* The default init value is used */
  CrcHandle.Init.DefaultInitValueUse     = DEFAULT_INIT_VALUE_DISABLE;

  /* The input data are not inverted */
  CrcHandle.Init.InputDataInversionMode  = CRC_INPUTDATA_INVERSION_BYTE;//CRC_INPUTDATA_INVERSION_NONE;

  /* The output data are not inverted */
  CrcHandle.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE;//CRC_OUTPUTDATA_INVERSION_DISABLE;

  /* The input data are 32-bit long */
  CrcHandle.InputDataFormat              = CRC_INPUTDATA_FORMAT_BYTES;
  
  CrcHandle.Init.InitValue = 0x0000FFFF;

  if (HAL_CRC_Init(&CrcHandle) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }
  
  
  __HAL_RCC_DMA2_CLK_ENABLE();
  DmaHandle.Init.Channel = DMA_CHANNEL_0;
  DmaHandle.Init.Direction = DMA_MEMORY_TO_MEMORY;
  DmaHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  DmaHandle.Init.MemBurst = DMA_MBURST_SINGLE;
  DmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  DmaHandle.Init.MemInc = DMA_MINC_DISABLE;
  DmaHandle.Init.Mode = DMA_NORMAL;
  DmaHandle.Init.PeriphBurst = DMA_PBURST_SINGLE;
  DmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  DmaHandle.Init.PeriphInc = DMA_PINC_ENABLE;
  DmaHandle.Init.Priority = DMA_PRIORITY_VERY_HIGH ;
  DmaHandle.Instance = DMA2_Stream0;
  
  if(HAL_DMA_Init(&DmaHandle) != HAL_OK)
  {
          Error_Handler();
  }
  __HAL_CRC_DR_RESET(&CrcHandle);
  
  if( HAL_DMA_Start(&DmaHandle,(uint32_t)bDataBuffer, (uint32_t)&CRC->DR, BUFFER_SIZE ) != HAL_OK)
  {
          Error_Handler();
  }
  while(__HAL_DMA_GET_FLAG(&DmaHandle,DMA_FLAG_TCIF0_4) == 0);
  __HAL_DMA_CLEAR_FLAG(&DmaHandle,DMA_FLAG_TCIF0_4);
  uwCRCValue1 = CRC->DR;
HAL_DMA_Abort(&CrcDmaHandle); //取消本次DMA传输


  /*##-2- Compute the CRC of "aDataBuffer" ###################################*/
  uwCRCValue = HAL_CRC_Calculate(&CrcHandle, (uint32_t *)aDataBuffer, BUFFER_SIZE);
  
  /*##-3- Compare the CRC value to the Expected one ##########################*/
  if (uwCRCValue != uwExpectedCRCValue)
  {
    /* Wrong CRC value: Turn LED3 on */
    Error_Handler();
  }
  else
  {
    /* Right CRC value: Turn LED1 on */
    BSP_LED_On(LED1);
  }

  /* Infinite loop */
  while (1)
  {
  }
}

[/mw_shl_code]

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。