[stm32]stm32按键外部中断,如何消抖

2024-01-09 02:38

本文主要是介绍[stm32]stm32按键外部中断,如何消抖,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

讨论一下stm32下按键外部中断如何进行有效的消抖

工程的代码是直接使用stm32 cubeMX进行配置生成的,下面就一起讨论吧。
1. 在中断处理服务函数中注释清除中断标志的语句,防止按键抖动而不断的进入中断服务程序中
2. 进入回调函数后先进性延时,一般为10ms,进行消抖,然后再判断引脚的电平状态
3. 在结束时一定注意要延时一段时间,然后才清除中断标志,而且要相对消抖时间要长一些,目的是为了松开按键时产生的抖动而又再次进入中断服务程序中,产生的抖动
4. 其实第3步是极其不严谨的。延时一段时间再清除中断标志,如果在清除中断标志的时候。按键仍未松开呢,等到松开时候,仍会有抖动。正确的应该是等待引脚电平的释放,eg(1 != HAL_GPIO_ReadPin(WK_UP_GPIO_Port,WK_UP_Pin)) 。引脚释放了才清除相应的中断标志

注:该处理方式仍属于阻塞等待的方式哦,小伙伴们可以把阻塞等待方式改为使用定时器去定时检测的方式

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{/* EXTI line interrupt detected */if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET){
//    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);HAL_GPIO_EXTI_Callback(GPIO_Pin);}
}void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){if(WK_UP_Pin == GPIO_Pin){HAL_Delay(10);if(1 == HAL_GPIO_ReadPin(WK_UP_GPIO_Port,WK_UP_Pin));myprintf(&huart1, "wake up key pressed\n");}else if(KEY0_Pin == GPIO_Pin){HAL_Delay(10);if(0 == HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin))myprintf(&huart1, "key 0 pressed\n");}else if(KEY1_Pin == GPIO_Pin){HAL_Delay(10);if(0 == HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin))myprintf(&huart1, "key 1 pressed\n");}else if(KEY2_Pin == GPIO_Pin){HAL_Delay(10);if(0 == HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin))myprintf(&huart1, "key 2 pressed\n");}HAL_Delay(100);__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
}

如图:消抖成功
在这里插入图片描述

下面是之前使用标准库写的,程序采用时间片轮询(周期5ms)的方式进行任务处理,不用外部中断的轮询方式

