Skip to main content
MRamy.1
Associate II
December 16, 2019
Solved

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

  • December 16, 2019
  • 3 replies
  • 1385 views
#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.

This topic has been closed for replies.
Best answer by waclawek.jan

> 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

3 replies

Tesla DeLorean
Guru
December 16, 2019

Looks to be 10 seconds​

You will need to explicitly clear the Update flag.​

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
MRamy.1
MRamy.1Author
Associate II
December 16, 2019

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?

waclawek.jan
waclawek.janBest answer
Super User
December 16, 2019

> 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