Timers
TIMER-Registers
-
Timer Count Register (TIMx_CNT)
Shows the current counter value. Size could be 32-bit or 16-bit depending on timer module used.
-
Timer Auto-Reload Register (TIMx_ARR)
Timer raises a flag and the counter restarts automatically when counter value reaches the value in the auto-reload register. The counter is an up counter by default but can also be configured to be a down counter.

-
Timer Prescaler Register (TIMx_PSC)
The prescaler slows down the counting speed of the timer by dividing the input clock of the timer

-
Status Register (SR)

-
Capture/Compare Register (ccr1, ccr2, ccr3, ccr4)

-
Capture/Compare Mode Register

-
Capture/Compare Enable Register (CCER)

TIMER- Some Terms
-
Update Event
When timeout occurs or how long it takes for flag to be raised

The
+1is because we start from 0 -
Period
Value loaded into auto-reload register (TIM_ARR)
-
Up counter
Counts from zero to a set value.
-
Down counter
Counts from a set value down to zero



General Purpose Timer example
#include "stm32f4xx.h"
#define TIM2EN (1U<<0)
#define CR1_CEN (1U<<0)
#define SR_UIF (1U<<0)
void tim2_1hz_init(void)
{
/*Enable clock access to tim2*/
RCC->APB1ENR |= TIM2EN;
/*Set prescaler value*/
TIM2->PSC = 1600 - 1; // 16 000 000 / 1 600 = 10 000
/*Set auto-reload value*/
TIM2->ARR = 10000 - 1; // 10 000 / 10 000 = 1
/*Clear counter*/
TIM2->CNT = 0;
/*Enable timer*/
TIM2->CR1 = CR1_CEN;
}
int main(void)
{
tim2_1hz_init();
while(1)
{
/*Wait for UIF */
while(!(TIM2->SR & SR_UIF)){}
/*Clear UIF*/
TIM2->SR &= ~SR_UIF;
printf("A second passed !! \n\r");
}
}
Timer Output Compare example



#include "stm32f4xx.h"
#define TIM2EN (1U<<0)
#define CR1_CEN (1U<<0)
#define OC_TOGGLE ((1U<<4) | (1U<<5))
#define CCER_CC1E (1U<<0)
#define GPIOAEN (1U<<0)
#define AFR5_TIM (1U<<20)
void tim2_pa5_output_compare(void)
{
/*Enable clock access to GPIOA*/
RCC->AHB1ENR |= GPIOAEN;
/*Set PA5 mode to alternate function*/
GPIOA->MODER &= ~(1U<<10);
GPIOA->MODER |= (1U<<11);
/*Set PA5 alternate function type to TIM2_CH1 (AF01)*/
GPIOA->AFR[0] |= AFR5_TIM;
/*Enable clock access to tim2*/
RCC->APB1ENR |= TIM2EN;
/*Set prescaler value*/
TIM2->PSC = 1600 - 1; // 16 000 000 / 1 600 = 10 000
/*Set auto-reload value*/
TIM2->ARR = 10000 - 1; // 10 000 / 10 000 = 1
/*Set output compare toggle mode*/
TIM2->CCMR1 = OC_TOGGLE;
/*Enable tim2 ch1 in compare mode*/
TIM2->CCER |= CCER_CC1E;
/*Clear counter*/
TIM2->CNT = 0;
/*Enable timer*/
TIM2->CR1 = CR1_CEN;
}
int main(void)
{
tim2_pa5_output_compare();
while(1)
{
}
}
Timer Input Capture example
#include "stm32f4xx.h"
#define SR_CC1IF (1U<<1)
#define TIM2EN (1U<<0)
#define TIM3EN (1U<<1)
#define CR1_CEN (1U<<0)
#define OC_TOGGLE ((1U<<4) | (1U<<5))
#define CCER_CC1E (1U<<0)
#define GPIOAEN (1U<<0)
#define AFR5_TIM (1U<<20)
#define AFR6_TIM (1U<<25)
#define CCER_CC1S (1U<<0)
void tim3_pa6_input_capture(void)
{
/*Enable clock access to GPIOA*/
RCC->AHB1ENR |= GPIOAEN;
/*Set PA6 mode to alternate function*/
GPIOA->MODER &= ~(1U<<12);
GPIOA->MODER |= (1U<<13);
/*Set PA6 alternate function type to TIM3_CH1 (AF02)*/
GPIOA->AFR[0] |= AFR6_TIM;
/*Enable clock access to tim3*/
RCC->APB1ENR |= TIM3EN;
/*Set Prescaler*/
TIM3->PSC = 16000 - 1; // 16 000 000 /16 000
/*Set CH1 to input capture*/
TIM3->CCMR1 = CCER_CC1S;
/*Set CH1 to capture at rising edge*/
TIM3->CCER = CCER_CC1E;
/*Enable TIM3*/
TIM3->CR1 = CR1_CEN;
}
void tim2_pa5_output_compare(void)
{
/*Enable clock access to GPIOA*/
RCC->AHB1ENR |= GPIOAEN;
/*Set PA5 mode to alternate function*/
GPIOA->MODER &= ~(1U<<10);
GPIOA->MODER |= (1U<<11);
/*Set PA5 alternate function type to TIM2_CH1 (AF01)*/
GPIOA->AFR[0] |= AFR5_TIM;
/*Enable clock access to tim2*/
RCC->APB1ENR |= TIM2EN;
/*Set prescaler value*/
TIM2->PSC = 1600 - 1; // 16 000 000 / 1 600 = 10 000
/*Set auto-reload value*/
TIM2->ARR = 10000 - 1; // 10 000 / 10 000 = 1
/*Set output compare toggle mode*/
TIM2->CCMR1 = OC_TOGGLE;
/*Enable tim2 ch1 in compare mode*/
TIM2->CCER |= CCER_CC1E;
/*Clear counter*/
TIM2->CNT = 0;
/*Enable timer*/
TIM2->CR1 = CR1_CEN;
}
int timestamp = 0 ;
/*Set up : Connect a jumper wire from PA5 to PA6*/
int main(void)
{
tim2_pa5_output_compare();
tim3_pa6_input_capture();
while(1)
{
/*Wait until edge is captured*/
while(!(TIM3->SR & SR_CC1IF)){}
/*Read captured value*/
timestamp = TIM3->CCR1;
}
}
// ...existing code...