cancel
Showing results for 
Search instead for 
Did you mean: 

How to calculate the values to be inserted in the TIM2 registers?

MRamy.1
Associate II
#include "stm32f4xx.h"                  // Device header
 
// Trying to use the General Purpose Timer (TIM2) to create a 1 second delay
// Board External Crystal 8.0 MHz
// Port A Pin 0 Output
 
// The program should output a high on GPIOA Pin 0 and delay 1 second then output low and delay 1 second.
 
int main(void){
	
	RCC->AHB1ENR |= 0x00000001; //Enable Clock to PortA
	GPIOA->MODER |= 0x00000001; //General Purpose IO for PortA Pin 0
	
	//TIM2 Configuration
	RCC->APB1ENR |= 0x00000001; Enable Clock to TIM2
	TIM2->PSC = 8000-1; 
	TIM2->ARR = 10000 - 1;
	TIM2->CNT = 0;
	TIM2->CR1 = 0x00000001;
	
	while(1){
		while((!TIM2->SR & 1)){
			GPIOA->ODR ^= 0x00000001; // Output high/low on Pin0 PortA
		}
	}
}

Would like to know how to calculate the values that should be inserted in TIM2->PSC, TIM2->ARR, and TIM2->CNT. Is there a formula to calculate the values. Also what values must be added to the registers in the above program to make it a 1 second delay. The program runs but the LED doesn't blink, its just ON.

1 ACCEPTED SOLUTION

Accepted Solutions

> How did you know its 10 seconds?

Clive just assumed that that your system clock is either the default 16MHz HSI or as the comment in code says, 8MHz HSE; and that there are no dividers on the APB buses or they are equal to 2 which means the timers run at the same clock as the system clock.

Then, update (i.e. "oveflow") rate of the timer is

fUPDATE = fCLK_IN / (PSC + 1) / (ARR + 1)

so that's in your case 8'000'000Hz/8'000/10'000 = 0.1Hz (or twice that if the 16MHz is the system clock). That's 10s (or 5s) pulse followed by 10s (5s) space if you toggle the output as above.

> Which register is the Update flag is in?

Clive means TIMx_SR.UIF, the flag you are testing:

while((!TIM2->SR & 1)){

GPIOA->ODR ^= 0x00000001; // Output high/low on Pin0 PortA

}

If you don't clear it, it will remain set, so then the while cycle is exit immediately and the pin will toggle at an extremely high rate, hundreds of kHz - invisible by naked eye. Use an oscilloscope/logic analyzer (LA) to observe the output.

Clear the flag by writing 0 into it.

OTOH, if you'd just clear the flag, the output would again toggle rapidly while it's 0. You want this:

while(1) {  // an infinite loop
  while((TIM2->SR & TIM_SR_UIF) == 0);  // wait until TIM2_SR.UIF gets set, when the timer overflows
  TIM2->SR = ~TIM_SR_UIF;  // clear the flag
  GPIOA->ODR ^= 0x00000001; // Output high/low on Pin0 PortA
}
 
 

JW

View solution in original post

3 REPLIES 3

Looks to be 10 seconds​

You will need to explicitly clear the Update flag.​

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

How did you know its 10 seconds? What formula did you use to know that its a 10 second delay. Which register is the Update flag is in?

> How did you know its 10 seconds?

Clive just assumed that that your system clock is either the default 16MHz HSI or as the comment in code says, 8MHz HSE; and that there are no dividers on the APB buses or they are equal to 2 which means the timers run at the same clock as the system clock.

Then, update (i.e. "oveflow") rate of the timer is

fUPDATE = fCLK_IN / (PSC + 1) / (ARR + 1)

so that's in your case 8'000'000Hz/8'000/10'000 = 0.1Hz (or twice that if the 16MHz is the system clock). That's 10s (or 5s) pulse followed by 10s (5s) space if you toggle the output as above.

> Which register is the Update flag is in?

Clive means TIMx_SR.UIF, the flag you are testing:

while((!TIM2->SR & 1)){

GPIOA->ODR ^= 0x00000001; // Output high/low on Pin0 PortA

}

If you don't clear it, it will remain set, so then the while cycle is exit immediately and the pin will toggle at an extremely high rate, hundreds of kHz - invisible by naked eye. Use an oscilloscope/logic analyzer (LA) to observe the output.

Clear the flag by writing 0 into it.

OTOH, if you'd just clear the flag, the output would again toggle rapidly while it's 0. You want this:

while(1) {  // an infinite loop
  while((TIM2->SR & TIM_SR_UIF) == 0);  // wait until TIM2_SR.UIF gets set, when the timer overflows
  TIM2->SR = ~TIM_SR_UIF;  // clear the flag
  GPIOA->ODR ^= 0x00000001; // Output high/low on Pin0 PortA
}
 
 

JW