cancel
Showing results for 
Search instead for 
Did you mean: 

ADC regular conversion mode with DMA on with external triger source

Jems On
Associate II
Posted on March 11, 2018 at 23:41

Hi !

I'm excited to join the ST community!

I hope someone can solve my problem.

I am experiencing timing issues when converting an ADC.

Here is the configuration of my project:

- The timer 3 is configured in center aligned mode, Trigger output ENABLE on update events, PWM signal generation

- ADC: Scan conversion mode enabled, DMA in continuous request ENABLE, NB of conversion: 4, EOC: flag at the end of all conversion.

External trigger source Timer 3 out event on rising edge.

What I want to do: I want to start the conversion of 4 channels(scan conversion) when the timer 3 is in the middle of the PWM pulse.

My problem: Actually my conversion seems well started on rising edge but also on falling edge.

I join screenshots of the oscilloscope illustrating the problem.

0690X00000604SwQAI.jpg

In blue it is the PWM signal.

In red is the time spent in the DMA2_Stream0_IRQhandler () function.

I do not understand two things about this capture: Why I do not fit in the DMA2_Stream0_IRQhandler () function in the middle of the high level and the low level because I am in the center aligned mode and that normally the UEV (update event) should be done

between.

Second remark it seems that the conversion is done on high level and on low level while I set externa trigger conversion conversion edge only on rising on rising edge ....

Here's another screenshot that shows the PWM signal and the time spent in the HAL_ADC_ConvCpltCallback () function.

Again we see that the conversions are on a rising and falling front.

0690X00000604T1QAI.jpg

I think I have to make a mistake in configuring my DMA ....

Here is the configuration generated from Cube MX:

[CODE]

/* ADC1 init function */

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 = ENABLE;

  hadc1.Init.ContinuousConvMode = DISABLE;

  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 = 4;

  hadc1.Init.DMAContinuousRequests = ENABLE;

  hadc1.Init.EOCSelection = ADC_EOC_SEQ_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_7;

  sConfig.Rank = 1;

  sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES;

  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != 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_14;

  sConfig.Rank = 2;

  sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES;

  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != 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_15;

  sConfig.Rank = 3;

  sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES;

  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != 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_5;

  sConfig.Rank = 4;

  sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;

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

  {

    _Error_Handler(__FILE__, __LINE__);

  }

}

/* TIM3 init function */

static void MX_TIM3_Init(void)

{

  TIM_SlaveConfigTypeDef sSlaveConfig;

  TIM_MasterConfigTypeDef sMasterConfig;

  TIM_OC_InitTypeDef sConfigOC;

  htim3.Instance = TIM3;

  htim3.Init.Prescaler = 0;

  htim3.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1;

  htim3.Init.Period = 1999;

  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }

  if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }

  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;

  sSlaveConfig.InputTrigger = TIM_TS_ITR3;

  if (HAL_TIM_SlaveConfigSynchronization(&htim3, &sSlaveConfig) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;

  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;

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

  {

    _Error_Handler(__FILE__, __LINE__);

  }

  sConfigOC.OCMode = TIM_OCMODE_PWM1;

  sConfigOC.Pulse = 500;

  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }

  HAL_TIM_MspPostInit(&htim3);

}

/**

  * Enable DMA controller clock

  */

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

}

[/CODE]

5 REPLIES 5
Posted on March 11, 2018 at 23:56

What is the expected duration of the 4 ADC conversions?

The DMA ISR is invoked at the end of them.

[EDIT]

It may perhaps confuse you that there are 2 conversions per PWM cycle  - but then there are also 2 Update events you are using as TRGO->ADC conversion start per period, in the up-down (a.k.a. center-aligned) mode:

0690X0000060A3iQAE.png

[/EDIT]

Btw., which STM32 are you using?

JW

Posted on March 12, 2018 at 09:31

First, thanks waclawek.jan for responding so quickly !

I'm using an STM32F413. HSE --> 84MHz

What I actually want to do is neither more nor less than what is described in the following picture :

0690X00000604TGQAY.jpg

I want to run a conversion cycle only in the middle of the high time of the PWM.

I understand that using UEV there are two events generated per PWM period.

Only I thought I would filter the first UEV using hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING; but maybe I don't understand the TRIGCONVEDGE_RISING option.

Is there a better configuration to make this ?

Posted on March 12, 2018 at 14:56

I honestly don't know.

Try setting TRGO to compare event of some of the channels, and then set that channel's CCRx equal to ARR.

JW

Posted on March 13, 2018 at 03:24

I think Jan is correct. The Update Events occur at the center of the pwm Pulse (overflow event) and the center of the gaps (underflow event). Using your second scope trace....

0690X0000060A5fQAE.png

The update events (green) are positioned as above.

Your 4 conversions take place over the intervals shown by the blue arrows, then followed by your EOC callbacks (red).

Do a test, shorten your adc conversion cycles to the minimum. The callbacks that currently look symmetric around the pwm pulse, will probably shift (not symmetric). The red pulse leading the pwm pulse will shift more to the center of the gap, and the lagging red pulse will shift to the center of the pulse. If shortened, your may finish inside the pwm pulse as you want. 

Basically your sampling twice, once in the gap, and a second time starting at the pulse center, but the conversion don't finish inside the pwm pulse!

As Jan suggested, using the compare events, the events occur on the rising edge and following edges of the pwm. Rising compare will get you sampling in the pulse, but not centered on the pulse.

Posted on March 13, 2018 at 03:52

You could set you adc clk and conversion cycles, and calculate the period required for the 4 channels.

Then add CH4 on timer, with a pulse width equal to the conversion period.

Use the compare event from CH4 at the trigger.

One event will center the samples on the CH1-CH3 pulses.

But you will have a second trigger and conversion cycle to deal with or discard.