Stm32 Time Base Interrupt (without any library)


I use Stm32f103c8t6 processor and I want to make 1 second counter. Normaly I dont use tımer update ınterrupt and my counter counts correctly but when I add timer update ınterrupt in code my counter doesnt count correctly. So fast increment. And ı cant remove update interrupt flag (UIF) in TIM1's SR register. If I remove this flag my code is entering infinty loop. I cant any solution for this problem. Thanks for help

This part is bring in startup_stm32f10x_md.s

 * @brief  This is the code that gets called when the processor receives an
 *         unexpected interrupt.  This simply enters an infinite loop, preserving
 *         the system state for examination by a debugger.
 * @param  None
 * @retval : None
    .section    .text.Default_Handler,"ax",%progbits
    b   Infinite_Loop -----------------------------> my code is stuck here
    .size   Default_Handler, .-Default_Handler

And this is a my code.

#include <stddef.h>
#include "stm32f10x.h"

void CLK_Config(){
     RCC-> CR = 0x00000000;             //CR Reset
     RCC-> CR |= 0x00010000;            //HSE enable
     while(!(RCC-> CR & 0x00020000));   //HSE FLAG control
     RCC-> CR |= 0x00080000;            //CSS enable
     RCC-> CR |= 0x01000000;            //PLL On
     RCC-> CFGR |= 0x00010000;          //HSE Select PLL input
     RCC-> CFGR |= 0x001C0000;          //PLL Multi With 9 = 72 Mhz
     RCC-> CFGR |= 0x00000002;          //PLL Select as SYSCLK
     RCC-> CFGR |= 0x00000400;          //APB1 Clock divided by 2

     RCC-> APB1ENR |= 0x18000000;       //APB1 BKP Clock Enable
     PWR-> CR |= 0x0100;                //PWR BKP Access Enable

     RCC-> APB2ENR |= 0x00000001;       //APB2 AFIO Clock Enable

void TIM1_Config(){
     RCC-> APB2ENR  |= 0x00000800;      //TIM1 CLK Enable
     TIM1-> CR1     |= 0x0085;          //Update Request Source, Counter Enable
     TIM1-> DIER     = 0x0001;          //Update Interrupt Enable
     TIM1-> ARR      = 0x1F40;          //8000 is set as Auto Reload Value
     TIM1-> PSC      = 0x2327;          //9000 is set as Prescaler Value for 1 sn Formula: 1sn=1Hz=(PCLK/(PSC*ARR))

void USART1_Config(){
    RCC-> APB2ENR   |= 0x00000004;      //GPIOA CLK Enable
    GPIOA-> CRH     |= 0x00000AA0;      //GPIOA 10,9 Push-Pull Alternate Function 2Mhz
    RCC-> APB2ENR   |= 0x00004000;      //USART1 CLK Enable
    USART1-> BRR    |= 0x00001D4C;      //USART1 Baund Rate 9600
    USART1-> CR1    |= 0x000020C8;      //USART, TXE Interrupt, TC Interrupt, Transmitter Enable

void Interrupt_Config(){
    NVIC-> ISER[0]  |= 0x02000000;      //NVIC TIM1 UP
    NVIC-> ISER[1]  |= 0x00000020;      //NVIC USART1 Global Interrupt

    NVIC-> IP[25]   = 0x10;             //TIM1 UP Interrupt Priority 2.         25th Interrupt
    NVIC-> IP[37]   = 0x40;             //USART1 Global Interrupt Priority 5.   37th Interrupt


uint8_t count1sec; // Global variable

int main(void)

  while (1)
      if(count1sec != 0){
          USART1-> DR = count1sec;


void TIM1_UP_IRQHandler(){
    TIM1-> SR = 0x00000000;
    NVIC-> ICPR[0] = 0x02000000;
    count1sec += 1;
asked on Stack Overflow Feb 1, 2020 by RasimGök

1 Answer


I'm not able to detect the exact cause of your problem, but I can provide some suggestions and make some guesses.

1) Do not use magic numbers! Use predefined bit names. Here is an example:

USART2->BRR = 0x1a0; // 115200 bps @ 24 MHz (OVER8=1, ONEBIT=1)
USART2->CR1 |= USART_CR1_OVER8 // Oversampling is reduced for higher baud rates
            | USART_CR1_IDLEIE // Idle line detection interrupt is enabled
            | USART_CR1_TE // Transmitter is enabled
            | USART_CR1_RE; // Receiver is enabled
USART2->CR3 |= USART_CR3_ONEBIT // One bit mode for increased clock deviation tolerance
            | USART_CR3_DMAT // DMA for TX
            | USART_CR3_DMAR; // DMA for RX
USART2->CR1 |= USART_CR1_UE; // Enable USART2

2) Use CMSIS functions to access NVIC functionality. Here is an example:

NVIC_SetPriority(TIM6_DAC_IRQn, 2);

3) You have Auto-reload preload enable bit set in TIM1->CR1 register. This normally delays the update of the ARR register until the next update event. I'm not sure how it works during the initial run of the timer, but I suggest to avoid using it until you're sure everything works fine.

4) You normally don't need to clear pending bits in NVIC. I suggest removing that code from the ISR. Clearing the flags in the peripheral registers is all you need and you're already doing it with TIM1->SR = 0 line.

5) The reason you stuck in Infinite_Loop is probably the USART TX interrupt. It gets fired but as you didn't supply a ISR for it, it falls into the Default_Handler. You load DR manually in the main loop, so in this case you don't even need USART TX interrupts.

answered on Stack Overflow Feb 1, 2020 by Tagli

User contributions licensed under CC BY-SA 3.0