cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F051 TIM2 counting way too fast?

Philipp Krause
Senior II
Posted on February 20, 2018 at 10:27

I'm trying to use TIM2 on the STM32F0-Discovery board (I am new to the STM32, but have used the STM8 before).

I setup TIM2 and USART1, then in a loop I send the value of TIM2_CNT via the USART1, so I can see how TIM2 counts. Since the USART1 stuff is working at the intended 9600 baud, I am confident that the basic clock setup is there and the STM32F0 is running at 8 Mhz.

However, I see TIM2_CNT count at about 50 Mhz, no matter the value of TIM2_PSC.

Here is my initialization code:

&sharpinclude <stdint.h>

&sharpdefine TIM2_BASE    0x40000000

&sharpdefine TIM2_CR1    (*(volatile uint16_t *)(TIM2_BASE + 0x00))

&sharpdefine TIM2_CNT    (*(volatile uint32_t *)(TIM2_BASE + 0x24))

&sharpdefine TIM2_PSC    (*(volatile uint16_t *)(TIM2_BASE + 0x28))

&sharpdefine RCC_BASE    0x40021000

&sharpdefine RCC_APB2ENR    (*(volatile uint32_t *)(RCC_BASE + 0x18))

&sharpdefine RCC_APB1ENR    (*(volatile uint32_t *)(RCC_BASE + 0x1c))

&sharpdefine GPIOA_BASE    0x48000000

&sharpdefine GPIOA_MODER    (*(volatile uint32_t *)(GPIOA_BASE + 0x00))

&sharpdefine GPIOA_AFRH    (*(volatile uint32_t *)(GPIOA_BASE + 0x24))

&sharpdefine USART1_BASE    0x40013800

&sharpdefine USART1_CR1    (*(volatile uint32_t *)(USART1_BASE + 0x00))

&sharpdefine USART1_BRR    (*(volatile uint32_t *)(USART1_BASE + 0x0c))

&sharpdefine USART1_ISR    (*(volatile uint32_t *)(USART1_BASE + 0x1c))

&sharpdefine USART1_TDR    (*(volatile uint32_t *)(USART1_BASE + 0x28))

void init(void)

{

    RCC_AHBENR |= (1ul << 17); // Enable I/O A

    RCC_APB2ENR |= (1ul << 14); // Enable USART1

    RCC_APB1ENR |= (1ul << 0); // Enable Timer 2

    // Use PA9, PA10 for USART instead of GPIO.

    GPIOA_MODER |= (0x2ul << 18) | (0x2ul << 20);

    GPIOA_AFRH |= (0x1ul << 4) | (0x1ul << 8);

    // 9600 baud, 1 start bit, 8 data bits, 1 stop bit.

    USART1_BRR = 8000000 / 9600;

    USART1_CR1 = 0xd;

    // Set timer to 1000 ticks per second?

    TIM2_PSC = 8000;

    TIM2_CR1 = (1ul << 0);

}

Philipp

#stm32f0 #tim2 #timer
1 ACCEPTED SOLUTION

Accepted Solutions
Posted on February 20, 2018 at 10:56

Philipp,

The prescaler is - in ST's parlance - preloaded, which means, that the value from PSC won't get used until Update event (i.e. 'overflow') occurs. As TIM2 is a 32-bit register and the reset value of ARR is 0xFFFFFFFF, even at 48MHz it takes cca 90 seconds until this happens. You can force an update by setting TIMx_EGR.UG (but that then sets the TIMx_SR.UIF which in turn fires an interrupt if enabled, this often confuses newbies as the 'libraries' do exactly this).

Please get a debugger, GDB+OpenOCD will do with the STLink onboard the Discos. Observe TIM2 behaviour from there (yes the debugger is intrusive, due to HW-triggers-upon-read registers e.g. the CCxIF bits in TIMx_SR, but for this simple purpose it's fine).

JW

PS What in the licence of device headers ([Cube or SPL]\Drivers\CMSIS\Device\ST\[STM32xxxxx]\Include\) makes you feel them being not free? Not using them (symbols and constants from there) just adds another layer of uncertainty.

View solution in original post

1 REPLY 1
Posted on February 20, 2018 at 10:56

Philipp,

The prescaler is - in ST's parlance - preloaded, which means, that the value from PSC won't get used until Update event (i.e. 'overflow') occurs. As TIM2 is a 32-bit register and the reset value of ARR is 0xFFFFFFFF, even at 48MHz it takes cca 90 seconds until this happens. You can force an update by setting TIMx_EGR.UG (but that then sets the TIMx_SR.UIF which in turn fires an interrupt if enabled, this often confuses newbies as the 'libraries' do exactly this).

Please get a debugger, GDB+OpenOCD will do with the STLink onboard the Discos. Observe TIM2 behaviour from there (yes the debugger is intrusive, due to HW-triggers-upon-read registers e.g. the CCxIF bits in TIMx_SR, but for this simple purpose it's fine).

JW

PS What in the licence of device headers ([Cube or SPL]\Drivers\CMSIS\Device\ST\[STM32xxxxx]\Include\) makes you feel them being not free? Not using them (symbols and constants from there) just adds another layer of uncertainty.