2. 按键控制LED亮灭

任务目标

使用MCU的GPIO引脚连接一个按键和一个LED,通过读取按键状态控制LED的亮灭。按键按下时LED点亮,松开时LED熄灭,并实现按键消抖以避免机械抖动导致的误触发。

硬件连接

  • LED正极通过限流电阻(约220Ω)连接至MCU的PB0引脚,负极接地
  • 按键一端连接至MCU的PB1引脚,另一端接地(按下为低电平)
  • PB1引脚内部启用上拉电阻,确保未按下时读取为高电平

完整代码(STM32F103 HAL库)

#include "stm32f1xx_hal.h"

// 引脚定义
#define LED_PIN         GPIO_PIN_0
#define LED_PORT        GPIOB
#define KEY_PIN         GPIO_PIN_1
#define KEY_PORT        GPIOB

// 简单延时函数(非精确,用于消抖)
static void delay_ms(volatile uint32_t ms) {
    for (volatile uint32_t i = 0; i < ms * 4000; i++) {
        __NOP();
    }
}

int main(void) {
    HAL_Init();
    __HAL_RCC_GPIOB_CLK_ENABLE();

    // 配置LED引脚为推挽输出
    GPIO_InitTypeDef gpio_led = {0};
    gpio_led.Pin = LED_PIN;
    gpio_led.Mode = GPIO_MODE_OUTPUT_PP;
    gpio_led.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(LED_PORT, &gpio_led);

    // 配置按键引脚为输入,启用内部上拉
    GPIO_InitTypeDef gpio_key = {0};
    gpio_key.Pin = KEY_PIN;
    gpio_key.Mode = GPIO_MODE_INPUT;
    gpio_key.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(KEY_PORT, &gpio_key);

    // 初始状态:LED熄灭
    HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET);

    while (1) {
        // 检测按键是否按下(低电平有效)
        if (HAL_GPIO_ReadPin(KEY_PORT, KEY_PIN) == GPIO_PIN_RESET) {
            delay_ms(20);  // 延时消抖

            // 再次确认按键仍处于按下状态
            if (HAL_GPIO_ReadPin(KEY_PORT, KEY_PIN) == GPIO_PIN_RESET) {
                HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET);  // LED点亮
            }
        } else {
            HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET);  // LED熄灭
        }
    }
}

编译与烧录

  1. 使用STM32CubeIDE创建新工程,选择对应MCU型号(如STM32F103C8T6)
  2. 将上述代码替换main.c中的默认内容
  3. 编译工程(Project → Build),确认无错误
  4. 通过ST-Link连接开发板,点击Run或Debug烧录程序

验证方法

  • 程序烧录后,LED初始状态为熄灭
  • 按下按键不放,LED应点亮;松开按键,LED立即熄灭
  • 快速连续按动按键,LED状态应稳定跟随,不会出现闪烁或误动作(消抖生效)

若LED状态与按键动作完全同步且无抖动干扰,则判定案例通过。

关键说明

  • 消抖原理:按键按下瞬间会产生约5~20ms的机械抖动,通过首次检测到低电平后延时20ms再确认一次,可过滤抖动信号
  • 本例采用查询方式检测按键,适用于单按键场景;若需多按键或低功耗应用,可改用外部中断+定时器消抖方案
  • delay_ms函数为软件延时,实际延时时间与系统时钟频率相关,本代码基于默认8MHz内部时钟估算