void Key_Config(void){GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC,ENABLE);// Key1 / Key2 / Key3 -> IPUGPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;	GPIO_Init(GPIOC,&GPIO_InitStructure);// SW1 -> IPUGPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPU;		//SW°´¼üÉÏÀ­ÊäÈëGPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;GPIO_Init(GPIOB,&GPIO_InitStructure);// SW2 -> IPUGPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPU;		//SW°´¼üÉÏÀ­ÊäÈëGPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;GPIO_Init(GPIOA,&GPIO_InitStructure);
}u8 Key_Scan(void){u8 i,temp;for(i=0;i<5;i++)	{		temp=KEY_VAL>>i;	if(0x1f!=KEY_VAL && 0==(temp & 0x01))return i+1;}	return 0;	
}
u8 Get_Key(void){static u8 n,status=0,last_val;u8 key_val;key_val=Key_Scan();	if(0!=key_val && key_val==last_val){if(0==status)	status=1;						//°´¼ü°´Ï±êʶelse 	n++;}if(1==status && key_val==0){status=0;													//°´¼üÊͷűêʶif(n>2 && n<25){	//40ms ~ 500ms		//¶Ì°´µ¥»÷ʱ¼ä¿ØÖÆ£¬¸ù¾Ý¿ØÖÆÖÜÆÚʱ¼ä¿ØÖÆ´ÎÊýn=0;														//Çå³ý¼ÆÊýreturn last_val;								//·µ»Ø¼üÖµ}else if(n>=25){		//´óÓÚ 500ms			//³¤°´Ê±¼ä¿ØÖÆn=0;														//Çå³ý¼ÆÊýreturn last_val+10;							//³¤°´¼üÖµ = (¶Ì°´¼üÖµ+10)}else{ 															//°´¼üʱ¼ä¹ý¶Ì±»ÈÏΪÊÇ°´¼ü¶¶¶¯»òÎó°´×´Ì¬n=0;														//Çå³ý¼ÆÊýreturn 20;											//·µ»ØÎó°´×´Ì¬}}last_val=key_val;										//±£´æÉÏÒ»´ÎµÄ¼üÖµreturn 0;
}void TIM2_Config(void){TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);/*	Tout=((arr+1)*(psc+1))/Tclk	*/TIM_TimeBaseStructure.TIM_Prescaler=719;         				//Ô¤·ÖƵ£º72 000 000 / (719+1) = 1 000 00 HzTIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //¼ÆÊý·½Ê½£ºÏòÉϼÆÊýTIM_TimeBaseStructure.TIM_Period= 1999;            				//¼ÆÊýÖÜÆÚ£º1 000 00 / (4999 + 1) = 50 Hz = 0.02 s = 20 msTIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;     //ʱÖÓ²»·Ö¸î	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);NVIC_Config(0,0,TIM2_IRQn,2);	TIM_ITConfig(TIM2,TIM_IT_Update , ENABLE);	TIM_Cmd(TIM2,ENABLE);	
}void TIM2_IRQHandler(void){	if(TIM_GetFlagStatus(TIM2,TIM_IT_Update)!=RESET)	{Key_Val=Get_Key();				//ÔÚÖжϳÌÐòÖлñÈ¡¼üÖµDATA_Task();							//ͨ¹ý°´¼ü»ñȡʹÄÜÄǸöÊý¾Ý´«Ê书ÄÜ£¬Êý¾Ý´«Ê亯ÊýÔÚÖ÷º¯ÊýÖе÷ÓÃTIM_ClearFlag(TIM2,TIM_IT_Update);	}
}

小伙伴们有什么更好的方式吗,欢迎下方评论

这篇关于[stm32]stm32按键外部中断,如何消抖的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/585677

相关文章

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD

STM32内部闪存FLASH(内部ROM)、IAP

1 FLASH简介  1 利用程序存储器的剩余空间来保存掉电不丢失的用户数据 2 通过在程序中编程(IAP)实现程序的自我更新 (OTA) 3在线编程(ICP把整个程序都更新掉) 1 系统的Bootloader写死了,只能用串口下载到指定的位置,启动方式也不方便需要配置BOOT引脚触发启动  4 IAP(自己写的Bootloader,实现程序升级) 1 比如蓝牙转串口,

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

寻迹模块TCRT5000的应用原理和功能实现(基于STM32)

目录 概述 1 认识TCRT5000 1.1 模块介绍 1.2 电气特性 2 系统应用 2.1 系统架构 2.2 STM32Cube创建工程 3 功能实现 3.1 代码实现 3.2 源代码文件 4 功能测试 4.1 检测黑线状态 4.2 未检测黑线状态 概述 本文主要介绍TCRT5000模块的使用原理,包括该模块的硬件实现方式,电路实现原理,还使用STM32类

STM32 ADC+DMA导致写FLASH失败

最近用STM32G070系列的ADC+DMA采样时,遇到了一些小坑记录一下; 一、ADC+DMA采样时进入死循环; 解决方法:ADC-dma死循环问题_stm32 adc dma死机-CSDN博客 将ADC的DMA中断调整为最高,且增大ADCHAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_Buffer_Size); 的ADC_Bu

FreeRTOS学习笔记(四)Freertos的中断管理及临界保护

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、Cortex-M 中断管理1.1 中断优先级分组1.2 相关寄存器1.3 相关宏定义1.4 FreeRTOS 开关中断 二、临界段及其保护2.1 taskENTER_CRITICAL( ) 和 taskEXIT_CRITICAL( )2.2 taskENTER_CRITICAL_FROM_ISR( )

独立按键单击检测(延时消抖+定时器扫描)

目录 独立按键简介 按键抖动 模块接线 延时消抖 Key.h Key.c 定时器扫描按键代码 Key.h Key.c main.c 思考  MultiButton按键驱动 独立按键简介 ​ 轻触按键相当于一种电子开关,按下时开关接通,松开时开关断开,实现原理是通过轻触按键内部的金属弹片受力弹动来实现接通与断开。  ​ 按键抖动 由于按键内部使用的是机

基于stm32的河流检测系统-单片机毕业设计

文章目录 前言资料获取设计介绍功能介绍具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机设计精品