【STM32】HAL库——按键原理及消抖

本文详细介绍了STM32中按键消抖的原理和实现方法,包括硬件消抖和软件消抖。通过STM32CubeMX配置时钟和GPIO,以及在MDK5中编写代码,展示了如何利用软件消抖提高按键检测的准确性。最终实现了100%的按键响应准确率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前期准备:

  1. STM32CubeMX
  2. STM32RCT6核心板
  3. IDE Keil(MDK-ARM)

什么是按键消抖?

按键消抖通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖

按键工作原理

在这里插入图片描述
这是最基本的按键电路,以KEY1为例:
3.3V流经10k电阻(限流电阻),经过按键再流入地,但是按键常态是松开的,也就是说这条路常态是是断开的,只有当按键按下时,这条路才能走通,才有电流。
那么此时我们引入一个IO口到KEY1的回路中,通过检测IO口的电平,即可知道这个回路是否有电流,即可知道按键是否按下

1.硬件消抖

硬件消抖一般是在电路硬件设计时考虑进去,提高电平的检测准确度。硬件消抖有很多种,这里我们介绍并联电容消抖法
在这里插入图片描述
电路中按键并联了一个电容。我们知道电容两端电压不能突变

如果把电比作水,电容就像一块海绵,它无法瞬间从瘪变到膨胀,对应电路就是两端电压无法突变,因为电压会给电容充电,充满电后再放电,这个充放电过程的时间由本身参数决定,所以一般采用0.1uf电容即可

因为按键时接触抖动会产生的毛刺电压,由于电容两端电压不能突变,使得按键两端的电压平缓,可以大大提升按键精确度。

2.软件消抖

光有硬件消抖,大概率能满足大部分情况,但有时候需要更精确的场合,这时就需要软件消抖上场了,何为软件消抖,说白了就是写代码,使得按键判断精确一点

STM32CubeMX部分

1. 配置时钟

选择STM32F103RCTx系列芯片,配置时钟的同时会自动配置IO口引脚
在这里插入图片描述
将HCLK设置为最大频率72MHz
在这里插入图片描述

2. 配置GPIO
在这里插入图片描述

  • PC4——>GPIO_Output模式
  • PB4——>GPIO_Input模式

在这里插入图片描述

3. 工程生成
在这里插入图片描述
在这里插入图片描述
工程管理依旧是这几个选项,然后GENERATE CODE,STM32CubeMX部分完成。

MDK 5部分

未消抖:
在while里写入

if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == 0)
{
	HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
}//按一次翻转一次电平

未消抖效果如图


可以看到未消抖的效果非常差、一次按键被误读多次,严重影响使用体验

消抖:
打开gpio.c文件

/* USER CODE BEGIN 0 */
#define KEY1  HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)//读取按键1
#define KEY2  HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)//读取按键2  
#define KEY3  HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2)//读取按键3
#define KEY4  HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_3)//读取按键4

#define KEY1_PRES   1	//KEY1按下
#define KEY2_PRES	2	//KEY2按下
#define KEY3_PRES	3	//KEY3按下
#define KEY4_PRES	4 //KEY4按下
/* USER CODE END 0 */

本篇作为例程我只用了1个按键,一般来说用到了按键,肯定不会只用1个,这里的代码我按照4个按键来写的

接着再写入检测按键函数

/* USER CODE BEGIN 2 */
//按键处理函数
//返回按键值
//0 没有键按下
//1 KEY1按下
//2 KEY2按下
//3 KEY3按下
//4 KEY4按下
//优先响应级别:KEY0>KEY1>KEY2>KEY3
uint8_t KEY_Scan(uint8_t mode)
{	 
	static uint8_t key_up=1;//按键松开标志位
	if(key_up&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))
	{
		HAL_Delay(10);//去抖动
		key_up=0;
		if(KEY1==0)return KEY1_PRES;
		else if(KEY2==0)return KEY2_PRES;
		else if(KEY3==0)return KEY3_PRES;
		else if(KEY4==0)return KEY4_PRES;
	}
	else if(KEY1==1||KEY2==1||KEY3==1||KEY4==1)key_up=1; 	    
 	return 0;//无按键按下
}
/* USER CODE END 2 */

接着回到main.c文件

/* USER CODE BEGIN Includes */
#define KEY1_PRES   1	//KEY1按下
#define KEY2_PRES	2	//KEY2按下
#define KEY3_PRES	3	//KEY3按下
#define KEY4_PRES	4   //KEY4按下
/* USER CODE END Includes */

