STM32 - TIMx values question...

Hi all!

Hope all is well for you all.

Okay, I’ve been playing around with timers/interrupts on the STM32 for a few days now, and I’ve come to a mental block in regards to the actual values for the prescaler and period etc :?

I’ve looked at the manuals, and code etc., and am now just confusing myself! So I thought I would just ask the group and see if someone can just set me straight…

Lets say I have my sysclock set to 72MHz.

I want to set TIM3 to be at 1KHz (actually you can pick any number…)

How do I calculate the values (prescaler, period, etc?)

I’m sure on page xyz of the manual it shows the formula, I’ve just become blind/blocked and now cannot see anything in my minds eye… :!:

Here is a code sample that comes close to 1KHz, I used a scope and adjusted numbers until I got there…did not calculate the numbers…

#include "stm32f10x_conf.h"
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_tim.h"
#include "misc.h"

// TIM2 callback handler
void TIM2_IRQHandler()
{
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

    // toggle bit
    GPIOC->ODR ^= GPIO_Pin_12;
}

void RCC_Configuration(void)
{
    /* Enable TIM2
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
}

void TIM_Configuration(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;

    /* TIM2 configuration */
    TIM_TimeBaseStructure.TIM_Period = 132; // 133
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;    
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0000;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    TIM_OCStructInit(&TIM_OCInitStructure);

    /* Output Compare Timing Mode configuration: Channel1 */
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
    TIM_OCInitStructure.TIM_Pulse = 0x0;  
    TIM_OC1Init(TIM2, &TIM_OCInitStructure);

    /* TIM2 enable counter */
    TIM_Cmd(TIM2, ENABLE);

    /* Immediate load of TIM2 Precaler value */
    TIM_PrescalerConfig(TIM2, ((SystemCoreClock/1200) - 1), TIM_PSCReloadMode_Immediate);

    /* Clear TIM2 update pending flag */
    TIM_ClearFlag(TIM2, TIM_FLAG_Update);

    /* Enable TIM2 Update interrupt */
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
}

int main(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    /* Configure the system clocks */
    RCC_Configuration();

    /* Enable the GPIO_LED Clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

    // config port
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOC, &GPIO_InitStructure);

    /* Configure TIMs */
    TIM_Configuration();

    /* Configure two bits for preemption priority */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    /* Enable the TIM2 Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    while(1)
    {
    }
}

Many thanks in advance!

In fact, the principle of this is simple.

The prescaler is a simple frequency divider. If you have 4MHz in, with DV4, you have 1MHz out.

And endly, the count value is the simplest - the timer counts to this value, generates IRQ if set, then restarts.

At 1KHz, my timer module is set like this:

TInit->TIM_Period = 2; 
TInit->TIM_Prescaler = 72 << 9;

This way, the total clock division is (72 << 9) * 2.

Giving us a division factor of 73k - Please notice that 72M / 73k is roughly 1kHz. :slight_smile:

If I’m unclear, please tell me. I’ve been working two days to get it to work, last week…

Hi Gwen,

Okay, can you show me mathematically how you get the following numbers.

I have a 72MHz clock

I would like a 5 khz clock (or close enough)

Can you tell me step by step how you figure out the values?

Thanks!

Well, a timer is a frequency divider plus a counter.

From 72MHz to 5KHz, I would get a 10khz clock trough the prescaler (which is simply the frequency divider), then simply count from 0 to 1 - further dividing the clock by 2, giving you 5Khz.

The prescaler should then be at a value of 7200, giving a timer signal @ 10KHz, and the timer value of 1.

This an example, there is tens of possible combinations. I personally like setting the prescaler to 1Khz output so I count in milliseconds.

Hi,

You should consider the whole clock tree, the timers are not fed directly from the sysclk but sysclk/ahb_prescaler/apb1_prescaler so usually the timers clock is 36MHz, not 72MHz but it may be even lower depending on the prescalers settings.

You better read very carefully the section 6 if the reference manual, especially the Figure 8.

If you need some STM32 sample code follow the link in my signature (however it does not use the ST library, it is wasted code IMO).

Giovanni

Note, for the moderators, please forgive me but I hit the “report” button by mistake instead of reply…