cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 timer (Prescaler Value)

kazafwing
Associate II
Posted on January 24, 2013 at 03:46

Hi, I have just saw a program about a interrupt time. The program can let the LED on and off in a specified period. But I have some question about the prescaler value, can anyone help me to understand the prescale value of this case, thanks a lot. My problem is that, I don't know why the period value is 10000-1 for 1 ms delay, is there any equation for this case and why the prescaler value is 336-1 for 1MHz. Also, why the period and prescaler value is alway -1?

Thanks.

The program is as follow:

/**

  ******************************************************************************

  * @file    USART/main.c 

  * @author  Andrew Markham

  * @version V1.0.0

  * @date    27-April-2012

  * @brief   Main program body

  ******************************************************************************

  */ 

/* Includes ------------------------------------------------------------------*/

&sharpinclude ''stm32f4xx.h''

&sharpinclude <stdio.h>

/* Private typedef -----------------------------------------------------------*/

GPIO_InitTypeDef  GPIO_InitStructure;

TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

/* Private define ------------------------------------------------------------*/

/* Private macro -------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/

/* Private function prototypes -----------------------------------------------*/

void INTTIM_Config(void);

void LED_Config(void);

/* Private functions ---------------------------------------------------------*/

void TIM2_IRQHandler(void)

{

  if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)

  {

    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

GPIO_ToggleBits(GPIOD, GPIO_Pin_14);

    GPIO_ToggleBits(GPIOD, GPIO_Pin_13);

GPIO_ToggleBits(GPIOD, GPIO_Pin_12);

  }

}

/**

  * @brief  Main program

  * @param  None

  * @retval None

  */

int main(void)

{

  INTTIM_Config();

  /* LED Configuration */

  LED_Config();

  while (1)

  {  

  }

}

/**

  * @brief  Setup an interval timer

  * @param  None

  * @retval None

  */

void INTTIM_Config(void)

{

  NVIC_InitTypeDef NVIC_InitStructure;

  

  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;            /* Enable the TIM2 gloabal Interrupt */

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  /* value = 0 - 15*/

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;         /* value = 0 - 15*/

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

  /* TIM2 clock enable */

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

  /* Time base configuration */

  TIM_TimeBaseStructure.TIM_Period = 10000 - 1;  // 1 MHz down to 1 KHz (1 ms)

  TIM_TimeBaseStructure.TIM_Prescaler = 336 - 1; // 24 MHz Clock down to 1 MHz (adjust per your clock)

  TIM_TimeBaseStructure.TIM_ClockDivision = 0;

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  /* TIM IT enable */

  TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

  /* TIM2 enable counter */

  TIM_Cmd(TIM2, ENABLE);

}

void LED_Config(void)

{

  /* GPIOD Periph clock enable */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

  /* Configure PD12, PD13, PD14 and PD15 in output pushpull mode */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

  GPIO_Init(GPIOD, &GPIO_InitStructure);

}

&sharpifdef  USE_FULL_ASSERT

/**

  * @brief  Reports the name of the source file and the source line number

  *         where the assert_param error has occurred.

  * @param  file: pointer to the source file name

  * @param  line: assert_param error line source number

  * @retval None

  */

void assert_failed(uint8_t* file, uint32_t line)

{

  /* User can add his own implementation to report the file name and line number,

     ex: printf(''Wrong parameters value: file %s on line %d\r\n'', file, line) */

  while (1)

  {}

}

&sharpendif

/**

  * @}

  */ 

/**

  * @}

  */ 

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

#calculate-presc #stm32f2 #set-time-base #bxcan #filter
13 REPLIES 13
Posted on January 24, 2013 at 04:55

The comments don't jive with the values, hence you are rightly confused

Going from 1 MHz to 1 KHz you'd expect a 1000 -1 value

For a counter to have N states, it starts at 0 and counts up to N-1, the counter recognizes the N-1 state and the next state will be 0. The register is thus programed with N-1 rather than N.

TIM Update Frequency = TIM Clock / (P * Q)

Where Prescaler = P - 1, and Period = Q - 1

The base TIM Clock with depend on the AHB divider for the bus to which it's attached.

TIM2 on on APB1, the typical prescaler for that is 4, where the input for the timer is 2. See the Clock Tree diagram for this relationship. Thus the TIM Clock will nominally be 84 MHz (168 MHz / 2)