在while里写入

/* USER CODE BEGIN 3 */			   
	switch(KEY_Scan(0))
	{				 
		case KEY1_PRES:	
			HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
			break;
		case KEY2_PRES:	
			
			break;
		case KEY3_PRES:	
			
		  break;
        case KEY4_PRES:
			
			break;
	}
	/*if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == 0)
	{
		HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
	}*/
  }
  /* USER CODE END 3 */

编译下载时需要选择相对应的下载器,勾选以下
在这里插入图片描述
消抖效果如图


响应准确率100%

本期工程文档——>Gitee

<think>好的,我现在需要帮助用户了解如何使用STM32 HAL实现按键控制。首先,我得回顾一下用户提供的引用内容,看看里面有没有相关的信息。引用[1]提到HAL和LL,但没有具体的按键控制示例。引用[2]和[3]都提到了按键输入的实例,特别是引用[3]详细介绍了GPIO的配置和HAL的使用步骤,这应该是最有用的。 接下来,我需要整理出一个清晰的步骤,从配置STM32CubeMX到编写代码。用户可能对STM32CubeMX不太熟悉,所以第一步应该是创建工程和选择型号,比如STM32L051K8T6。然后配置GPIO引脚为输入模式,选择上拉或下拉,这取决于硬件设计。根据引用[3],按键通常连接到GPIO口,配置为输入模式,并启用内部上拉电阻,这样按键按下时引脚电平会变化。 接着,生成代码后,用户需要了解如何在Keil中编写按键检测的逻辑。这里应该使用轮询方式,在主循环中不断检查按键状态。HALHAL_GPIO_ReadPin函数可以读取引脚状态。同时,防处理是必须的,简单的延时即可,但更复杂的可能需要定时器中断。引用[3]中提到了轮询法和中断法,但用户的问题可能只需要基础示例,所以先介绍轮询法。 用户可能还会关心如何测试,比如用LED灯来反馈按键状态,这需要在代码中配置LED的GPIO为输出,并在按键按下时翻转LED状态。这部分的代码示例需要包括GPIO的初始化和主循环中的逻辑。 最后,生成相关问题,帮助用户深入理解。比如如何实现长按和短按,或者使用外部中断的方法。这些扩展问题可以引导用户进一步学习。 检查是否遵循了系统级指令,所有数学公式用$...$,但这里可能不需要。代码部分用代码块,并确保LaTeX语法正确。回答使用中文,结构清晰,分步骤说明。引用部分要正确标注,例如配置步骤参考了引用[2]和[3]。 总结一下,回答的结构应该是:步骤1到步骤5,配置CubeMX,编写代码,防处理,测试方法,然后相关问题。确保每个部分都有对应的引用标注,并且代码示例正确无误。同时,注意用户可能需要的细节,比如具体的函数调用和配置选项。</think>### STM32 HAL按键控制实现步骤 #### 1. **STM32CubeMX配置**(参考引用[2][^2]) - **创建工程**:选择对应型号(如STM32L051K8T6) - **GPIO配置**: - 按键引脚设为`GPIO_Input`模式 - 根据硬件设计选择上拉(Pull-up)或下拉(Pull-down) - 例如:按键接地时选择内部上拉,按下时电平为低 - **时钟配置**:确保GPIO所在总线时钟已使能 ![STM32CubeMX GPIO配置示意图](https://via.placeholder.com/300x200/EEE/aaa?text=GPIO_Input+Mode) #### 2. **Keil代码实现**(参考引用[3][^3]) ```c // main.c int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); while (1) { if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) // 按键按下检测 { HAL_Delay(50); // 简单防 if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) { // 执行按键操作(如翻转LED) HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5); while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET); // 等待释放 } } } } ``` #### 3. **防处理优化** - **硬件防**:并联0.1μF电容 - **软件防进阶**: ```c // 使用定时器中断实现精准防 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { static uint8_t debounce_cnt = 0; if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) debounce_cnt++; else debounce_cnt = 0; if(debounce_cnt > 5) // 5ms确认有效 HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5); } ``` #### 4. **测试验证方法** - 使用逻辑分析仪观察GPIO电平变化 - 配合LED灯验证按键响应 - 通过`printf`输出调试信息(需配置串口)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值