Skip to main content
massimiliano2399
Associate
September 20, 2016
Question

Trigger ADC1 scan using TIM1 CC1 on F410RB

  • September 20, 2016
  • 3 replies
  • 2321 views
Posted on September 20, 2016 at 13:08

Hi,

I use STM32F410RB, and I need to trigger an ADC1 scan regular conversion every TIM1 CC1 event.

I am sure that TIM1 works, because I have an interrupt that is triggered every CC1 event.

I tried to configure ADC as follows:


ADC_ChannelConfTypeDef sConfig;


/* ADC Initialization */

AdcHandle.Instance = ADC1;


AdcHandle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;

AdcHandle.Init.Resolution = ADC_RESOLUTION_12B;

AdcHandle.Init.ScanConvMode = ENABLE;

AdcHandle.Init.ContinuousConvMode = DISABLE;

AdcHandle.Init.DiscontinuousConvMode = DISABLE;

AdcHandle.Init.NbrOfDiscConversion = 0;

AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;

AdcHandle.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;

AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT;

AdcHandle.Init.NbrOfConversion = 2;

AdcHandle.Init.DMAContinuousRequests = DISABLE;

AdcHandle.Init.EOCSelection = ADC_EOC_SINGLE_CONV;


HAL_ADC_Init(&AdcHandle);


/* Configure ADC3 regular channel */

sConfig.Channel = ADC_CHANNEL_0;

sConfig.Rank = 1;

sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;

sConfig.Offset = 0;


HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);


/* Configure ADC3 regular channel */

sConfig.Channel = ADC_CHANNEL_1;

sConfig.Rank = 2;

sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;

sConfig.Offset = 0;


HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);


HAL_ADC_Start_IT(&AdcHandle);

But ADC no interrupt is triggered.

Which register, which bit are involved in the configuration?

best regards

Max

#adc #timer #stm32f410rb

Note: this post was migrated and contained many threaded conversations, some content may be missing.
This topic has been closed for replies.

3 replies

Walid FTITI_O
Visitor II
September 21, 2016
Posted on September 21, 2016 at 11:51

Hi cialdi.massimiliano,

To trigger ADC each TIM cc1 event , you should apply the following modfication :

- Enable

DiscontinuousConvMode

- Enable

DMAContinuousRequests

- Configure DMA

I recommend to check further for more help the example ''ADC_RegularConversion_DMA'' : STM32Cube_FW_F4_V1.13.0\Projects\STM324xG_EVAL\Examples\ADC\ADC_RegularConversion_DMA

-Hannibal-

Dana Myers
Senior
November 7, 2017
Posted on November 07, 2017 at 11:59

 ,

 ,

Are you sure this is correct?

From ,STM32Cube_FW_F4_V1.17.0\Projects\STM324xG_EVAL\Examples\ADC\ADC_RegularConversion_DMA:

/* ♯ ♯ -1- Configure the ADC peripheral ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ */

 ,

AdcHandle.Instance = ADCx,

 ,

 ,

AdcHandle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2,

 ,

AdcHandle.Init.Resolution = ADC_RESOLUTION_12B,

 ,

AdcHandle.Init.ScanConvMode = DISABLE,

 ,

AdcHandle.Init.ContinuousConvMode = ENABLE,

 ,

AdcHandle.Init.DiscontinuousConvMode = DISABLE,

 ,

AdcHandle.Init.NbrOfDiscConversion = 0,

 ,

AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE,

 ,

AdcHandle.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1,

 ,

AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT,

 ,

AdcHandle.Init.NbrOfConversion = 1,

 ,

AdcHandle.Init.DMAContinuousRequests = ENABLE,

 ,

AdcHandle.Init.EOCSelection = DISABLE,

This does not seem to enable conversions triggered by TIM1 CC1 with ,ADC_EXTERNALTRIGCONVEDGE_NONE.

nico 2010
Associate
October 28, 2017
Posted on October 28, 2017 at 10:24

Hello,

I faced with the same problem.

Insert

