STM32基于外部中断+定时器中断实现非阻塞式按键消抖
之前我一直使用阻塞式的按键消抖,虽然用在实时性不强的裸机系统问题不大,但感觉一直很膈应,因为我的宗旨是能不用delay就不用delay(笑),所以我写了这样一个程序来记录一下。我的设备是STM32F411CEU6,使用HAL库,利用CUBEMX生成代码,开启TIM4设置20ms定时中断,然后KEY4_Pin是我定义的外部中断引脚。思路就提供到这了,还有非常多的功能不完善,我也不知道该如何改进了,欢
·
之前我一直使用阻塞式的按键消抖,虽然用在实时性不强的裸机系统问题不大,但感觉一直很膈应,因为我的宗旨是能不用delay就不用delay(笑),所以我写了这样一个程序来记录一下。
我的思路是利用按键外部中断,在中断中记录当前按键值,唤醒一个20ms的定时器中断,当定时器产生中断事件时,在中断事件里再次读取按键值,如果两次按键值一致则判定按键触发。
这里我只提供思路,就不放完整代码了(因为我代码写的太烂了)
我的设备是STM32F411CEU6,使用HAL库,利用CUBEMX生成代码,开启TIM4设置单次触发20ms定时中断,然后KEY4_Pin是我定义的外部中断引脚。
这里是外部中断函数里的处理:
volatile uint8_t button_pressed_flag = 0;//定义按键按下标志
volatile uint8_t debounce_timer_enabled = 0;//定义定时器启动标志
volatile uint8_t Keyx_input = 0;//定义是哪一个按键按下
//外部中断回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == KEY4_Pin)//KEY4_Pin为用户标签
{
// 如果定时器没有在运行,就启动它
if (debounce_timer_enabled == 0)
{
// 设置互斥锁,防止重复启动
debounce_timer_enabled = 1;
//按键4按下
Keyx_input = 4;
//读取按键值
button_pressed_flag = HAL_GPIO_ReadPin(KEY4_GPIO_Port, KEY4_Pin);
// 启动定时器,单次模式
HAL_TIM_Base_Start_IT(&htim4); // 启动tim4
}
}
}
然后下面是定时器中断中的按键事件处理:
//定时器事件更新回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM4) // 如果是TIM4触发了更新事件
{
// 停止定时器并清除标志位
HAL_TIM_Base_Stop_IT(&htim4);
//如果是按键4触发了外部中断
if(Keyx_input == 4)
{
// 再次读取按键电平,进行判断
if (HAL_GPIO_ReadPin(KEY4_GPIO_Port, KEY4_Pin) == button_pressed_flag)
{
// 两次电平相同,判定按键按下
if (button_pressed_flag == GPIO_PIN_RESET) // 按下是低电平
{
// 切换LED状态
HAL_GPIO_TogglePin(DEBUG_LED_GPIO_Port, DEBUG_LED_Pin);
}
}
}
}
这里我为了测试就只写了翻转电平。
思路就提供到这了,还有非常多的功能不完善,我也不知道该如何改进了,欢迎各路大佬来指导/(ㄒoㄒ)/~~
更多推荐



所有评论(0)