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-13 8:05 AM - edited 2025-05-13 8:08 AM
Update event occurs both on CNT=0 and CNT=ARR.
If you want trigger only upon CNT=ARR, set one channel to CCRx=ARR+1 and trigger on that.
Note, that there may be a delay between the Compare event and ADC trigger, due to resynchronization if the timer is at a different bus than ADC (or maybe even if it's on the same bus). Also note, that ADC trigger starts the sampling process, the ADC conversion start is further delayed by the sampling time.
What's the reason to use particularly Center-Aligned Mode 2?
JW
2025-05-25 7:05 AM
I'm also facing the same issue in the STM32G030C8T6 series Controller. I want to trigger the ADC using the TRGO2 trigger event on a specific Output compare OC2REF of timer 1, but it's not working. It seems to be a CUBEMX code generation error or a Timer Library-related issue. @st, please help us resolve this issue.
2025-05-25 8:14 AM
Maybe show your work instead of just saying it doesnt work. No reason to doubt the reference manual.
2025-05-26 12:41 AM
Dear TDK, I'm sharing the code I tried, but it's not working. It's triggering only once, but not getting regular interrupts. I want to trigger the ADC using the TRGO2 trigger event on a specific Output compare OC4REF (Wrongly mentioned OC2REF in previous msg) of timer 1
void MX_TIM1_Init(void)
{
/* USER CODE BEGIN TIM1_Init 0 */
/* USER CODE END TIM1_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
/* USER CODE BEGIN TIM1_Init 1 */
/* USER CODE END TIM1_Init 1 */
htim1.Instance = TIM1;
htim1.Init.Prescaler = FSW_26KHZ_PSC;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = FSW_26KHZ;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 1;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_OC_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC2REF;
sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_OC4REF;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
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_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_ACTIVE;
sConfigOC.Pulse = 399;
if (HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
sConfigOC.Pulse = 99;
if (HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
{
Error_Handler();
}
__HAL_TIM_ENABLE_OCxPRELOAD(&htim1, TIM_CHANNEL_4);
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.BreakFilter = 0;
sBreakDeadTimeConfig.BreakAFMode = TIM_BREAK_AFMODE_INPUT;
sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
sBreakDeadTimeConfig.Break2Filter = 0;
sBreakDeadTimeConfig.Break2AFMode = TIM_BREAK_AFMODE_INPUT;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM1_Init 2 */
/* USER CODE END TIM1_Init 2 */
HAL_TIM_MspPostInit(&htim1);
}
2025-05-26 2:25 AM
> It's triggering only once, but not getting regular interrupts.
Are you talking about ADC interrupts? Maybe ADC does not convert upon the subsequent trigger, for example if it overflows. Read ADC chapter in RM.
JW
2025-05-26 6:43 AM
Dear Waclawek,
Yes, I'm talking about ADC working in Timer trigger interrupt Mode. ADC does its job perfectly if I select Trigger Event (TRGO2) as Update Event, but if I select OC4REF as Trigger Event (TRGO2) then it works only once.
Thanks.
2025-05-26 10:46 AM
> I'm using NUCLEO-F103RB
STM32F103 does not have TRGO2 in TIM1. See TIM1 and ADC chapters in RM0008.
JW
2025-05-27 4:44 AM
Dear Waclawek,
Ok, but I'm talking about the STM32G030C8T6 microcontroller.
Thanks.
2025-05-27 6:39 AM
I've just noticed that you are not the original poster.
Please don't hijack other threads - start your own. Present a coherent description of your problem. Describe your hardware setup, and also describe what is in your software. Describe your observations and how are they different from the expected behaviour.
Read out and check/post content of relevant registers - TIM, ADC, maybe DMA if you use it. Check, if the flags which are supposed to trigger the interrupt, are set or not. A generic "interrupt does not fire" checklist is here.
JW