cancel
Showing results for 
Search instead for 
Did you mean: 

ADC DMA data transfer not triggering with timer on STM32f7 Discovery board

ConfusedContrarian
Associate III

Hi, I'm trying to use the STM32F7 to perform the FFT of a signal connected to ADC1 Channel 0 on my discovery board and I'm having trouble getting the TIMER 2 to trigger the conversion. When debgugging, it seems the DMA function isn't called at all. This is what my code looks like:

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_ADC1_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_TIM2_Init(void);
 
uint16_t uhADCxConvertedValue;
 
int main(void)
{
  HAL_Init();
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  MX_USART1_UART_Init();
  MX_TIM2_Init();
 
// Start Running ADC.	
  if(HAL_ADC_Start_DMA(&hadc1, (uint32_t*) &uhADCxConvertedValue, 1) != HAL_OK)
  {
        Error_Handler();
  }
	
// STart Running Timer:
//Enable and start peripheral counter
 if(HAL_TIM_Base_Start(&htim2) != HAL_OK)
 {
	 Error_Handler();
 }
	
 while (1)
  {
 
  }
 
}

My DMA, ADC and TIMER Initialisation functions look like this:

static void MX_ADC1_Init(void)
{
 
  ADC_ChannelConfTypeDef sConfig;
 
    /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
    */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE; // Triggered by Timer 2
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
  hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T2_TRGO; 
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
    /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
    */
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_56CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
	
}
 
/* TIM2 init function */
static void MX_TIM2_Init(void)
{
 
  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_MasterConfigTypeDef sMasterConfig;
 
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 0;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 2159; // or 1080 depending on clarification of the APB1 Prescaler.. for a 100KhZ frequency
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
 
	/* TIM2 TRGO selection */
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
	
	//
}
 
static void MX_DMA_Init(void) 
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA2_CLK_ENABLE();
 
  /* DMA interrupt init */
  /* DMA2_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
 
}
 

and finally, the HAL_ADC_MspInit Function is:

void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
 
  GPIO_InitTypeDef GPIO_InitStruct;
  if(hadc->Instance==ADC1)
  {
  /* USER CODE BEGIN ADC1_MspInit 0 */
 
  /* USER CODE END ADC1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_ADC1_CLK_ENABLE();
  
    /**ADC1 GPIO Configuration    
    PA0/WKUP     ------> ADC1_IN0 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
    /* ADC1 DMA Init */
    /* ADC1 Init */
    hdma_adc1.Instance = DMA2_Stream0;
    hdma_adc1.Init.Channel = DMA_CHANNEL_0;
    hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
    hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_adc1.Init.Mode = DMA_CIRCULAR;
    hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }
 
    __HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);
 
  /* USER CODE BEGIN ADC1_MspInit 1 */
 
  /* USER CODE END ADC1_MspInit 1 */
  }
 
}

Can anyone please help point me in the right direction?

1 ACCEPTED SOLUTION

Accepted Solutions
ConfusedContrarian
Associate III

It seems TIMER2 doesn't trigger the ADC using a Trigger update. I switched to Timer 1 and that seemed to solve my issue. However, I'm now facing another issue. The buffer isn't filled and some samples are missing0690X0000088ScQQAU.png

WOuld it be better to open another thread?

View solution in original post

4 REPLIES 4

Make sure the memory address chosen for the buffer is appropriate for the DMA unit involved. Check RM diagrams, and address being used.

Check the DMA unit for reported errors.

Check the DMA/TIM/ADC units in the debugger for correct/expected configuration/settings.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
MNapi
Senior III

I had the same problem with other board, There are some bugs, try to work around use

setup first

HAL_TIM_Base_Start_IT(&htim2);

and as global intrupt in Cube MX. also ADC setup as interrupt trigger after all conversions

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

 UNUSED(htim);

   if (htim -> Instance == TIM2)

   {

   HAL_ADC_Start_DMA(&hadc1, (uint32_t*)array, 1000);

   }

}

you might need to stop it in another call back before running again.

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)

{

 UNUSED(hadc);

  HAL_ADC_Stop_DMA(&hadc1);

   

}

setup circular in Cube MX you would assume that setting DMA as normal would work but it did not. It had to be setup as circular.

and declare array as uint32_t

I noticed that declaring array as uint16_t might not work

ConfusedContrarian
Associate III

It seems TIMER2 doesn't trigger the ADC using a Trigger update. I switched to Timer 1 and that seemed to solve my issue. However, I'm now facing another issue. The buffer isn't filled and some samples are missing0690X0000088ScQQAU.png

WOuld it be better to open another thread?

S.Ma
Principal

To debug, output timer trigger to a gpio and connect it to the adc trigger input pin so you can pinpoint if the issue is on timer or adc+dma side.