6
\$\begingroup\$

I wrote a simple program to toggle an LED on and off using the TIM1 interrupt on an STM32F0 discovery board.

CLK Freq = 48MHz
Prescalar = 48000
Auto Reload Register = 1000

Using the following formula to calculate the timer frequency:

Timer frequency = (CLK FREQ/ (Prescalar -1) * ARR)

In my case it is equal to 1 second. If I run this code without an interrupt, it toggles the LED on and off at 1-second intervals, which is what I want.

As soon as I use the ISR, my LED TOGGLE is really fast (approximately 500ms), if I make my Timer_Value = 60000

void TIM1_BRK_UP_TRG_COM_IRQHandler(void)
{
    Timer_Value++;

if(Timer_Value == 60000)
{
if(Timer_Change_Status == Timer_Deactive)
{
    SendBitToPortAndPin(LEDIND_Port, LEDIND_Pin,1);
    Timer_Change_Status = Timer_Active;
}
else {
    SendBitToPortAndPin(LEDIND_Port, LEDIND_Pin,0);
    Timer_Change_Status = Timer_Deactive;
}
Timer_Value = 0;
}
  // reload counter
TIM1->EGR |= 0x01;
}

In my main loop, I call the following function

void COnfig_Start_Timer(void)
    {   
    RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;

    TIM1->PSC = 48000;                          ///Load Prescalar
    TIM1->ARR = 1000;                           ///Load Auto Reload value


    NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);   ///Enable interrupt
    NVIC_SetPriority(TIM1_BRK_UP_TRG_COM_IRQn,1);///Set interrupt priority
    TIM1->DIER |= TIM_DIER_UIE;                 ///Activate Timer Interrupt
    TIM1->CR1 |= TIM_CR1_CEN;                   ///start Timer


    while(1)
    {

    }
    }

I would like to know what is causing my ISR to fire so frequently, when it should only fire once every second. I have referred to my reference manual with no luck.

\$\endgroup\$
  • \$\begingroup\$ Except for your problem, probably you have to use 47999 and 999 for PSC and ARR, according to the formula: tim uptade frequency = TIM_CLK/(TIM_PSC+1)/(TIM_ARR + 1), but this does not explain the 0.5 instead of 1.0 seconds firing. \$\endgroup\$ – Michel Keijzers Jan 9 at 10:21
12
\$\begingroup\$

There are two things wrong with your code:

1) you attempt to reset and restart the counter in the interrupt handler with "TIM1->EGR |= 0x01;" . But you're using the automatic reload mode of the counter so you shouldn't do that.

2) You never clear the interrupt from the timer. The timer sets the interrupt, but you're responsible for clearing it once you've handled it. Since you don't do that, when your IRQ handler returns, the cpu immediately dispatches the same interrupt and calls it again. To clear the interrupt you need to clear bit 0 of TIM1_SR with something like

TIM1->SR &= ~0x1;

(or perhaps TIM1->SR &= ~TIM_SR_UIF; if you have that defined)

\$\endgroup\$
  • \$\begingroup\$ I thought you couldn't write to the Status register, thanks \$\endgroup\$ – user150963 Jan 9 at 10:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.