Electronic – Problem with interrupt-based timer on STM32F411

interruptsstm32

I was following this online tutorial and cannot get the interrupt-based timer to work. I know the timer is running because if I uncomment the five lines in the main loop, I get a nice square wave output. But with those lines commented out, the timer interrupt is not firing and I cannot figure out why. Can someone suggest what I'm doing wrong?

#include "stm32f4xx_hal.h"

void SysTick_Handler(void)
{
    HAL_IncTick();
    HAL_SYSTICK_IRQHandler();
}

static TIM_HandleTypeDef s_TimerInstance = { .Instance = TIM2 };

void InitializeTimer()
{
    __TIM2_CLK_ENABLE();
    s_TimerInstance.Init.Prescaler = 160;
    s_TimerInstance.Init.CounterMode = TIM_COUNTERMODE_UP;
    s_TimerInstance.Init.Period = 100;
    s_TimerInstance.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    s_TimerInstance.Init.RepetitionCounter = 0;
    HAL_TIM_Base_Init(&s_TimerInstance);
    HAL_TIM_Base_Start(&s_TimerInstance);
}

void InitializeLED()
{
    __GPIOA_CLK_ENABLE();
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.Pin = LD2_Pin;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStructure.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStructure);
}

void TIM2_IRQHandler()
{
    HAL_TIM_IRQHandler(&s_TimerInstance);
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
}

int main(void)
{
    HAL_Init();
    InitializeLED();
    InitializeTimer();

    HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM2_IRQn);

    for (;;)
    {
//        int timerValue = __HAL_TIM_GET_COUNTER(&s_TimerInstance);
//        if (timerValue == 50)
//            HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
//        if (timerValue == 100)
//            HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
    }
}

Best Answer

Looks like the UIE bit in TIM2->DIER is not enabled. There must be some HAL function to do it, I don't know. I would not recommend using HAL for timing stuff anyway, there are issues with its accuracy.

Starting a timer is just a few lines of code.

void InitializeTimer(void) {
    __TIM2_CLK_ENABLE();
    TIM2->PSC = 160;             /* Set prescaler value */
    TIM2->EGR = TIM_EGR_UG;      /* Update prescaler */
    TIM2->ARR = 100;             /* Set timer period */
    TIM2->DIER = TIM_DIER_UIE;   /* Enable interrupt generation on timer overflow */
    TIM2->CR1 = TIM_CR1_CEN;     /* Start counting */
}

void TIM2_IRQHandler()
{
    /* Clear interrupt flag first. It cannot be the last instruction in an interrupt handler. */
    TIM2->SR = 0;
    LD2_GPIO_Port->ODR ^= LD2_Pin;
}