0

我想实现长按按钮来打开设备。我使用外部中断按钮在按下时启动计时器,并在释放按钮时停止并重置它。如果您按住按钮足够长(1 秒),它将调用 Timer_Update 事件并打开 LED。

但是,当我将代码加载到 Discovery 并按下复位时,第一次按下用户按钮会立即点亮 LED,就好像在第一次启动定时器时产生了中断一样。然后它可以正常工作 - 如果您按住按钮 >= 1 秒,则会更改 LED 状态。

项目是通过 CubeMX 生成的

这是按钮中断处理程序

    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 */
}

这是定时器中断处理程序

    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);
}

CubeMX中定时器的触发事件设置为“更新事件”

4

2 回答 2

0

我会推荐以下实现:

  1. 为上升沿和下降沿设置 EXTI 引脚
  2. 检查中断处理程序中的引脚状态(而不是 is_pressed 变量)

EXTI 处理程序可以如下实现:

#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);
    }
}
于 2018-06-16T08:14:55.230 回答
0

好吧,这是生成的代码中的一个错误。在定时器初始化期间,调用 TIM_Base_SetConfig 调用。此调用的副作用是在 SR 中设置了更新中断位。这意味着当在 HAL_TIM_Base_Start_IT 中启用中断时,会立即生成中断。这就是你正在经历的。另见https://www.youtube.com/watch?v=3yvY7pLMHAg 5:40。还解释了一个 HAL 兼容修复。

于 2022-03-03T19:45:28.403 回答