简体   繁体   English

STM32F3 如何在定时器上触发 ADC 转换并使用循环 DMA 传输

[英]STM32F3 how to trigger ADC conversions on Timer and use circular DMA transfer

Im using the STM32F303 Discovery Board.我正在使用 STM32F303 探索板。 I want to trigger a row of ADC conversions to fill my DMA buffer every time my timer triggers.每次我的计时器触发时,我都想触发一行 ADC 转换以填充我的 DMA 缓冲区。 I am using the HAL, this problem would have probably been solved easier with bare metal, I know.我正在使用 HAL,我知道使用裸机可能更容易解决这个问题。

Ive found already this post and the answer helped me quite alot, but I still seem to have problems getting it to run.我已经找到了这篇文章,答案对我帮助很大,但我似乎仍然无法运行它。 How to do a adc conversion every 1us with Nucleo-F303K8? 如何使用 Nucleo-F303K8 每 1us 进行一次 adc 转换?

Either Im getting the ADC to convert constantly with its sample time or when Im using the timer as trigger input I get exaclty one conversion.我让 ADC 以其采样时间不断转换,或者当我使用定时器作为触发输入时,我得到了精确的一次转换。

Here is my initialisation code for the ADC and timer:这是我的 ADC 和定时器的初始化代码:

void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_MultiModeTypeDef multimode = {0};
  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */
  /** Common config
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
  hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
      adcErrorHandler();
  }
  /** Configure the ADC multi-mode
  */
  multimode.Mode = ADC_MODE_INDEPENDENT;
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
      adcErrorHandler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_2;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.SamplingTime = ADC_SAMPLETIME_61CYCLES_5;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
      adcErrorHandler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}

static void MX_TIM3_Init(void)
{

  /* USER CODE BEGIN TIM3_Init 0 */

  /* USER CODE END TIM3_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM3_Init 1 */

  /* USER CODE END TIM3_Init 1 */
  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 72-1;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 100;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM3_Init 2 */

  /* USER CODE END TIM3_Init 2 */

}

Im starting the timer and ADC with我开始定时器和ADC

HAL_TIM_Base_Start(&htim3);
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc1SampleBuffer, SAMPLESIZE);

The DMA is configured to be circular: DMA 配置为循环:

Cube DMA config立方体DMA配置

Im using then the following callbacks to get my Samples:我使用以下回调来获取我的样本:

void HAL_ADC_ConvHalfCpltCallback (ADC_HandleTypeDef * hadc)
void HAL_ADC_ConvCpltCallback (ADC_HandleTypeDef * hadc)

I have figured it out myself, the settings for ContinuousConvMode and DiscontinuousConvMode have to be:我自己弄明白了,ContinuousConvMode 和 DiscontinuousConvMode 的设置必须是:

  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = ENABLE;

That way it works like intended to trigger conversions only on timer and when the buffer is full or halffull it triggers the callbacks.这样它就像打算只在计时器上触发转换一样工作,当缓冲区已满或半满时,它会触发回调。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM