cancel
Showing results for 
Search instead for 
Did you mean: 

ADC_RegularConversion_DMA project question.

mbmail4
Associate II

Hi Everyone. I'm modifying a the example project "ADC_RegularConversion_DMA" for the STM32F4-Discovery board.

I now want it to work via TIM2 trigger. I would like TIM2 to trigger the ADC, and then the DMA to transfer the ADC result to a buffer.

The project works fine in the default mode, but when I add TIM2 and set it up to trigger the ADC, I'm not able to get the ADC to work.

Can this ADC,TIM, and DMA combination work on this CPU? and if so can anyone give me some advice on what extra modifications I may need?

Thanks

M.B

The setup I'm using is below:

 hadc3.Instance = ADC3;

 hadc3.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV8;

 hadc3.Init.Resolution = ADC_RESOLUTION_12B;

 hadc3.Init.ScanConvMode = DISABLE;

 hadc3.Init.ContinuousConvMode = ENABLE;

 hadc3.Init.DiscontinuousConvMode = DISABLE;

 hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;

 hadc3.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T2_TRGO;

 hadc3.Init.DataAlign = ADC_DATAALIGN_RIGHT;

 hadc3.Init.NbrOfConversion = 1;

 hadc3.Init.DMAContinuousRequests = ENABLE;

 hadc3.Init.EOCSelection = ADC_EOC_SEQ_CONV;

 if (HAL_ADC_Init(&hadc3) != HAL_OK)

 htim2.Instance = TIM2;

 htim2.Init.Prescaler = 0;

 htim2.Init.CounterMode = TIM_COUNTERMODE_UP;

 htim2.Init.Period = 1890;

 htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

 htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

 sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

 sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

  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_NORMAL;

  hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;

  hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

  if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)

  {

   Error_Handler();

  }

  __HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);

3 REPLIES 3

Should be HALFWORD into the ADC

Make sure DMA points to the ADC3->DR, check the register settings.

Check MMS bits in the TIM2->CR2

Check TIM2 clock enabled

Review DMA registers, check status/error conditions.

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

Hi.

Thanks for your reply Clive1.

After much confusion I was able to get the DMA to work correctly by setting the Half word into the ADC as you said above. In relation to my question above, I want to trigger the ADC from TIM2, and xfer the sampled data into RAM by DMA.

I have gone through some of the documentation in the ref manual, and stepped through the code so in answering the points you made above Clive, please see below, and by the way, during my confused state(still present), I have redone the project, sorry, it now uses ADC1 instead, but all else is the same.

Should be HALFWORD into the ADC

yep done

Make sure DMA points to the ADC3->DR, check the register settings.

hadc→Instance = ADC1

__HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);

Check MMS bits in the TIM2→CR2

Bits 6:4 MMS[2:0]: Master mode selection

010: Update - The update event is selected as trigger output (TRGO). For instance a master timer can then be used as a prescaler for a slave timer.

Check TIM2 clock enabled

HAL_TIM_Base_Start_IT(&htim2)

__HAL_TIM_ENABLE(htim);

Review DMA registers, check status/error conditions.

HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)

Going through the init functions, I cant seem to see anything that could cause an error.

Can anyone point me in the right direction?

thanks

mb

mbmail4
Associate II

The new settings are:

 hadc1.Instance = ADC1;

 hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4;

 hadc1.Init.Resolution = ADC_RESOLUTION_12B;

 hadc1.Init.ScanConvMode = DISABLE;

 hadc1.Init.ContinuousConvMode = DISABLE; /* Continuous mode disabled to have only 1 conversion at each conversion trig */

 hadc1.Init.DiscontinuousConvMode = DISABLE; /* Parameter discarded because sequencer is disabled */

 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;

 hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T2_TRGO; /* Conversion start trigger at each external event */

 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();

 }

 /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.

 */

 sConfig.Channel = ADC_CHANNEL_9;

 sConfig.Rank = 1;

 sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;

 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

 {

  Error_Handler();

 }

---------------------------------------------------------------------------------------------

 htim2.Instance = TIM2;

 htim2.Init.Prescaler = 0;

 htim2.Init.CounterMode = TIM_COUNTERMODE_UP;

 htim2.Init.Period = 1890;

 htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

 htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

 if (HAL_TIM_Base_Init(&htim2) != HAL_OK)

 {

  Error_Handler();

 }

 sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;

 sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

 if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)

 {

  Error_Handler();

 }

-----------------------------------------------------------------------------------------------------------

  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_NORMAL;

  hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;

  hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

  if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)

  {

   Error_Handler();

  }

  __HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);

-----------------------------------------------------------------------------------------------------------

the initialisation code in my main() is:

if(HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC_ConvertedValue, 16) != HAL_OK)

{

uart_puts(&huart2,"\r\nERROR: HAL_ADC_Start_DMA\r\n");

}

if(HAL_TIM_Base_Start_IT(&htim2) != HAL_OK)

{

uart_puts(&huart2,"\r\nERROR: HAL_TIM_Base_Start_IT\r\n");

}