2021-01-01 01:20 PM
Hi and happy new year,
Migrating from STM32F103 to STM32F303, I mostly copy&paste my code from STM32103 to STM32F303, and only adjust what's necessary. However, I am having troubles with the TIM2 peripheral. Before starting the counter, the CNT register shows the correct reset value of 0x0000. My ARR register is set to 499. When I start the timer, I do not enter my ISR. When I halt the program, I see that the counter has incremented far beyond my ARR value (11052779 when I halted the program). The ISR was not entered between CNT=0 and CNT=11052779).
When I let the program run for a while (couple of minutes), the counter keeps incrementing until an overflow occurs (counter value > 2^32), starting from 0 again. When this happens, I enter the ISR, service it and leave the ISR again. Then, my ISR gets entered every 500ms, as supposed.
Can anyone tell me, why the counter misses the first ARR, needs to go all the way up to 2^32, overflows, and then matches the ARR regularly in the required 500ms intervals? Comparing the ref manuals of these two microcontrollers, the only difference I notice is that TIM2 on the F303 is a 32bit counter.
To answer the question where the 500ms might come from:
I use internal 8MHz clock and a prescaler of 7999. This gives a counter frequency of 8MHz/(7999+1) = 1000. This yields a 1ms timer increment. Counting to 499 gives 500ms.
/**
* STM32F303CC General Purpose Timer
* Uses TIM2_CH2 (PA1): Triggers every 500ms and toggles an LED on PC13
* OC2M configuration: 000 Frozen Comparison between CCR2 and CNT does not affect OC2REF
*/
#include <stdint.h>
#include "stm32f3xx.h"
int main(void)
{
__NVIC_EnableIRQ(TIM2_IRQn);
// Check which bus PC13 sits on
RCC->AHBENR |= RCC_AHBENR_GPIOCEN;
uint8_t i = 0;
for(;i<255;i++);
i=0;
GPIOC->MODER |= GPIO_MODER_MODER13_0;
// Enables TIM2 bus
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
for(;i<255;i++);
i=0;
TIM2->CR1 |= TIM_CR1_ARPE | TIM_CR1_URS;
TIM2->DIER |= TIM_DIER_UIE;
TIM2->PSC = 7999;
TIM2->ARR = 499;
TIM2->CR1 |= TIM_CR1_CEN;
/* Loop forever */
for(;;);
}
void TIM2_IRQHandler(void)
{
static char flag = 0;
TIM2->SR &= ~TIM_SR_UIF;
if(flag)
{
GPIOC->BSRR = GPIO_BSRR_BR_13;
flag = 0;
}
else
{
GPIOC->BSRR = GPIO_BSRR_BS_13;
flag = 1;
}
}
Solved! Go to Solution.
2021-01-01 01:43 PM
Hello Happy new year.
Te ARR is preloaded. So will update in first update event.
Clear ARPE bit in CR1 before you load the ARR or leave it as is and before start counter, make an update event by setting UG bit in EGR (to update the ARR shadow reg)
2021-01-01 01:43 PM
Hello Happy new year.
Te ARR is preloaded. So will update in first update event.
Clear ARPE bit in CR1 before you load the ARR or leave it as is and before start counter, make an update event by setting UG bit in EGR (to update the ARR shadow reg)
2021-01-01 01:50 PM
Thank you very much. That makes sense. It works as expected now. Thank you.
Cheers,
2021-01-01 01:52 PM
Don't use this form TIM2->SR &= ~TIM_SR_UIF;
Use this one TIM2->SR = ~TIM_SR_UIF; it is designed to work with a single atomic write
Update is clocked into CNT == 0 state