Therefore to get the time base ticking at 1 MHz, the prescaler needs to be 84 - 1, a period of 1000 - 1 will get the update down to 1 KHz.

Your example would generate 25 Hz in my estimation, a division of 3360000, whose factors include 336 and 10000
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
kazafwing
Associate II
Posted on January 24, 2013 at 05:15

Thanks, I have a further question. The question is that I have use the Oscilloscope to view the wave of this case. Before using the Oscilloscope to view, I have changed the program.

GPIO_ToggleBits(GPIOD, GPIO_Pin_15)  -->  GPIO_TogglesBits(GPIOD, GPIO_Pin_6)

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;  -->  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;

Then, I connected Pin6 to Oscilloscope. But there is no any waveform. It shows a 

horizontal line is below the x-axis, after a moment, the 

horizontal line return over the x-axis. This event is happened continuously.

Posted on January 25, 2013 at 08:31

To start, forget about the timers for a while. Write a simple loop toggling the pin, and observe it using the oscilloscope. Only after you confirm that working, proceed with the timer (and come back with the result).

JW

kazafwing
Associate II
Posted on January 25, 2013 at 10:57

Thanks for your help. I can use the Oscilloscope to view a square wave from a pin.

ghosalkar
Associate
Posted on September 02, 2013 at 12:09

i want to run the timer at 25MHz so the prescaler value = 2.36 is it possible to get the prescaler values in floating points?????if nt what is the fuether step?

Posted on September 02, 2013 at 14:36

You can't use fractional dividers, the STM32 permits only integers.

You could generate 25 MHz in a couple of ways. Run the processor at 150 MHz or some other 25 MHz multiple and have timers at 150 or 75 MHz via APB2/APB1. With a 25 MHz HSE crystal, you could feed that via MCO1 (PA8), which is typical for Ethernet/PHY implementations. You might also be able to use PLLI2S and feed that via MCO2

For an F2 the processor would need to run at 100 MHz to get 25 MHz out via a timer.
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
abuchholz91
Associate II
Posted on September 29, 2014 at 23:59

Clive, please forgive my ignorance, but, where P - 1 is the Prescalar, this value should be an interger, so one could view this arrangement as 1000 - 1 = 999. Is this correct or is this actually supposed to be a range of defined values from 1000 to 1?

Thanks!

Chris

Posted on September 30, 2014 at 02:35

The comparators want to check for an N-1 value for N discreet values, 0 .. N-1.

When it sees the CURRENT value is N-1, the NEXT value is ZERO (Update Event)

To divide by 1000 a value of 999 is programmed into the timer.

The prescaler is always a 16-bit integer value in the range 0 .. 65535, representing a division by 1 .. 65536
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
abuchholz91
Associate II
Posted on September 30, 2014 at 22:41

I have found an excellent example for Factoring the numbers (Prescalar and also the Period). Its in C# but its a start to get to the end result:

public List<int> Factor(int number) {

    List<int> factors = new List<int>();

    int max = (int)Math.Sqrt(number);  //round down

    for(int factor = 1; factor <= max; ++factor) { //test from 1 to the square root, or the int below it, inclusive.

        if(number % factor == 0) {

            factors.add(factor);

            if(factor != number/factor) { // Don't add the square root twice!  Thanks Jon

                factors.add(number/factor);

            }

        }

    }

    return factors;

}

See:

http://stackoverflow.com/questions/239865/best-way-to-find-all-factors-of-a-given-number-in-c-sharp

to get the Targeted Number for (P-1 * Q-1) this works:

uint PnQ = (Clk / DesiredFrequency);

One can factor the Values of Prescalar and Period from there also. I hope this helps others out there as its not the easiest concept to get ones head around.

As an example and some modifications, I get:

Desired Frequency: 6543Hz

Factored Numbers:

i = 1

i = 12838

i = 2

i = 6419

i = 7

i = 1834

i = 14

i = 917

i = 49

i = 262

i = 98

i = 131

Freq 6543 = (84000000 (Clk) / 12838 Factored Numbers: (14 * 917))

Actual Frequency calculated is: 6543.075245365322

Thanks to Clive, I have read many of your posts and found them very helpful!

All the best

  Chris