2. 按键输入检测与消抖
任务目标
使用STM32微控制器的GPIO输入功能读取按键状态,通过软件延时消抖处理机械按键的抖动问题,实现按键按下时翻转LED的亮灭状态。本案例以STM32F103系列为例,使用标准外设库完成GPIO输入模式配置与按键检测逻辑。
硬件连接
- 按键一端接PA0引脚,另一端接地(低电平有效)
- LED正极通过限流电阻接PC13引脚,负极接地(高电平点亮)
- PA0需配置为上拉输入模式,确保按键未按下时引脚为高电平
关键代码
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
// 延时函数(简单软件延时,约1ms @72MHz)
void Delay_ms(uint32_t ms) {
uint32_t i, j;
for (i = 0; i < ms; i++)
for (j = 0; j < 7200; j++);
}
// 按键消抖检测函数:返回1表示确认按下(已消抖),返回0表示未按下
uint8_t Key_Scan(void) {
if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0) { // 检测到低电平
Delay_ms(20); // 延时20ms跳过抖动区
if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0) { // 再次确认仍为低电平
while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0); // 等待按键释放
return 1; // 确认一次有效按下
}
}
return 0;
}
int main(void) {
GPIO_InitTypeDef GPIO_InitStructure;
// 使能GPIOA和GPIOC时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);
// 配置PA0为上拉输入(按键输入)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置PC13为推挽输出(LED控制)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_SetBits(GPIOC, GPIO_Pin_13); // 初始状态:LED灭
while (1) {
if (Key_Scan()) {
// 翻转LED状态
if (GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13) == 0) {
GPIO_SetBits(GPIOC, GPIO_Pin_13); // 置高,LED灭
} else {
GPIO_ResetBits(GPIOC, GPIO_Pin_13); // 置低,LED亮
}
}
}
}
编译与运行
- 使用Keil MDK或IAR创建工程,选择对应STM32F103型号,添加上述代码
- 在工程配置中启用标准外设库(STM32F10x_StdPeriph_Lib)
- 编译生成HEX文件,通过ST-Link或J-Link下载至开发板
验证方法
程序下载后,按下按键并释放,观察LED状态是否翻转。快速连续按动按键,每次按下释放后LED应恰好翻转一次,不会出现多次翻转或闪烁现象。若LED状态不稳定或一次按键多次翻转,说明消抖延时不足或按键释放检测逻辑有误,可适当增加延时时间至30~50ms。
消抖原理说明
机械按键在按下和释放瞬间会产生约5~10ms的电平抖动,表现为引脚电平在高低之间快速跳变。本案例采用“检测低电平→延时20ms→再次检测”的软件消抖方法:若第一次检测到低电平后延时20ms仍为低电平,则判定为有效按下;随后等待按键释放,确保一次按键只触发一次动作。这种消抖方式不依赖额外硬件,适用于大多数按键场景。