3. 按键控制LED
任务说明
本案例实现按键控制LED:按下按键时LED点亮,松开时LED熄灭。核心目标是掌握GPIO输入模式的配置方法、按键消抖处理以及输入状态的读取逻辑。硬件连接为:按键一端接MCU的PA0引脚,另一端接GND(按下时PA0为低电平);LED正极经限流电阻接PC13引脚,负极接GND(PC13输出高电平时LED点亮)。
硬件连接
按键采用“按下接地”接法,配合MCU内部上拉电阻,空闲时PA0读到高电平,按下时读到低电平。LED由PC13引脚直接驱动,需串联约330Ω限流电阻。
代码实现
#include "stm32f1xx_hal.h"
/* 按键引脚:PA0 */
#define KEY_PORT GPIOA
#define KEY_PIN GPIO_PIN_0
/* LED引脚:PC13 */
#define LED_PORT GPIOC
#define LED_PIN GPIO_PIN_13
/* 简单延时(非精确,仅用于消抖) */
static void delay_ms(volatile uint32_t ms)
{
for (volatile uint32_t i = 0; i < ms * 4000; i++) {
__NOP();
}
}
int main(void)
{
HAL_Init();
/* 1. 使能GPIOA和GPIOC时钟 */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/* 2. 配置PA0为输入模式,内部上拉 */
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);
/* 3. 配置PC13为推挽输出 */
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);
/* 4. 初始状态:LED熄灭 */
HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET);
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_SET); /* 点亮LED */
}
}
else
{
HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET); /* 熄灭LED */
}
}
}
代码说明
代码核心逻辑如下:
- GPIO输入配置:PA0设置为输入模式并启用内部上拉电阻,确保按键悬空时引脚电平稳定为高。
- 按键消抖:首次检测到低电平后延时20ms再次读取,若仍为低电平则判定为有效按下,避免机械抖动导致的误触发。
- LED控制:PC13配置为推挽输出,按下时输出高电平点亮LED,松开时输出低电平熄灭LED。
编译与烧录
本代码基于STM32CubeMX生成的HAL库工程,适用于STM32F103系列。在STM32CubeIDE中新建工程,选择对应MCU型号,将上述代码替换main.c中的主函数内容,并确保已生成HAL库初始化代码。编译通过后,使用ST-Link通过SWD接口烧录到开发板。
验证方法
完成烧录并复位开发板后,按以下步骤验证:
- 观察LED初始状态应为熄灭。
- 按下按键不放,LED应立即点亮。
- 松开按键,LED应立即熄灭。
- 快速连续按动按键,LED应跟随按键状态稳定切换,无闪烁或误动作。
判定标准:若LED亮灭与按键按下/松开状态完全同步,且无抖动误触发,则本案例验证通过,说明GPIO输入读取与消抖逻辑正确。