Skip to main content
yabool2001
Associate III
September 27, 2023
Solved

Solution to avoid immediate TIM IRQ in CMSIS.

  • September 27, 2023
  • 2 replies
  • 2039 views

Hi,

I 'm trying to code TIM to count 5s for me using CMSIS. Using the code snippet provided below I got IRQ immediately.

RCC->APBENR2 |= RCC_APBENR2_TIM16EN ; // Enable TIM16 clock
TIM16->PSC = 16000 - 1 ; // 1 ms
TIM16->ARR = 10000 - 1 ; // 10 s = 10000 * 1 ms
TIM16->DIER |= TIM_DIER_UIE ; // Enable interrupt generation
NVIC_SetPriority ( TIM16_IRQn , 0 ) ; // Configure interrupt priority
NVIC_EnableIRQ ( TIM16_IRQn ) ; // Enable interrupt
TIM16->CR1 |= TIM_CR1_CEN ; // Start count TIM16

 I know the solution for HAL to avoid immediate IRQ would be:

 

__HAL_TIM_CLEAR_IT ( &htim16 , TIM_IT_UPDATE ) ;

 

Please help to find relevant solution in CMSIS, because I stucked.

Here is entire code .

V/r

yabool2001

 

This topic has been closed for replies.
Best answer by waclawek.jan

Prescaler is unconditionally preloaded, so the value you write to it does not get applied until the next Update. In other words, during the first timer period timer works with the default PSC=0, which given you are setting it to relatively high value, is observed as "update happens immediately".

One solution is to

  1. write new value to TIMx_PSC
  2. force Update by setting TIMx_EGR.UG
  3. clear Update flag in TIMx_SR

Btw. for clearing flags in TIMx_SR, don't use RMW, write the value directly.

JW

2 replies

Issamos
Super User
September 27, 2023

Hello @yabool2001 

I think you should put the bit UIF of the TIMx_SR register to 0 before enabling the TIMER.

Best regards.

II

yabool2001
Associate III
September 28, 2023

Hello Issamos,

It's not enough. waclawek.jan recommend 1 more crucial point (Force EGR.UG update):

TIM16->EGR |= TIM_EGR_UG ; // Force EGR.UG update
TIM16->SR &= ~TIM_SR_UIF ; // Clear UIF Flag

 and it works.

V/r

yabool2001

Piranha
Principal III
September 28, 2023

Jan also told you to not use RMW operations!

TIM16->EGR = TIM_EGR_UG;
TIM16->SR = ~TIM_SR_UIF;

And no - it's not just because of efficiency, but because the code with RMW is broken.

waclawek.jan
waclawek.janBest answer
Super User
September 28, 2023

Prescaler is unconditionally preloaded, so the value you write to it does not get applied until the next Update. In other words, during the first timer period timer works with the default PSC=0, which given you are setting it to relatively high value, is observed as "update happens immediately".

One solution is to

  1. write new value to TIMx_PSC
  2. force Update by setting TIMx_EGR.UG
  3. clear Update flag in TIMx_SR

Btw. for clearing flags in TIMx_SR, don't use RMW, write the value directly.

JW

yabool2001
Associate III
September 28, 2023

Outstanding ! Thank you very much for your help. Following solution works:

RCC->APBENR2 |= RCC_APBENR2_TIM16EN ; // Enable TIM16 clock
TIM16->PSC = 16000 - 1 ; // write prescaler 0,001 s. My system clock is 16 000 000 Hz
TIM16->EGR |= TIM_EGR_UG ; //Clear EGR force Update
TIM16->SR &= ~TIM_SR_UIF ; //Clear UIF Flag
TIM16->DIER |= TIM_DIER_UIE ; // Enable interrupt generation
NVIC_SetPriority ( TIM16_IRQn , 0 ) ; // Configure interrupt priority
NVIC_EnableIRQ ( TIM16_IRQn ) ; // Enable interrupt
TIM16->ARR = 5000 - 1 ; // 5 s = 5000 * 0,001s (prescaler value)
TIM16->CR1 |= TIM_CR1_CEN ; // Start counting

 V/r

yabool2001