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

[复制链接]
 楼主| 发表于 2017-10-29 10:00 | 显示全部楼层 |阅读模式
之前公司485通信是采用软件CRC16,感觉在STM32F7这样的片子上有点浪费了,而且硬件算起来多快啊,手册上写32bit在4个AHB周期完成,16bit在2个AHB周期,8bit在1个AHB周期,如果需要校验的字节数,硬件CRC16带来的效率可高太多了。如果再使用DMA来进行传输,CPU还可以解放。在STM32Cube_FW_F7_V1.7.0\Projects\STM32F767ZI-Nucleo\Examples\CRC\CRC_UserDefinedPolynomial\MDK-ARM工程基础上该的,串口数据以字节方式输入(DMA),如果使用CPU直接计算,需要将4个字节数据凑成32bit。测试了一组数据,与软件CRC16计算的结果一致,计算速度比软件计算快多了。
  1. /* Private typedef -----------------------------------------------------------*/
  2. /* Private define ------------------------------------------------------------*/
  3. /* aDataBuffer is 32 bit long*/
  4. #define BUFFER_SIZE 7

  5. /* The user defined polynomial*/
  6. #define CRC_POLYNOMIAL_8B 0xA001

  7. /* Private macro -------------------------------------------------------------*/
  8. /* Private variables ---------------------------------------------------------*/
  9. /* CRC handler declaration */
  10. CRC_HandleTypeDef   CrcHandle;
  11. DMA_HandleTypeDef DmaHandle;

  12. /* Used for storing CRC Value */
  13. __IO uint32_t uwCRCValue = 0;
  14. __IO uint32_t uwCRCValue1 = 0;

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

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

  38.   /* Configure LED1 and LED3 */
  39.   BSP_LED_Init(LED1);
  40.   BSP_LED_Init(LED3);

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

  43.   /* The default polynomial is not used. It is required to defined it in CrcHandle.Init.GeneratingPolynomial*/  
  44.   CrcHandle.Init.DefaultPolynomialUse    = DEFAULT_POLYNOMIAL_DISABLE;
  45.   
  46.   /* Set the value of the polynomial */
  47.   CrcHandle.Init.GeneratingPolynomial    = 0x8005;
  48.   
  49.   /* The user-defined generating polynomial generates a
  50.      8-bit long CRC */
  51.   CrcHandle.Init.CRCLength               = CRC_POLYLENGTH_16B;

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

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

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

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

  62.   if (HAL_CRC_Init(&CrcHandle) != HAL_OK)
  63.   {
  64.     /* Initialization Error */
  65.     Error_Handler();
  66.   }
  67.   
  68.   
  69.   __HAL_RCC_DMA2_CLK_ENABLE();
  70.   DmaHandle.Init.Channel = DMA_CHANNEL_0;
  71.   DmaHandle.Init.Direction = DMA_MEMORY_TO_MEMORY;
  72.   DmaHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  73.   DmaHandle.Init.MemBurst = DMA_MBURST_SINGLE;
  74.   DmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  75.   DmaHandle.Init.MemInc = DMA_MINC_DISABLE;
  76.   DmaHandle.Init.Mode = DMA_NORMAL;
  77.   DmaHandle.Init.PeriphBurst = DMA_PBURST_SINGLE;
  78.   DmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  79.   DmaHandle.Init.PeriphInc = DMA_PINC_ENABLE;
  80.   DmaHandle.Init.Priority = DMA_PRIORITY_VERY_HIGH ;
  81.   DmaHandle.Instance = DMA2_Stream0;
  82.   
  83.   if(HAL_DMA_Init(&DmaHandle) != HAL_OK)
  84.   {
  85.           Error_Handler();
  86.   }
  87.   __HAL_CRC_DR_RESET(&CrcHandle);
  88.   
  89.   if( HAL_DMA_Start(&DmaHandle,(uint32_t)bDataBuffer, (uint32_t)&CRC->DR, BUFFER_SIZE ) != HAL_OK)
  90.   {
  91.           Error_Handler();
  92.   }
  93.   while(__HAL_DMA_GET_FLAG(&DmaHandle,DMA_FLAG_TCIF0_4) == 0);
  94.   __HAL_DMA_CLEAR_FLAG(&DmaHandle,DMA_FLAG_TCIF0_4);
  95.   uwCRCValue1 = CRC->DR;

  96.   /*##-2- Compute the CRC of "aDataBuffer" ###################################*/
  97.   uwCRCValue = HAL_CRC_Calculate(&CrcHandle, (uint32_t *)aDataBuffer, BUFFER_SIZE);
  98.   
  99.   /*##-3- Compare the CRC value to the Expected one ##########################*/
  100.   if (uwCRCValue != uwExpectedCRCValue)
  101.   {
  102.     /* Wrong CRC value: Turn LED3 on */
  103.     Error_Handler();
  104.   }
  105.   else
  106.   {
  107.     /* Right CRC value: Turn LED1 on */
  108.     BSP_LED_On(LED1);
  109.   }

  110.   /* Infinite loop */
  111.   while (1)
  112.   {
  113.   }
  114. }




发表于 2017-12-24 20:44 来自手机 | 显示全部楼层
发表于 2017-12-24 21:16 | 显示全部楼层
CRC啊,菜农大叔的神器秒杀。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

34

帖子

1

粉丝
快速回复 返回顶部 返回列表