3. GPIO中断检测按键事件

GPIO中断检测按键事件 学习卡片

任务说明

本案例实现按键控制LED:读取一个按键的输入状态,按下时点亮LED,松开时熄灭。使用STM32F103最小系统板(Blue Pill)作为目标硬件,通过Rust Embedded HAL编写裸机程序,不依赖任何操作系统。

硬件连接

  • 按键:一端接PA0,另一端接GND(PA0内部上拉,按下为低电平)
  • LED:正极经220Ω电阻接PC13,负极接GND(PC13输出低电平点亮)

实现代码

// Cargo.toml 依赖
// [dependencies]
// cortex-m = "0.7"
// cortex-m-rt = "0.7"
// panic-halt = "0.2"
// stm32f1xx-hal = { version = "0.10", features = ["stm32f103", "rt"] }

use cortex_m_rt::entry;
use panic_halt as _;
use stm32f1xx_hal::{
    gpio::{gpioc::PC13, gpioa::PA0, Input, Output, PullUp, PushPull},
    pac,
    prelude::*,
};

#[entry]
fn main() -> ! {
    // 获取外设访问权限
    let dp = pac::Peripherals::take().unwrap();
    let cp = cortex_m::Peripherals::take().unwrap();

    // 初始化时钟(8MHz外部晶振,系统时钟72MHz)
    let mut flash = dp.FLASH.constrain();
    let mut rcc = dp.RCC.constrain();
    let clocks = rcc.cfgr.use_hse(8.mhz()).sysclk(72.mhz()).freeze(&mut flash.acr);

    // 初始化GPIO
    let mut gpioa = dp.GPIOA.split(&mut rcc.apb2);
    let mut gpioc = dp.GPIOC.split(&mut rcc.apb2);

    // PA0配置为输入,内部上拉(按键按下时接地,读到低电平)
    let button: PA0<Input<PullUp>> = gpioa.pa0.into_pull_up_input(&mut gpioa.crl);

    // PC13配置为推挽输出(LED阳极接PC13,低电平点亮)
    let mut led: PC13<Output<PushPull>> = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);

    // 初始化延时(用于按键消抖)
    let mut delay = cp.SYST.delay(&clocks);

    loop {
        // 读取按键状态(按下为低电平)
        if button.is_low() {
            // 消抖延时
            delay.delay_ms(20u16);
            // 再次确认按键仍处于按下状态
            if button.is_low() {
                // 点亮LED(输出低电平)
                led.set_low();
                // 等待按键释放
                while button.is_low() {
                    // 空循环等待
                }
            }
        } else {
            // 松开时熄灭LED(输出高电平)
            led.set_high();
        }
    }
}

代码说明

程序初始化系统时钟为72MHz,将PA0配置为带上拉输入的按键引脚,PC13配置为推挽输出的LED引脚。主循环中持续读取按键状态:当检测到PA0为低电平(按键按下)时,先进行20ms延时消抖,再次确认按下状态后点亮LED,并等待按键释放;当PA0为高电平(按键松开)时,LED熄灭。消抖逻辑确保机械按键的抖动不会导致LED闪烁。

编译与烧录

# 编译(在项目根目录执行)
cargo build --release

# 烧录(使用OpenOCD + ST-Link)
openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c "program target/thumbv7m-none-eabi/release/button_led verify reset exit"

验证方法

将编译生成的固件烧录到STM32F103开发板后,观察以下行为:

  1. 初始状态(未按键):LED保持熄灭
  2. 按下按键并保持:LED点亮
  3. 松开按键:LED熄灭
  4. 快速连续按动按键:LED状态跟随按键变化,无异常闪烁

判定标准:LED亮灭状态与按键按下/松开状态一一对应,且按键过程中无抖动导致的闪烁现象,即视为验证通过。

STM32F103 Blue Pill PA0 PC13 3.3V GND 按键 信号线 GND 内部上拉 LED 220Ω 信号线 按键按下 → PA0低电平 → LED点亮 按键松开 → PA0高电平 → LED熄灭