cancel
Showing results for 
Search instead for 
Did you mean: 

Timer clock confusion.

jamessteward
Associate II
Posted on March 11, 2009 at 01:47

Timer clock confusion.

5 REPLIES 5
jamessteward
Associate II
Posted on May 17, 2011 at 13:05

Thanks fastmapper.

Your analysis of Figure 7 is different from mine... The diagram says ''If (APB1 prescaler = 1) x1 else x2''. Or is my copy wrong?

In code I have;

Code:

/* HCLK = SYSCLK */

RCC_HCLKConfig(RCC_SYSCLK_Div1);

/* PCLK2 = HCLK */

RCC_PCLK2Config(RCC_HCLK_Div1);

/* PCLK1 = HCLK/2 */

RCC_PCLK1Config(RCC_HCLK_Div2);

/* PLLCLK = 8MHz * 9 = 72 MHz */

RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

/* Enable PLL */

RCC_PLLCmd(ENABLE);

/* Wait till PLL is ready */

while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {

}

/* Select PLL as system clock source */

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

So I guess I've divided by 2, hence the timer clock is later multiplied by 2 - from 36 MHz to 72MHz just before the timers.

Page 316, section 13.4.11 Prescaler (TIMx_PSC) was the key. Now I understand where the problem lies. Yes, I should have RTFM again.

So because I am prescaling APB1 by 2, the resultant 36 MHz clock is multiplied by 2 before being fed into the timers.

The timer prescaler set to 1, has 1 added to it becoming 2, therefore 72MHz / 2 = 36MHz for the PWM out.

Yeah I got it now. Thanks.

jamessteward
Associate II
Posted on May 17, 2011 at 13:05

I have my STM32 running at 72 MHz, and APB1 at 36 MHz.

I have a PWM output running with the expected output frequency configured as;

Code:

/* Selects the internal clock for TIM2 */

TIM_InternalClockConfig(TIM2);

TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);

TIM_TimeBaseInitStruct.TIM_Prescaler = 1; //36 MHz / 1 = 36MHz

TIM_TimeBaseInitStruct.TIM_Period = 1536 - 1; //36MHz / 1536 = 23.4375kHz

TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;

TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);

However, I have timer 3 set up as;

Code:

/* Selects the internal clock for TIM3 */

TIM_InternalClockConfig(TIM3);

TIM_TimeBaseInitStruct.TIM_Prescaler = 72; //72 MHz / 72 = 1MHz

TIM_TimeBaseInitStruct.TIM_Period = 4000-1; //1MHz / 4000 = 250Hz

TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;

TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);

<snip>

/* TIM IT enable */

TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);

And in interrupt handler that simply toggles a GPIO, and this yields a toggle frequency on the GPIO of 250Hz. I.e., the ISR is being called at a rate of 250 Hz, which is what I want.

Why does the ISR get called at 250Hz, when TIM3 clock is really only 36 MHz?

Cheers,

James.

fastmapper
Associate II
Posted on May 17, 2011 at 13:05

According to figure 7 on page 68 of the STM32 reference manual (

http://www.st.com/stonline/products/literature/rm/13902.pdf

), the APB1 clock is multiplied by 2 before it is fed to the timers but only when the APB1 prescaler is 1.

Also, you should see page 319 because the prescale divisor is one greater than the value programmed into the prescaler register. For TIM2, this means you should be getting 72MHz / 2 / 1536 = 23440Hz and for TIM3 you should be getting 72MHz / 73 / 4000 = 246.6Hz. If your TIM3 prescaler were changed to 72 (by setting the prescaler register to 71) you may even get a resultant frequency closer to 250Hz than you are getting now.

[ This message was edited by: fastmapper on 10-03-2009 07:44 ]

fastmapper
Associate II
Posted on May 17, 2011 at 13:05

Quote:

Your analysis of Figure 7 is different from mine... The diagram says ''If (APB1 prescaler = 1) x1 else x2''. Or is my copy wrong?

That was my mistake. Your interpretation of the figure is correct.

What I should have said was ''with the AHB frequency of 72MHz, the APB1 prescaler must be 2 to produce 36MHz which is then multiplied by 2 to produce the APB1 timer clock frequency of 72MHz.'' The end result is that you have a 72MHz clock for the APB1 timers (including TIM2 and TIM3).

jamessteward
Associate II
Posted on May 17, 2011 at 13:05

Cool.

I've rewritten the TIM_Prescaler code to read

Code:

TIM_Prescaler = X - 1;

Same for TIM_Period. At least this helps me remember how it works!

I wish some of these intricacies were documented in the FWLib doco.

Cheers.