Skip to main content
Visitor II
March 11, 2018
Question

ADC regular conversion mode with DMA on with external triger source

  • March 11, 2018
  • 2 replies
  • 1785 views
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]

    This topic has been closed for replies.

    2 replies

    Super User
    March 11, 2018
    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

    Jems OnAuthor
    Visitor II
    March 12, 2018
    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 ?

    Super User
    March 12, 2018
    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

    Graduate II
    February 18, 2025

    i know this is an old question.
    But im facing a similar issue with an stm32G4 (HRTIM) https://community.st.com/t5/stm32-mcus-products/adc-measuring-only-high-side-of-centered-mode-pwm-hrtim/m-p/773768

    As @Jems On  says i just want to measure during high side of pulses when in PWM centered mode.
    Dinamically change the ADC sampling time as @John Craven said is not an option

    The two solutions i have right now are not ideal:

    1. Measuring high and low side pulses anyway and do some buffer filtering trick.
    2. Add more Triggers dedicated just for ADC and update them so they are aligned with high duty cycle also in the logic of my code.

    Edit: i ended up using a dedicated CR just to trigger ADC and setting it up to Timer period.