OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7747|回复: 3

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

[复制链接]

8

主题

47

帖子

1

精华

高级会员

Rank: 4

积分
675
金钱
675
注册时间
2014-9-17
在线时间
89 小时
发表于 2017-10-29 10:05:37 | 显示全部楼层 |阅读模式
本帖最后由 火透 于 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.0\Projects\STM32F767ZI-Nucleo\Examples\CRC\CRC_UserDefinedPolynomial\MDK-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]

当你的才华还撑不起你的野心时你就应该静下心来学习。当你的经济还撑不起你的梦想时,你就应该踏实的去工作。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
发表于 2017-10-29 21:18:40 | 显示全部楼层
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165475
金钱
165475
注册时间
2010-12-1
在线时间
2115 小时
发表于 2017-11-11 01:42:09 | 显示全部楼层
谢谢分享,cool
回复 支持 反对

使用道具 举报

12

主题

29

帖子

1

精华

初级会员

Rank: 2

积分
194
金钱
194
注册时间
2020-1-27
在线时间
19 小时
发表于 2020-2-8 21:27:53 | 显示全部楼层
测试成功,多谢
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-8 06:16

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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