STM32HAL库开发第二讲——按键控制LED
一、前言
上一篇中,通过点亮LED实现了GPIO的“输出控制”,但一个完整的嵌入式系统必须具备双向交互的能力。本篇我们将正式跨入“输入”控制,详细讲解如何使用STM32CubeMX配置GPIO的上拉输出和下拉输入模式,并编写经典的按键控制LED灯控制;同时,我们还会分析机械按键不可避免的硬件抖动问题,并分析如何用软件轮询来消除抖动,实现单片机从数字相应到事件触发的转变。
二、按键检测原理
引脚配置成输出上拉模式
硬件电路中有一个硬性规定,引脚不能悬空,如果单片机的引脚什么都不接,它的输入阻抗极高。这时候,周围的空间电磁波、手指靠近、甚至板子上的微笑静电,都能轻易的改变这个引脚的电平。单片机去读取它时,一会儿读到1,一会读到0,处于严重的不稳定状态。为了解决这个问题,引脚在没有外部信号主动输入时,必须有一个明确的默认状态。最常用的按键接线方式是:案件的一端接单片机引脚,另一端直接接地。这时候如果单片机内部配置为输出上拉模式,就不会出现不稳定的状态。如下图所示

当按键没有被按下时,引脚通过内部的上拉电阻接到VDD。因为引脚内部输入阻抗极大,几乎没有电流流动,引脚电压被“拉”在VDD附近。单片机读取到的电平是稳定的高电平(1)。
当按键按下时,引脚直接与地接通。此时,外部地的驱动能力远远大于内部上拉电阻的阻抗,引脚电平被强行拽到0V。单片机读取到的电平是稳定的低电平(0)。
按键抖动
1、为什么会产生抖动
我们平时用的按键,内部其实是两片微小的弹性金属片。当你按下按键时,金属片由于自身弹性和机械惯性,并不会瞬间死死贴在一起,而是在接触的刹那间发生连续的、微小的肉眼不可见的机械弹跳。这就好比一个乒乓球从高处掉到地上,不会立刻粘在地上,而是会上下弹跳几下才最终静止。同理,当按键松开时,金属片断开的瞬间也会产生类似的弹跳。
2. 抖动带来的危害
电平毛刺: 在机械弹跳期间,引脚电平会在高低电平之间疯狂来回切换(形成一串电平毛刺),这个过程通常持续 5ms 到 10ms。
误判后果: 如果你不做任何处理,单片机就会把这串毛刺误认为是你连续快速按下了好几次按键。本来你只想给 LED 翻转一次状态,结果由于抖动,单片机检测到了 5 次动作,LED 疯狂翻转了 5 次,最终亮灭状态完全随机,体验极差。
3. 如何解决抖动
在实际开发中,消抖主要有两种路线:
硬件消抖
在按键两端并联一个 0.1μF 左右的电容。利用电容充放电的“惰性”平滑掉高频的电平毛刺,把突变的波形变成平缓的电压过渡,从而在硬件上直接滤除抖动。
软件消抖
第一次检测: 发现引脚电平变低了(疑似按键按下)。
延时等待: 强制延时 10~20ms(利用 HAL_Delay),主动跳过这一段机械抖动期。
第二次确认: 延时结束后,再次读取引脚电平。如果依然是低电平,说明这次不是噪声干扰,而是真的有人按下了按键,此时才执行相应的控制逻辑。
此篇代码所用的方法就是软件消抖。
三、软件配置
CubeMX 配置步骤:
先新建工程,芯片选择stm32f103c8t6,右上角start
设置调试接口

设置引脚参数
最小系统板上有一颗板载LED,接在PC13引脚上


按键要接在PA9引脚上,这里选择输入模式


配置完成后点击右上角生成代码,CubeMX就帮我们配置好了
这是硬件接线图

四、代码展示
GPIO_PinState HAL_GPIO_WritePin(GPIOx,GPIO_Pin)
这个编程接口的作用是读取当前IO口的电平值,它还有一个返回值,类型是GPIO_PinState,是一个枚举类型,用来返回IO引脚的读数:GPIO_PIN_RESET----0,GPIO_PIN_SET----1
while (1)
{
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_9)==GPIO_PIN_SET)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
}else
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
}
}
这里实现的功能是按键按下就点亮板载LED,松开就熄灭,如果要实现按下一次按键再松开就改变LED状态的话,需要对按键实行软件消抖
while (1)
{
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_9)== GPIO_PIN_RESET)// 检测按键按下(低电平有效)
{
HAL_Delay(20);// 按下消抖
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_9)== GPIO_PIN_RESET)// 确认按键按下
{
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);// 翻转LED
while (HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_9) == GPIO_PIN_RESET);// 等待按键释放
HAL_Delay(20); // 释放消抖
}
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
这里就实现了对按键的消抖,同时按下按键并松开就会改变LED当前的状态。
五、总结
本篇实现了从“输出”向“输入”人机交互的跨越。核心逻辑是利用 STM32 内部的输入上拉(Pull-up)模式,为 PA9(按键引脚) 提供稳定的默认高电平,防止悬空干扰;针对机械按键不可避免的硬件抖动(5~10ms 毛刺),我们在 while(1) 循环中引入了 20ms 软件延时消抖 与 死等松手机制,精准控制 PC13(板载 LED 驱动引脚) 的电平翻转。虽然这种“轮询法”会因阻塞死等而浪费 CPU 资源,但它建立起了输入检测的完整底层逻辑。
更多推荐



所有评论(0)