Timer help on STM32 - Page 1
Forum section: electronics / general

author: WillHuang
author_rank: Contributor
timestamp: October 30, 2017, 03:30:00 pm
content: Hello all,I'm trying to get a basic timer going. What I would like to do is generate an interrupt each time an overflow happens or a compare match occurs. I can get into the interrupt handler, but I can't seem to clear the interrupt flag. As a result, I just stay in the handler mode.I am using the nucleo-f411re board, and using the internal 16 MHz clock.This is my code:Code:#include "stm32f4xx.h" // Device headervolatile uint32_t ticks = 0;int main(void){RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;/* GPIO */GPIOA->MODER |= (0x01 << GPIO_MODER_MODE5_Pos);/* Timer */TIM2->CR1 = 0;TIM2->CR2 = 0;TIM2->PSC = 0;TIM2->ARR = 10000;TIM2->CCR1 = 9999;TIM2->SR = 0;NVIC_ClearPendingIRQ(TIM2_IRQn);NVIC_EnableIRQ(TIM2_IRQn); // Enable TIM2 InterruptTIM2->DIER |= (TIM_DIER_UIE | TIM_DIER_CC1IE); // Ebable update event and compare match interruptTIM2->CR1 |= TIM_CR1_CEN; // Enable timerfor(;;){}return 0;}void TIM2_IRQHandler(void){if((TIM2->SR & TIM_SR_UIF) || (TIM2->SR & TIM_SR_CC1IF)){TIM2->SR &= ~(TIM_SR_UIF | TIM_SR_CC1IF); // Clear interrupt flagsticks++;GPIOA->ODR ^= GPIO_ODR_OD5;}}What am I doing wrong?

author: AndyC_772
author_rank: Super Contributor
timestamp: October 30, 2017, 04:26:30 pm
content: You need to also:Code:NVIC_ClearPendingIRQ(TIM2_IRQn);

author: andyturk
author_rank: Frequent Contributor
timestamp: October 30, 2017, 04:34:33 pm
content: Quote from: AndyC_772 on October 30, 2017, 04:26:30 pmHe doesn't need to clear the NVIC bit in the handler. That happens automatically.https://electronics.stackexchange.com/questions/114985/to-clear-or-not-to-clear-arm-cortex-m-nvic-interrupt-pendingIf the core just re-enters the TIM2 handler again, take a look at the TIM2 registers (in a debugger) to see what's keeping the IRQ active.

author: langwadt
author_rank: Super Contributor
timestamp: October 30, 2017, 04:42:43 pm
content: Quote from: AndyC_772 on October 30, 2017, 04:26:30 pmthat isn't needed, clearing it in the timer is enoughthe only obvious difference from something I know works is using &= rather than just write to the status register

author: newbrain
author_rank: Super Contributor
timestamp: October 30, 2017, 05:53:12 pm
content: Quote from: langwadt on October 30, 2017, 04:42:43 pmTrue on both counts.Just to make sure, I reproduced the code on a F103 (different core, but exactly the same timer 2), and it works as expected.I also moved the port toggling within the for(;; ) loop, with a condition onticks, so the code is definitely not stuck in the ISR.The code, as written, is a bit strange: the difference between the ARR and CCR1 register is just one, so by the time the ISR is entered and the if() is reached, also UIF is set (together with CC1F) and then both are reset.The capture, then, has no real effect on this program.Another hint: to simplify debugging, it is convenient to set DBG_TIM2_STOP bit in the DBGMCU_APB1_FZ register, so that the timer is stopped when the core is halted.

author: WillHuang
author_rank: Contributor
timestamp: October 30, 2017, 11:12:22 pm
content: Hi all, thanks for your input. It's working now.Quote from: newbrain on October 30, 2017, 05:53:12 pmThanks so much for the hint, great option. I can see the status register changing!

author: mbless
author_rank: Regular Contributor
timestamp: October 31, 2017, 12:03:05 pm
content: Quote from: WillHuang on October 30, 2017, 11:12:22 pmExplain what you changed to make it work! Solved threads without solutions are

author: donotdespisethesnake
author_rank: Super Contributor
timestamp: October 31, 2017, 01:47:15 pm
content: I assume when people don't give a reason it's because of a daft mistake they are too embarrassed to mention.

author: WillHuang
author_rank: Contributor
timestamp: October 31, 2017, 05:58:27 pm
content: Quote from: mbless on October 31, 2017, 12:03:05 pmSorry!It was newbrain's tip that helped. When I was stepping through the code, I could not see the status register change even after writing zero to it. After setting the debug bit, I can see the registers are changing.