Timer interrupt triggers immediately after interrupt enabled
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-09-25 2:20 PM
Hello all,
I want to disable the timer interrupt in the IRQ Handler and then enable again in the main loop. However the interrupt is triggered nearly immediately after I re-enable the interrupt (setting the UIE bit). I attached my code below. If I disable and enable the counter instead of just the interrupt then the code runs correctly. Why is that? I have tried to set the TIM_CR1_URS but no avail.
void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = 0;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 3333;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM2_Init();
HAL_TIM_Base_Start_IT(&htim2);
uint16_t c;
while (1)
{
if(int_count == 1)
{
int_count = 0;
HAL_GPIO_WritePin(GPIOA, TX_pin, 0);
__HAL_TIM_SET_COUNTER(&htim2, 0);
__HAL_TIM_ENABLE_IT(&htim2, TIM_IT_UPDATE);
}
c = 0xFFFF;
while(c)
{
c--;
}
}
}
void TIM2_IRQHandler(void)
{
if (__HAL_TIM_GET_FLAG(&htim2, TIM_FLAG_UPDATE) != RESET)
{
if (__HAL_TIM_GET_IT_SOURCE(&htim2, TIM_IT_UPDATE) != RESET)
{
__HAL_TIM_CLEAR_FLAG(&htim2, TIM_FLAG_UPDATE);
if(int_count == 0)
{
__HAL_TIM_DISABLE_IT(&htim2, TIM_IT_UPDATE);
HAL_GPIO_WritePin(GPIOA, TX_pin, 1);
int_count = 1;
}
}
}
return;
}
P/S: Side question: when I debugged the code, I notice that when I clear the interrupt flag with __HAL_TIM_CLEAR_FLAG, even though the code says the flag is cleared but I still see bit UIF set when looking at the timer register. Does anyone know why?
Solved! Go to Solution.
- Labels:
-
TIM
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-09-25 3:12 PM
The update interrupt will fire immediately after enabled in HAL_TIM_Base_Start_IT unless you clear it first. Note that if ARR=0, it'll get set immediately. So you need to set ARR, then clear the flag, then start the timer.
When debugging, the timer is still running unless you have timers disabled during debug so it gets set immediately again.
Mixing HAL calls with your own IRQ handler doesn't seem smart. You should call HAL_TIM_IRQHandler instead. Or just ditch HAL.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-09-25 3:12 PM
The update interrupt will fire immediately after enabled in HAL_TIM_Base_Start_IT unless you clear it first. Note that if ARR=0, it'll get set immediately. So you need to set ARR, then clear the flag, then start the timer.
When debugging, the timer is still running unless you have timers disabled during debug so it gets set immediately again.
Mixing HAL calls with your own IRQ handler doesn't seem smart. You should call HAL_TIM_IRQHandler instead. Or just ditch HAL.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-09-25 3:33 PM
"Mixing HAL calls with your own IRQ handler doesn't seem smart."
Why is that? I want to use HAL but the HAL interrupt handlers are too long so I decided to write my own.
Anw, adding __HAL_TIM_CLEAR_FLAG(&htim2, TIM_FLAG_UPDATE); before __HAL_TIM_ENABLE_IT(&htim2, TIM_IT_UPDATE); solves the problem.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2020-09-25 3:38 PM
The basic TIM stuff is pretty simple. If you just want to trigger an update interrupt at 500 Hz (or whatever) and you're concerned about speed, direct register access is easy to read. It also gives you finer control over how things are initialized and you can avoid stuff like the update interrupt firing immediately.
