3
\$\begingroup\$

First off I'm a complete n00b and just getting started with STM32. I'm encountering some weird behavior while setting up TIM1 and also using external interrupt EXTI3. I'm attempting to measure a low input frequency on the external interrupt and using TIM1 to increment a 1 MHz counter, so I can measure in microseconds. I'm doing this as it seems SysTick isn't fast enough (1 ms) to give me an accurate measurement.

The core clock is 16 MHz, and TIM1 is set up as follows:

htim1.Instance = TIM1;
htim1.Init.Prescaler = 16; // 16 MHz / 16 = 1 MHz
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 1; // 1Mhz no sub-dividing
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
...
HAL_NVIC_SetPriority(EXTI3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI3_IRQn);
...
void TIM1_UP_TIM10_IRQHandler(void)
{
    timerTicks++;
    HAL_TIM_IRQHandler(&htim1);
}
...
void EXTI1_IRQHandler(void)
{
    previousTimerTicks = currentTimerTicks;
    currentTimerTicks = timerTicks;
}
...
// Start the timer as interrupt
HAL_TIM_Base_Start_IT(&htim1);
...
while(1){
    // Blink a light so we know the program is running
    HAL_GPIO_TogglePin(GPIOB, Led_Green_Pin);
    HAL_Delay(100);
}

However, the program pretty much locks up and the while() run loop doesn't seem to execute. Yet, I can see the TIM1 counter is incrementing. If I slow the Period down to say, 100, the main application loop seems to run OK.

Is this a problem with TIM1 and EXTI3 conflicting at that speed - or something else going on here? I figure the device should have no issue providing a 1 MHz counter, but maybe I'm doing this all wrong.

\$\endgroup\$
  • \$\begingroup\$ If you want to divide the input clock by 16 then you should set the Prescaler value to 15. \$\endgroup\$ – kkrambo Apr 3 '17 at 0:48
  • \$\begingroup\$ I didn't catch this in the examples I followed but you seem to be correct, very good to know! \$\endgroup\$ – Michael Brown Apr 4 '17 at 18:10
3
\$\begingroup\$

You're going about this all wrong.
There is no possible way that you're going to be able to execute your timer interrupt handler in just 16 clock cycles - nevermind get around to your while(1) loop.

What you should be doing is letting timer run free and only handle interrupts when it overflows. We'll get back to this soon.

Next, set up an interrupt handler for your EXTI and in it, capture the value of the timer & save it.
In the next interrupt, calculate the difference between the 2 values - and there you have it - the time between 2 successive EXTI events in multiples of your timer period (1uSec if you keep it set up the same).

But what if the timer rolls over - well that's why we want to handle timer interrupts on rollover.
Here you can set a flag to tell your EXTI handler that the timer has rolled over and it needs to take that into account when doing the calculation.

\$\endgroup\$
  • \$\begingroup\$ Hmmmm, I thought this was exactly what I was doing. In my EXTI interrupt code all I'm doing is grabbing the value of timerTicks when the interrupt is generated and also storing the previous value. My main loop performs the actual calculation based on the difference of the two values. \$\endgroup\$ – Michael Brown Apr 4 '17 at 18:04
  • 1
    \$\begingroup\$ That's the root of your problem. Don't use a variable incremented by the timer ISR - use the timer's own internal hardware counter register - it's already there and is available for you to read & use. \$\endgroup\$ – brhans Apr 4 '17 at 18:08
  • \$\begingroup\$ I see, I thought it would be implemented the same underneath - thank you I'll give it a shot. \$\endgroup\$ – Michael Brown Apr 4 '17 at 18:47
  • 1
    \$\begingroup\$ The main difference in this instance is that the timer's own counter is already incrementing without any CPU intervention, whereas your ISR implementation uses CPU instructions. \$\endgroup\$ – brhans Apr 4 '17 at 19:00

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.