STM32F103C8T6 轻触按键演示

从按键外形到程序逻辑,从电路原理到交互演示 —— 全面解析轻触按键的检测与消抖

芯片:STM32F103C8T6  |  HAL库  |  按键:PB11  |  LED:PC13

1轻触按键介绍

认识轻触按键的外形特征、工作原理与核心功能

A外形特征

本演示使用的是经典的 6×6mm 四脚轻触按键,是电子设计中最常见的按键类型之一。其外观小巧,顶部有一个圆形按钮帽,底部有四个引脚。

轻触按键正面
轻触按键背面
焊接在板子上
引脚结构:四个引脚分为两组(左侧两脚一组,右侧两脚一组),同组的两个引脚内部是连通的。按键未按下时,两组之间断开;按下后,四脚全部导通。焊接时无需区分方向,对角引脚即可当作两端开关使用。

B工作原理

机械原理

按键内部有一个金属弹片( dome ),按下按钮帽时,弹片受力变形向下凸起,接触底部的两个触点,使电路导通;松开后弹片依靠自身弹性恢复原状,触点分离,电路断开。

未按下(断开) ✕ 按下(导通) 压力 ✓

电气原理

在电路中,轻触按键相当于一个常开型开关。配合上拉电阻,可以实现"默认高电平、按下低电平"的检测方案:

VCC (3.3V) R 10kΩ PB11 GPIO引脚 KEY 轻触按键 GND 未按下: 3.3V 按下: 0V
核心逻辑:上拉电阻将 GPIO 引脚拉至高电平(3.3V);按键另一端接地(GND)。未按下时,引脚读到高电平(1);按下时,引脚被直接拉到地,读到低电平(0)。这就是"低电平有效"的按键检测方案。

C核心功能

  • 人机交互输入:将用户的物理按压动作转化为 MCU 可读取的电信号(高/低电平)
  • 电平翻转:每次按下并松开后,翻转 LED 状态(亮↔灭),实现"按键开关"效果
  • 消抖处理:通过软件延时 10ms 过滤机械触点抖动,确保每次按压只触发一次
  • 边沿检测等效:"等待松开再动作"的模式等效于检测按键的下降沿(按下)+上升沿(松开),保证一次完整按压只响应一次

2硬件电路分析

原理图、PCB布局与引脚分配

A原理图

按键原理图
按键原理图
按键PCB封装
按键PCB封装

B引脚分配

外设引脚GPIO模式上下拉初始电平说明
LED PC13 推挽输出 (OUTPUT_PP) 无 (NOPULL) 高 (SET) 板载LED,低电平点亮
KEY PB11 输入模式 (INPUT) 上拉 (PULLUP) 高 (默认) 按下接地,读低电平
电路连接说明:
• LED(PC13):STM32F103C8T6 最小系统板的板载 LED 接在 PC13 上,低电平点亮。初始设为高电平(SET),即默认熄灭。
• KEY(PB11):配置为上拉输入模式,启用内部上拉电阻。按键一端接 PB11,另一端接 GND。未按下时由上拉电阻保持高电平;按下时引脚被拉至 GND,读到低电平。

CGPIO 配置代码

gpio.c — MX_GPIO_Init()
void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO 端口时钟使能 */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /* LED 初始输出高电平(熄灭) */
  HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);

  /* LED 引脚配置:推挽输出 */
  GPIO_InitStruct.Pin   = LED_Pin;              // PC13 */
  GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;   // 推挽输出 */
  GPIO_InitStruct.Pull  = GPIO_NOPULL;           // 无上下拉 */
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;   // 低速即可 */
  HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct);

  /* KEY 引脚配置:上拉输入 */
  GPIO_InitStruct.Pin  = KEY_Pin;                // PB11 */
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;        // 输入模式 */
  GPIO_InitStruct.Pull = GPIO_PULLUP;            // 内部上拉 */
  HAL_GPIO_Init(KEY_GPIO_Port, &GPIO_InitStruct);
}

3程序分析

主循环逐行解读 — 按键检测、消抖与LED翻转

A主循环完整代码

main.c — while(1) 主循环
while (1)
{
    // ① 检测按键是否按下(读到低电平 = RESET)
    if(HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin) == GPIO_PIN_RESET)
    {
        HAL_Delay(10);  // ② 延时10ms,软件消抖
        if(HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin) == GPIO_PIN_RESET)  // ③ 再次确认
        {
            while(HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin) == GPIO_PIN_RESET);  // ④ 等待松开
            HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);  // ⑤ 翻转LED
        }
    }
}

B逐行解析

① 检测按键按下

if(HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin) == GPIO_PIN_RESET)

HAL_GPIO_ReadPin() 读取 PB11 的电平。由于配置了内部上拉,未按下时为高电平(SET),按下时为低电平(RESET)。当读到 RESET,说明按键可能被按下。

② 延时10ms消抖

HAL_Delay(10);

机械按键在闭合瞬间,金属弹片会发生弹性抖动,导致电平在 0 和 1 之间快速跳变,持续约 5~10ms。HAL_Delay(10) 跳过这段抖动期,等信号稳定后再判断。

为什么要消抖?如果不消抖,一次按压可能在抖动期内被 MCU 误读为多次快速按压,导致 LED 来回翻转多次。

③ 再次确认

if(HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin) == GPIO_PIN_RESET)

延时后再次读取引脚电平。如果仍为 RESET,确认是真正的按键按下(而非干扰噪声);如果恢复为 SET,说明之前的低电平是抖动或干扰,忽略本次触发。

④ 等待按键松开

while(HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin) == GPIO_PIN_RESET);

这是一个空循环,持续检测引脚电平。只要按键还按着(RESET),程序就停在这里等待。直到用户松开按键,电平恢复为 SET,循环退出。这一步保证"按一次只翻转一次"。

⑤ 翻转LED

HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);

按键松开后,调用 HAL_GPIO_TogglePin() 翻转 PC13 的输出电平。如果当前是高(灭)→ 变低(亮);如果是低(亮)→ 变高(灭)。每次完整按压-松开周期,LED 切换一次状态。

4程序流程图

完整的检测-消抖-响应流程

主循环 while(1) 读取 KEY 引脚电平 电平 == RESET? (按键按下?) 否 未按下 是 延时 10ms(消抖) 仍为 RESET? (确认按下?) 否 抖动 是 等待按键松开 翻转 LED 状态 ↻ 继续 循环检测
流程要点:整个流程采用了"两次检测 + 等待松开"的经典消抖模式。第一次检测捕捉按键事件,10ms延时后第二次检测确认真实性,等待松开确保一次按压只响应一次,最后翻转LED。这种"检测-消抖-确认-等待-执行"的模式是嵌入式按键处理的标准范式。

5交互演示

点击按钮体验完整的按键检测-消抖-LED翻转过程

硬件模拟

按住
轻触按键 (PB11) — 鼠标按住=按下,松开=松开
PB11 电平
3.3V
板载 LED (PC13)
熄灭

信号波形

执行步骤

① 检测按键电平
② 延时 10ms 消抖
③ 再次确认按键
④ 等待按键松开
⑤ 翻转 LED 状态
使用说明:用鼠标按住上方圆形按钮模拟按键按下(电平拉低),松开鼠标模拟按键松开(电平拉高),即可触发完整的检测-消抖-LED翻转流程。也可点击"自动播放"观看完整动画演示。波形图实时展示 PB11 引脚的电平变化,包括按下和松开瞬间的抖动。

STM32F103C8T6 轻触按键演示  |  HAL库  |  按键检测+软件消抖+LED翻转

演示程序基于 STM32CubeMX 生成