Timer STM32定时器中断意外行为
我想实现长按按钮来打开设备。 我使用外部中断按钮在按下时启动计时器,在松开按钮时停止并重置计时器。如果按住按钮足够长(1秒),它将调用计时器更新事件并打开LED 但是,当我将代码加载到Discovery并按下reset时,第一次按下用户按钮会立即点亮LED,就好像中断是在计时器第一次启动时产生的一样。然后它可以正常工作-如果按住按钮>=1秒,则会改变LED状态 项目是通过CubeMX生成的 这是按钮中断处理程序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
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中计时器的触发事件设置为“更新事件”我建议以下实现:
#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)