hadc1.Instance->CR2 |= ADC_CR2_SWSTART;

in stm32f4xx_it.c 

where TIM IRQ is handled.

It is a bug in library.

Best regards

Dana Myers
Senior
November 7, 2017
Posted on November 07, 2017 at 12:08

What you describe is manually triggering conversions from software in an interrupt service routine; that's not what the hardware is supposed to do and incurs interrupt service overhead.

What I found to work on the STM32F410RB here is to configure TIM1 CC1 for 'Toggle Output', then configure ADC1 to trigger on TIM1 CC1 on both rising and falling edges. I am using DMA but believe that's not related to this.

The initialization produced by STM32CubeMX:

TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_TOGGLE;

TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE;

TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_DISABLE;

TIM_OC_InitStruct.CompareValue = 0;

TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH;

TIM_OC_InitStruct.OCNPolarity = LL_TIM_OCPOLARITY_HIGH;

TIM_OC_InitStruct.OCIdleState = LL_TIM_OCIDLESTATE_LOW;

TIM_OC_InitStruct.OCNIdleState = LL_TIM_OCIDLESTATE_LOW;

LL_TIM_OC_Init(TIM1, LL_TIM_CHANNEL_CH1, &TIM_OC_InitStruct);

and:

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;

hadc1.Init.DiscontinuousConvMode = DISABLE;

hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISINGFALLING;

hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;

nico 2010
Associate
November 8, 2017
Posted on November 08, 2017 at 08:32

Hello!

I see you use a mixture of LL and HAL and I don't work with LL libraries.

What I want to say is that using this settings for ADC1 and TIMER1, ADC didn't read any value until I made the modification in Timer1 IRQ Handler, like below. So I guess that is a bug in the library of ADC, as I said in my topic 'Nucleo F410RB ADC dilema'.

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;

hadc1.Init.DiscontinuousConvMode = ENABLE;

hadc1.Init.NbrOfDiscConversion = 1;

hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISINGFALLING;

hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC2;

hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;

hadc1.Init.NbrOfConversion = 1;

hadc1.Init.DMAContinuousRequests = DISABLE;

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

sConfig.SamplingTime = ADC_SAMPLETIME_112CYCLES;

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

{ _Error_Handler(__FILE__, __LINE__); } }

static void MX_TIM1_Init(void)

{

  TIM_ClockConfigTypeDef sClockSourceConfig;

  TIM_MasterConfigTypeDef sMasterConfig;

  TIM_OC_InitTypeDef sConfigOC;

  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;

  htim1.Instance = TIM1;

  htim1.Init.Prescaler = 0;

  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;

  htim1.Init.Period = 1000;

  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

  htim1.Init.RepetitionCounter = 0;

  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;

  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }

  if (HAL_TIM_OC_Init(&htim1) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC2REF;

  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;

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

  {

    _Error_Handler(__FILE__, __LINE__);

  }

  sConfigOC.OCMode = TIM_OCMODE_TIMING;

  sConfigOC.Pulse = 100;

  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;

  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;

  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;

  if (HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }

  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;

  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;

  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;

  sBreakDeadTimeConfig.DeadTime = 0;

  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;

  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;

  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;

  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }

}

void TIM1_CC_IRQHandler(void)

{

  /* USER CODE BEGIN TIM1_CC_IRQn 0 */

    HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin);

    hadc1.Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART;

  /* USER CODE END TIM1_CC_IRQn 0 */

  HAL_TIM_IRQHandler(&htim1);

  /* USER CODE BEGIN TIM1_CC_IRQn 1 */

  /* USER CODE END TIM1_CC_IRQn 1 */

}

Dana Myers
Senior
November 8, 2017
Posted on November 08, 2017 at 21:40

I was beginning to conclude the same thing myself. As much as I rather like the STM32 parts, using them is sometimes a bit of an 'adventure'.

Thank you for the help (and

Preda.Cristinel

‌ you probably want to review your code that's using an ISR; it's probably not what you

really want and this is).