Interrupt on CEN bit setting in TIM7
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-03-06 4:06 AM
Posted on March 06, 2013 at 13:06
Hello everybody!
I'm using timer TIM7 on STM32F407 to generate an interrupt on overflow. It works fine except one thing. When I enable the counter at first time it rises an interrupt immediately, right after setting the CEN bit in TIM7_CR1 register. Following iterations are ok.Does anybody know what's the problem?Initialization codevoid TIM7_Init(void){ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE); TIM7->CR1 |= TIM_CR1_OPM | TIM_CR1_URS; //One-pulse mode and Update generation only on Counter Overflow TIM7->DIER |= TIM_DIER_UIE; // Interrupt generation on Counter Overflow TIM7->PSC = 1600; //With HSI frequency 16MHz gives a 100us period NVIC_InitStruct.NVIC_IRQChannel = TIM7_IRQn; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; NVIC_Init(&NVIC_InitStruct);}PushButton Handlervoid EXTI0_IRQHandler(void){ for (volatile uint32_t cnt=200000; cnt!=0; cnt--); //wait until bounce stops EXTI_ClearITPendingBit(EXTI_Line0); //reset pending state GPIO_ToggleBits(GPIOD, GPIO_Pin_12); //LED TIM7->ARR = 10000; //delay 1s TIM7->CR1 |= TIM_CR1_CEN; //start counting}Overflow handlervoid TIM7_IRQHandler(void){ TIM7->SR &= 0xFFFFFFFE; //reset UIF flag GPIO_ToggleBits(GPIOD, GPIO_Pin_15); //LED} #stm32f4-timer-tim7-interrupt
Labels:
- Labels:
-
TIM
This discussion is locked. Please start a new topic to ask your question.
4 REPLIES 4
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-03-06 6:00 AM
Posted on March 06, 2013 at 15:00
Do you reset the chip using the hardware reset/poweron, or are you resetting it from some form of a debugger?
I'd reset the timer explicitly in RCC after enabling its clock, to be sure. > TIM7->SR &= 0xFFFFFFFE; //reset UIF flag Don't &=, do =, as all bits in TIMx_SR are of rc_w0 type, so you could inadvertently clear a bit which has been set meantime. It won't matter in the code as you presented it, but it's a good practice for future when you will manipulate multiple flags. Also, it might be perhaps a better style to stick to either using the ''peripheral library'', or directly the registers, not mixing them. JWOptions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-03-06 8:10 PM
Posted on March 07, 2013 at 05:10
Thanks for reply!
I'm reseting the chip both ways: with debugger and with hardware using NRST pin. The result is same. Also I tried to reset UIF flag in SR register and NVIC pending bit right after setting the CEN bit in CR1 register. Unfortunately, it has no any effect.Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-03-15 7:46 AM
Posted on March 15, 2013 at 15:46 Turns out, your problem has its explanation in the following sentence from the manual (RM0090 rev.4, p.526): ''The new prescaler ratio is taken into account at the next update event.'' So, after the first button press, the timer does count up to 10000, but at the maximum rate given by default prescaler value = 0 (which appears to be immediately for the human observer). Only then the new prescaler is taken into account. Hower, if you'd read out the PSC register after write, you'd see the new value. There is apparently another, user-invisible register for the real prescaling. All this ''shadowing'', although I see its purpose, is quite confusing; pity that all those ''shadow'' registers are not visible for the users for debugging purposes. The code below should do what you intend. Note, that if _SR register clear follows immediately after setting the UG bit in _EGR register, the update event is not cleared from _SR register - apparently, there is some internal timing of events involved but I am not going to investigate it further. JW ---
void EXTI0_IRQHandler(void)
{ for (volatile uint32_t cnt=200000; cnt!=0; cnt--); //wait until bounce stops EXTI_ClearITPendingBit(EXTI_Line0); //reset pending state GPIO_ToggleBits(GPIOD, GPIO_Pin_12); //LED TIM7->ARR = 10000; //delay 1s TIM7->CR1 |= TIM_CR1_CEN; //start counting } void TIM7_IRQHandler(void) { // TIM7->SR &= 0xFFFFFFFE; //reset UIF flag if (TIM7->SR & 1) { GPIO_ToggleBits(GPIOD, GPIO_Pin_15); //LED } else { GPIO_ToggleBits(GPIOD, GPIO_Pin_14); //LED } TIM7->SR = 0xFFFE; //reset UIF flag } static void TIM7_Init(void) { NVIC_InitTypeDef NVIC_InitStruct; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE); TIM7->PSC = 1600; //With HSI frequency 16MHz gives a 100us period TIM7->EGR = TIM_EGR_UG; // generate update to force the prescaler to be accepted TIM7->CR1 |= TIM_CR1_OPM | TIM_CR1_URS; //One-pulse mode and Update generation only on Counter Overflow TIM7->SR = 0; // clear all status (namely the update flag) TIM7->DIER |= TIM_DIER_UIE; // Interrupt generation on Counter Overflow NVIC_InitStruct.NVIC_IRQChannel = TIM7_IRQn; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; NVIC_Init(&NVIC_InitStruct); }Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-03-15 7:58 AM
Posted on March 15, 2013 at 15:58
Just one more minor thing:
TIM7->PSC = 1600; //With HSI frequency 16MHz gives a 100us period It should be 1599. Not that it matters when used with HSI which is much more imprecise than that (and also jitters like hell :) ), just I like things to be done precisely. JW