Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Timer STM32定时器中断意外行为_Timer_Interrupt_Stm32_Stm32f4discovery_St - Fatal编程技术网

Timer STM32定时器中断意外行为

Timer STM32定时器中断意外行为,timer,interrupt,stm32,stm32f4discovery,st,Timer,Interrupt,Stm32,Stm32f4discovery,St,我想实现长按按钮来打开设备。 我使用外部中断按钮在按下时启动计时器,在松开按钮时停止并重置计时器。如果按住按钮足够长(1秒),它将调用计时器更新事件并打开LED 但是,当我将代码加载到Discovery并按下reset时,第一次按下用户按钮会立即点亮LED,就好像中断是在计时器第一次启动时产生的一样。然后它可以正常工作-如果按住按钮>=1秒,则会改变LED状态 项目是通过CubeMX生成的 这是按钮中断处理程序 void EXTI0_IRQHandler(void) { /* USE

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

但是,当我将代码加载到Discovery并按下reset时,第一次按下用户按钮会立即点亮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);
}
这是定时器中断处理程序

    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中计时器的触发事件设置为“更新事件”

我建议以下实现:

  • 设置上升和下降边缘的EXTI引脚
  • 检查中断处理程序中的引脚状态(而不是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);
        }
    }
    

    为什么每个人都认为使用中断处理按钮是最好的解决方案?按钮通常在每次按下和释放时都会产生反弹,这可能会调用中断更多次,并可能导致意外行为。@vlk我稍后会麻烦取消按钮的抖动,我还有其他几个重要功能,取决于计时器的中断,如果我不能解决这个“简单”问题问题这意味着我不理解定时器中断的工作方式,这可能会导致我的程序稍后出现故障。感谢您的回答,我已经尝试过了,ReadPin函数似乎无法与EXTI配置的pin一起工作,或者可能是我做错了什么。尽管如此,问题仍然存在——计时器在第一次启动时立即调用其中断。在计时器处理程序中添加“First run”变量对我来说太粗糙了。EXTI配置不影响HAL_GPIO_ReadPin,它必须在没有任何限制的情况下工作2。您是否在配置pin之后和启用IRQ之前清除了EXTI标志?在启用HAL NVIC IRQ(EXTI0 IRQn)