0
votes

I want to implement long-press button to turn a device on. I use external interrupt button to launch the timer on press, and stop and reset it on release of the button. If you hold the button enough (1 sec) it will call a Timer_Update event and turn on LED.

However, when I load my code to the Discovery and press reset, the first press of the user button lights the LED immediately as if the interrupt is generated at the very first launch of the Timer. Then it works properly - changes LED state if you hold the button for >= 1sec.

Project is generated via CubeMX

This is button interrupt handler

    void EXTI0_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI0_IRQn 0 */
    static uint8_t is_pressed = 0;
  /* USER CODE END EXTI0_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
  /* USER CODE BEGIN EXTI0_IRQn 1 */
    if (!is_pressed) {
        HAL_TIM_Base_Start_IT(&htim7);
        HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_13);
        is_pressed = 1;
    }
    else {
        HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_13);
        HAL_TIM_Base_Stop_IT(&htim7);
        __HAL_TIM_SET_COUNTER(&htim7, 0);
        is_pressed = 0;
    }
  /* USER CODE END EXTI0_IRQn 1 */
}

This is Timer interrupt handler

    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_14);
    HAL_TIM_Base_Stop_IT(htim);
    __HAL_TIM_SET_COUNTER(htim, 0);
}

The trigger event for the Timer in CubeMX is set as "Update Event"

1
Why everyone thinks that using interrupts for processing buttons is the best solution? Buttons usually generating bounces at every press and release, this can call interrupt more times and can cause unexpected behavior. - vlk
@vlk I will bother debouncing the button later, I have several other important functions depending on interrupts by timers, and if I can't solve this "simple" problem it means I don't understand the way the timer interrupt works, this may cause my program malfunction later. - Warpony

1 Answers

0
votes

I would recommend the following implementation:

  1. Setup EXTI pin for rising and falling edges
  2. Check pin state in interrupt handler(instead of is_pressed variable)

EXTI handler can be implemented like below:

#define BUTTON_GPIO                GPIOA
#define BUTTON_PIN                 GPIO_PIN_0
#define BUTTON_PRESSED_STATE       GPIO_PIN_RESET

void EXTI0_IRQHandler(void)
{        
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);

    if (HAL_GPIO_ReadPin(BUTTON_GPIO, BUTTON_PIN) == BUTTON_PRESSED_STATE ) {
        HAL_TIM_Base_Start_IT(&htim7);
        __HAL_TIM_SET_COUNTER(&htim7, 0);
        HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_RESET);
    } else {
        HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_SET);
        HAL_TIM_Base_Stop_IT(&htim7);
    }
}