STM32按键消抖的几种实现方式-STM32 Button Debouncing

news/2024/11/30 18:34:57/

一、按键抖动的现象

按键按下和松开的时候,按键金属片之间的贴合、分离有一个过程。给STM32输入的信号并不是理想的0和1切换的过程。而是如下图所示的,按下和松开的一小段时间内按键信号出现抖动(jitter),这种现象称为按键抖动(Button Bouncing)。为了避免程序上出现误动作,需要从硬件或软件上消除按键抖动(Button Debouncing)。
button bouncing


二、 硬件电路消抖

可以从电路设计上消除抖动,常见的有RC滤波电路消抖。但是仅通过RC电路,消抖过程慢,实际效果也并不好,一般会加上施密特触发器。硬件消抖的缺点是要增加额外的元器件,如果有多个需要消抖的输入信号,则会增加较大的成本。

  • RC电路

    RC debounce circuit
  • RC电路加施密特触发器

三、 软件消抖

3.1 按键状态分析

按键状态变化后,短时间内的状态是抖动的、不可采用的。软件上可延迟一段时间再判断按键的状态。按键的状态机变化如下图所示。
button state

3.2 程序实现

下面通过程序来实现按键的消抖。下例中的开发板MCU为stm32f103RCT6, 按键接在PB12、PB13引脚,LED接在PC0、PC1引脚。程序基于HAL库编写,外设的初始化程序由Stm32CubeMx软件生成,此处不再赘述。

  • 循环阻塞判断
