2. 按键输入检测与消抖波形分析
任务说明
本案例实现一个基于MCU GPIO的按键输入检测程序,包含硬件消抖与软件消抖两种方式,并通过逻辑分析仪捕获按键按下/释放过程中的电平波形,验证消抖效果。核心目标:理解机械按键抖动特性,掌握软件消抖的边界条件判定方法。
硬件连接与测试拓扑
消抖原理与波形特征
机械按键在按下与释放瞬间,簧片接触会产生持续约5~20ms的不稳定抖动,表现为电平在高低之间多次跳变。硬件消抖采用RC低通滤波器(R=10kΩ,C=100nF,时间常数τ=1ms),将高频抖动分量滤除,使边沿变得平滑;软件消抖则通过延时采样,跳过抖动期后再确认电平状态。
代码实现
// main.c - 按键输入检测与消抖 (STM32F103, HAL库)
#include "stm32f1xx_hal.h"
// 按键引脚定义
#define BTN_HW_PORT GPIOA
#define BTN_HW_PIN GPIO_PIN_0 // PA0 - 硬件消抖按键(外部RC)
#define BTN_SW_PORT GPIOA
#define BTN_SW_PIN GPIO_PIN_1 // PA1 - 软件消抖按键
// 软件消抖延时(ms) - 需大于抖动周期(典型10ms)
#define DEBOUNCE_MS 10
static GPIO_InitTypeDef GPIO_InitStruct = {0};
// 按键状态枚举
typedef enum {
KEY_RELEASED = 0,
KEY_PRESSED
} KeyState_t;
// 软件消抖读取函数
// 返回: KEY_PRESSED(稳定按下) 或 KEY_RELEASED(稳定释放)
KeyState_t SW_Debounce_Read(GPIO_TypeDef* port, uint16_t pin) {
// 第一次采样
if (HAL_GPIO_ReadPin(port, pin) == GPIO_RESET) {
// 延时跳过抖动期
HAL_Delay(DEBOUNCE_MS);
// 第二次采样确认
if (HAL_GPIO_ReadPin(port, pin) == GPIO_RESET) {
return KEY_PRESSED;
}
}
return KEY_RELEASED;
}
// 硬件消抖读取函数(直接读取RC滤波后的电平)
KeyState_t HW_Debounce_Read(GPIO_TypeDef* port, uint16_t pin) {
// RC滤波已消除抖动,直接读取即可
return (HAL_GPIO_ReadPin(port, pin) == GPIO_RESET) ?
KEY_PRESSED : KEY_RELEASED;
}
int main(void) {
HAL_Init();
__HAL_RCC_GPIOA_CLK_ENABLE();
// 配置PA0, PA1为输入上拉
GPIO_InitStruct.Pin = BTN_HW_PIN | BTN_SW_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置PA5为LED输出(指示按键状态)
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
KeyState_t hw_state, sw_state;
while (1) {
// 读取两个按键状态
hw_state = HW_Debounce_Read(BTN_HW_PORT, BTN_HW_PIN);
sw_state = SW_Debounce_Read(BTN_SW_PORT, BTN_SW_PIN);
// 任一按键按下时点亮LED
if (hw_state == KEY_PRESSED || sw_state == KEY_PRESSED) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); // LED亮
} else {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); // LED灭
}
}
}
逻辑分析仪观测点
验证方法与判定标准
- 编译与烧录:使用STM32CubeIDE编译工程,通过ST-Link烧录至目标板。
- 硬件连接:按上图连接电路,逻辑分析仪CH0接PA0,CH1接PA1,共地。
- 波形捕获:设置逻辑分析仪采样率≥1MHz,触发方式为下降沿,按下SW1和SW2各一次。
- 判定标准:
- CH0(硬件消抖)波形:按下/释放边沿平滑,无任何毛刺跳变;
- CH1(软件消抖)波形:存在明显抖动毛刺(5~20ms内多次跳变);
- LED行为:每次稳定按下时点亮,释放时熄灭,无闪烁;
- 软件消抖生效:CH1的毛刺虽存在,但程序在10ms后二次确认,LED不误触发。
预期结果:逻辑分析仪显示CH0为干净的数字波形,CH1在边沿处有毛刺;LED仅在按键稳定按下时点亮,快速抖动不会导致LED闪烁。若观察到CH0仍有毛刺,说明RC参数不足(增大C或R);若LED响应迟钝,说明DEBOUNCE_MS过大。