2023-09-27 11:11 AM
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.
V/r
yabool2001
Solved! Go to Solution.
2023-09-28 12:15 AM
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
Btw. for clearing flags in TIMx_SR, don't use RMW, write the value directly.
JW
2023-09-27 11:20 AM - edited 2023-09-27 11:21 AM
Hello @yabool2001
I think you should put the bit UIF of the TIMx_SR register to 0 before enabling the TIMER.
Best regards.
II
2023-09-28 12:15 AM
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
Btw. for clearing flags in TIMx_SR, don't use RMW, write the value directly.
JW
2023-09-28 01:06 PM
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
2023-09-28 01:11 PM
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
2023-09-28 02:52 PM
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.
2023-10-01 03:01 AM
I missed it! I backed to Jan's link to g9 "STM32 gotchas" and found what you indicated "Performing RMW (&= or |=) with status registers is incorrect and dangerous".
It's corrected now. Thank you very much for your important remark.
V/r
yabool2001