STM32并口数据通过DMA传输

在工作当中,使用STM32与其他芯片通信,常用的有SPI、UART、I2C等串行类的通信,但是对于ADC等芯片来说,还存在并口类型的通信方式。STM32提供了FSMC功能对总线进行控制。但是对于小封装类的芯片(64PIN)并未提供该功能,那么该怎么处理呢?我认为通过DMA进行并行数据的读写可以解决上述问题。
本方法有个缺陷就是必须使用同一组IO口,如PA或PB,这样直接对寄存器IDR进行读写,达到同时读写端口的目的。
使用的DMA也有要求,之前在网上搜集DMA传输IO口方法的时候,看到有人在论坛里讨论可行性,发现需要查看STM32F系列的各型号的DMA总线,比如我使用的F4系列的DMA总线。STM32并口数据通过DMA传输_第1张图片
其中,DMA1的外设port只连接到了APB1上,不能作为IO的外设端,只能使用DMA2。
使用定时器TIM1的溢出作为触发传输,设置不同的定时时间,则得到不同的采样率。
定时器1配置:

void MX_TIM1_Init(void)
{
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 16;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 98;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }

}

定时器DMA配置

 if(tim_baseHandle->Instance==TIM1)
  {
  /* USER CODE BEGIN TIM1_MspInit 0 */
	//hdma_tim1_up.XferCpltCallback = myDMA;//若需要DMA传输满,则配置DMA中断
  /* USER CODE END TIM1_MspInit 0 */
    /* TIM1 clock enable */
    __HAL_RCC_TIM1_CLK_ENABLE();
  
    /* TIM1 DMA Init */
    /* TIM1_UP Init */
    hdma_tim1_up.Instance = DMA2_Stream5;
    hdma_tim1_up.Init.Channel = DMA_CHANNEL_6;
    hdma_tim1_up.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_tim1_up.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_tim1_up.Init.MemInc = DMA_MINC_ENABLE;//存储数组地址增加
    hdma_tim1_up.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_tim1_up.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_tim1_up.Init.Mode = DMA_NORMAL;//如需一直保存,则配置为DMA_CIRCULAR	
    hdma_tim1_up.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_tim1_up.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_tim1_up) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(tim_baseHandle,hdma[TIM_DMA_ID_UPDATE],hdma_tim1_up);

  /* USER CODE BEGIN TIM1_MspInit 1 */

  /* USER CODE END TIM1_MspInit 1 */
  }

主函数内或需要的地方配置开启DMA

HAL_TIM_Base_Start(&htim1);
HAL_DMA_Start_IT(&hdma_tim1_up,(uint32_t)&GPIOB->IDR,(uint32_t)ADC_RcvBuf,4096);
__HAL_TIM_ENABLE_DMA(&htim1, TIM_DMA_UPDATE);

完成。
注:主要注意的地方就是DMA1/2的选择。

你可能感兴趣的:(STM32并口数据通过DMA传输)