int main(void)
{while (1){if (HAL_GPIO_ReadPin(Button1_GPIO_Port, Button1_Pin) == GPIO_PIN_RESET){HAL_Delay(20);if(HAL_GPIO_ReadPin(Button1_GPIO_Port, Button1_Pin) == GPIO_PIN_RESET){printf("Key 1 pressed.\n");HAL_GPIO_TogglePin(Led1_GPIO_Port, Led1_Pin);while(HAL_GPIO_ReadPin(Button1_GPIO_Port, Button1_Pin) == GPIO_PIN_RESET);      // 等待按键松开}}}
}

上面的方式,按键松开之前程序一直卡在while循环里,按键松开之后才能处理其他的程序。


  • 增加标志位、非阻塞
int main(void)
{uint8_t Button1PressedFlag = 0;uint8_t Button2PressedFlag = 0;while (1){if (Button1PressedFlag == 0 && HAL_GPIO_ReadPin(Button1_GPIO_Port == Button1_Pin) == GPIO_PIN_RESET){HAL_Delay(20);if(HAL_GPIO_ReadPin(Button1_GPIO_Port, Button1_Pin) == GPIO_PIN_RESET){printf("Key 1 pressed.\n");HAL_GPIO_TogglePin(Led1_GPIO_Port, Led1_Pin);Button1PressedFlag = 1;}}if(Button1PressedFlag == 1 && HAL_GPIO_ReadPin(Button1_GPIO_Port, Button1_Pin) == GPIO_PIN_SET){HAL_Delay(20);if(HAL_GPIO_ReadPin(Button1_GPIO_Port, Button1_Pin) == GPIO_PIN_SET){printf("Key 1 released.\n");Button1PressedFlag = 0;}}if (Button2PressedFlag == 0 && HAL_GPIO_ReadPin(Button2_GPIO_Port, Button2_Pin) == GPIO_PIN_RESET){HAL_Delay(20);if(HAL_GPIO_ReadPin(Button2_GPIO_Port, Button2_Pin) == GPIO_PIN_RESET){printf("Key 2 pressed.\n");HAL_GPIO_TogglePin(Led2_GPIO_Port, Led2_Pin);Button2PressedFlag = 1;}}if(Button2PressedFlag == 1 && HAL_GPIO_ReadPin(Button2_GPIO_Port, Button2_Pin) == GPIO_PIN_SET){HAL_Delay(20);if(HAL_GPIO_ReadPin(Button2_GPIO_Port, Button2_Pin) == GPIO_PIN_SET){printf("Key 2 released.\n");Button2PressedFlag = 0;}}}
}

上面实现的是两个按键消抖的处理。非阻塞方式可实现两个LED灯的同时点亮和熄灭,阻塞方式只能一个一个地操作。


  • 外部中断方式
    ①. 将按键GPIO设置为外部中断输入方式,中断捕获类型可根据实际电路设置为上升沿或下降沿,这里我们配置为内部上拉、下降沿中断方式。

    ②. 设置中断优先级,打开中断

    ③. 在stm32f1xx_it.c文件中编写中断回调函数
void EXTI15_10_IRQHandler(void)
{HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12);HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
}       // EXTI15_10_IRQHandler 中断ISR 有CubeMx生成void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{if(GPIO_Pin == GPIO_PIN_12){printf("Button triggered!\n");HAL_Delay(20);if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12) == GPIO_PIN_RESET){HAL_GPIO_TogglePin(Led1_GPIO_Port, Led1_Pin);printf("Led toggled!\n");}}if(GPIO_Pin == GPIO_PIN_13){HAL_Delay(20);if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_13) == GPIO_PIN_RESET){HAL_GPIO_TogglePin(Led2_GPIO_Port, Led2_Pin);}}
}       // 中断回调函数 按键按下之后执行的动作由自己编写

   ⑤. 最后,还需修改一下HAL库中的外部GPIO中断服务函数

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{/* EXTI line interrupt detected */if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u){
//    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);    注释此行HAL_GPIO_EXTI_Callback(GPIO_Pin);__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);     // 添加此行}
}

关于中断消抖的方式,有几个需要注意的点。以上只是实现过程的描述,具体细节下一篇更新


http://www.ppmy.cn/news/751365.html

相关文章

stm32【按键处理:单击、连击、长按】

按键处理 测试平台:STM32F103C8T6 库版本:官方标准库3.5.0版本 按键:机械按键(需消除抖动影响)或触摸按键, 单片机硬件需求:定时器1个,IO口外部中断功能 按键处理是单片机底层驱动…

linux电脑滚轮不能用,鼠标滚轮不能用,小编教你电脑鼠标滚轮不能用怎么办

电脑用户最近遇到了一个问题,他们发现鼠标滚轮在一些应用下会不起作用。比如,我们用edge浏览器打开网页时,鼠标滚轮上下滚动会失效,而在原有的程序里则正常,那么怎么解决鼠标滚轮不能用的问题呢?下面&#…

服务器没有此伴奏文件,yy开直播,播放伴奏就一卡一卡的,不放伴奏就不卡,。是为什么...

1、关闭下载软件: 很多时候在观看直播的时候,下载游戏或者软件,会很大的影响网速,所以在观看YY直播之前,先把下载软件关闭。 2、设置网速优先: 观看YY直播的时候,也许还会聊天,还会做…

计算机鼠标左键不起作用,鼠标左键失灵怎么办 鼠标左键失灵处理方法【详解】...

现在使用电脑的特别多,我们使用电脑时使用最频繁的就是鼠标和键盘了,我们输入都是需要它们的,但是使用时间长了之后,难免会出现鼠标点击能听到咔哒的声音,但是就没反应,或者是一单机就变成双击,…

【Android】WorkManager的使用

序言 本文主要讲WorkManager的一些使用 WorkManager是在 Android 应用中调度和执行后台任务。它提供了一种灵活、可靠的方式来管理后台任务,并确保它们在最佳的设备条件下执行。 以下是 WorkManager 的主要作用: 后台任务调度:WorkManage…

Prompting Chain of Thought思维链开发实战

7.2 Prompting Chain of Thought思维链开发实战 现在看一个提示词思维链具体的应用案例。首先,定义一个get_completion_from_messages的函数,使用GPT-3.5模型,直接使用OpenAI的API,而不是LangChain的方式。 1. import os 2. import openai 3. import sys 4. from dotenv i…

redhat6安装mysql8.0.33

1、下载mysql 官网地址:https://downloads.mysql.com/archives/community/ 下载步骤: 过滤操作系统版本 下载后,上传到服务器Downloads目录 2、安装mysql8 解压压缩包 tar -xvf mysql-8.0.31-1.el9.x86_64.rpm-bundle.tar [rootrhel64 …