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

这篇具有很好参考价值的文章主要介绍了STM32按键消抖的几种实现方式-STM32 Button Debouncing。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、按键抖动的现象

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


二、 硬件电路消抖

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

  • RC电路
    stm32按键消抖,STM32,stm32,单片机,arm
    stm32按键消抖,STM32,stm32,单片机,arm
  • RC电路加施密特触发器
    stm32按键消抖,STM32,stm32,单片机,arm

三、 软件消抖

3.1 按键状态分析

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

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设置为外部中断输入方式,中断捕获类型可根据实际电路设置为上升沿或下降沿,这里我们配置为内部上拉、下降沿中断方式。
    stm32按键消抖,STM32,stm32,单片机,arm
    ②. 设置中断优先级,打开中断
    stm32按键消抖,STM32,stm32,单片机,arm
    ③. 在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);     // 添加此行
  }
}

关于中断消抖的方式,有几个需要注意的点。以上只是实现过程的描述,具体细节下一篇更新文章来源地址https://www.toymoban.com/news/detail-791584.html

到了这里,关于STM32按键消抖的几种实现方式-STM32 Button Debouncing的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 单片机入门资料,按键消抖方式,按键怎么消抖

     1.什么是按键消我们先来看一下按键按下去的波形图   1.按键消抖原理 我们可以看到当按键按下的那一时刻和松开的时候有类似于锯齿的形状那就是按键抖动,这个抖动不是我们人为能控制得了的,所以我们只能对进行硬件消抖或者进行软件消抖.          上图中我们可以

    2024年02月08日
    浏览(41)
  • 【STM32】STM32 CANFD外设的几种消息接收过滤模式

    在控制器区域网络(CAN)系统中,正确配置消息过滤器对于有效管理网络通信至关重要。特别是在使用Flexible Data-rate Controller Area Network(FDCAN)时,选择合适的过滤器类型可以大大提高网络效率和消息处理速度。 STM32G47x芯片的CAN外设有如下几种接收消息过滤方法: 这是一种范

    2024年01月18日
    浏览(37)
  • C语言-单片机:STM32程序烧录的几种方法

    STM32微控制器提供了多种程序烧录(也称为编程或固件更新)方式,这些方法允许用户将编译后的程序代码(通常为HEX或BIN格式)下载到MCU的闪存中。以下是几种常见的STM32程序烧录方式: ST-LINK : ST-LINK/V2 : 这是最常用的官方开发工具之一,可以直接通过USB接口与PC连接。S

    2024年04月26日
    浏览(46)
  • [FOC-Stm32]设置PWM占空比(比较值)的几种方法

    近期博主在阅读一些基于STM32的FOC代码中,对PWM占空比的设置问题很感兴趣,于是找了分别拿出来做了一下对比,来看看都是怎么来调整PWM输出的。 下图给出了PWM占空比调整的原理,在定时器循环中,有两个量:ARR 重装载值和 CCR 比较值。定时器内的计数器从0到ARR循环记录数

    2024年02月15日
    浏览(46)
  • 实现跨域的几种方式

    前后端的分离导致了跨域的产生  跨域的三要素:协议 域名 端口 三者有一个不同即产生跨域 例如: http ://www.csdn.com https ://www.csdn.com 由于协议不同,端口不同而产生跨域 注:http的默认端口80,https的默认端口443 跨域的解决方案 前端:webpack proxy,jsonp,ngix反向代理,webpac

    2024年02月13日
    浏览(47)
  • 前端实现动画的几种方式简介

    这里只是做简要介绍,属于知识的拓展。每种方案的更详细的使用方式需要各位自行了解。 大体上技术方案分为:CSS 动画、SVG 动画、CSS + SVG、JS 控制的逐帧动画、GIF 图。 CSS 实现动画有两种方式,一种是使用 trasition ;另一种是使用 animation 。 默认情况下,当 CSS 中的属性值

    2024年04月22日
    浏览(49)
  • Java实现异步的几种方式

    普通线程实现异步,但频繁创建、销毁线程比较耗资源,所以一般交给线程池执行 结果: Future异步 和普通线程实现异步区别不大,只是使用Future是要获取执行后的返回值 结果: Spring的@Async异步 使用@Async注解实现异步的前提是需要在启动类上标注@EnableAsync来开启异步配置

    2024年02月04日
    浏览(70)
  • 单例模式的几种实现方式

    在Java中,实现单例模式主要有几种方式:懒汉式、饿汉式、双重检查锁定、静态内部类和枚举。每种方式都有其特点和适用场景。 1. 饿汉式(线程安全) 饿汉式是最简单的一种实现方式,通过静态初始化实例,保证了线程安全。但它不是懒加载模式,无法在实际使用时才创

    2024年02月20日
    浏览(52)
  • 线程间实现通信的几种方式

    线程间通信的模型有两种:共享内存和消息传递,下面介绍的都是围绕这两个来实现 有两个线程A和B,B线程向一个集合里面依次添加元素“abc”字符串,一共添加10次,当添加到第五次的时候,希望线程A能够收到线程B的通知,然后B线程执行相关的业务操作 Object类提供了线程

    2024年02月15日
    浏览(68)
  • 游戏中模型动画的几种实现方式

    游戏内动画的实现方式一般有这几种: 骨骼动画 顶点动画 材质动画 CPU蒙皮动画 骨骼动画是一种基于骨骼系统的动画技术,它通过对骨骼进行变换来控制模型的姿态和动作。 在骨骼动画中,模型通常被分解成多个部分,每个部分都与一个或多个骨骼相连,通过对骨骼进行旋

    2024年02月05日
    浏览(64)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包