2025-05-13 7:55 AM - last edited on 2025-05-13 8:03 AM by Andrew Neil
(I'm using NUCLEO-F103RB)
Hello,
I'm currently working on a BLDC motor control project using STM32CubeMX and STM32CubeIDE with STM32 TIM1 peripheral.
I have configured TIM1 in Center-Aligned PWM Mode 2, with:
Prescaler = 3
ARR = 899
So, PWM frequency is 10kHz (from a 72MHz system clock).
In this mode, since the counter counts up and down between 0 and ARR, the counter reaching ARR marks the exact midpoint of the PWM ON time.
I would like to trigger an ADC conversion exactly at that point (i.e., at 50% of the ON time).
To do this, I thought of using TRGO = Update Event, since the update event happens when CNT = ARR in Center-Aligned Mode 2.
However, I am not fully sure if this is guaranteed to occur at that midpoint and whether it's the most precise method.
:question_mark:My questions are:
Is TRGO = Update Event guaranteed to occur exactly when CNT = ARR in Center-Aligned Mode 2?
Is this the best practice to trigger ADC at the center of the PWM ON duration?
If not, is there a more accurate or recommended method?
Any insight or clarification would be greatly appreciated.
Thank you in advance!
2025-05-27 7:45 AM
Hello,
can you please also share the ADC configuration or better whole project? What is the real value of "FSW_26KHZ"? In ADC configuration there should be set External Trigger Conversion Source to Timer 1 Trigger Out event 2.
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2025-05-28 12:41 AM
Dear HI_st
FSW_26KHZ value is 799. External Trigger Conversion Source is selected as Timer 1 Trigger Out event 2. I'm attaching the ADC configuration code here. Thanks.
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.LowPowerAutoPowerOff = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 7;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T1_TRGO2;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_7CYCLES_5;
hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_1CYCLE_5;
hadc1.Init.OversamplingMode = DISABLE;
hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
2025-05-28 12:49 AM
Dear Waclawek,
I'm a beginner in the ST Community. I just found this post almost similar to my issue. That's why I raised my issue in this post. Sorry, I don't want to hijack your thread. I'll do the necessary things to avoid this. Thanks.
2025-05-28 1:04 AM
I tried to configure ADC and TIM1 as it is in your project and it works to me right on my NUCELO board (ADC is periodically triggered and converted value is printed out). Why did you set DMAContinuousRequests as ENABLED, are you reading ADC value by DMA? if yes please share also DMA settings and code where you enabling ADC, DMA, TIM1 an all its interrupts.
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2025-05-28 3:11 AM
Dear HI_st,
Yes, I'm reading ADC Value by DMA. Here is the code,
GPIO_InitStruct.Pin = Pot1_Pin|Pot2_Pin|Pot3_Pin|Pot4_Pin
|Pot5_Pin|Pot6_Pin|Pot7_Pin;
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 = DMA1_Channel1;
hdma_adc1.Init.Request = DMA_REQUEST_ADC1;
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_WORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_adc1.Init.Mode = DMA_CIRCULAR;
hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc1);
/* ADC1 interrupt Init */
HAL_NVIC_SetPriority(ADC1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(ADC1_IRQn);
2025-05-28 6:16 AM
This settings also seems to be right. Try to compare your project with attached example it works fine to me. Can you also share the code where you turning on the TIM1, DMA and ADC?
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.