欢迎关注 youcans@xidian【嵌入式软件AI编程】专栏
1. 项目简介
1.1 实验目标
本实验在 NUCLEO-C542RC 开发板上,通过主循环轮询用户按键 B1(PC13),实现按键控制板载 LED 状态翻转,掌握 STM32C5 系列 GPIO 输入与输出的基本用法。
功能需求:
- 在主循环中轮询用户按键(PC13)
- 每次有效按下时切换板载 LED(PA5)的状态
- 持续按住不重复触发,松开后可响应下一次按键
- 消抖时间 20 ms
1.2 实验条件
硬件:
- NUCLEO-C542RC 开发板
- 支持数据传输的 USB Type-C 线(用于连接 ST-LINK 接口)

软件:
- STM32CubeMX2(用于引脚、时钟配置与代码生成)
- VS Code + STM32Cube 插件(用于编译、烧录、调试)
2. 硬件说明
2.1 NUCLEO-C542RC 开发板
NUCLEO-C542RC 是 ST 基于 STM32C542RCT6 推出的 Nucleo-64 开发板。主要特性:
- MCU:STM32C542RCT6,Arm Cortex-M33 内核,最高主频 144 MHz,256 KB Flash,64 KB RAM
- 调试器:板载 STLINK-V3EC,支持大容量存储、虚拟串口和调试端口三种功能
- 用户 LED:LD1,连接 PA5
- 用户按键:B1,连接 PC13
- 复位按键:B2
- 扩展接口:Arduino Uno V3 和 ST morpho 连接器
本实验使用板载的 LD1 和 B1,无需额外外设。

2.2 引脚说明
| 引脚 | 别名 | 功能 | 方向 | 有效电平 |
|---|---|---|---|---|
| PA5 | LD1 | 板载用户 LED | GPIO 输出 | 高电平点亮 |
| PC13 | B1 | 用户按键 | GPIO 输入 | 按下为高电平,松开为低电平 |
PA5(LD1):配置为推挽输出,输出高电平时 LED 点亮,输出低电平时 LED 熄灭。复位后初始状态为低电平(LED 熄灭)。
PC13(B1):配置为输入模式。PC13 通过外部电阻 R13(10K)下拉到地,按键按下时接 3V3。因此空闲时为低电平,按下时为高电平。
3. STM32CubeMX2 工程配置
3.1 新建工程
本实验采用 MCU 方式创建工程,即以芯片型号 STM32C542RC 为起点,而非开发板方式。
-
进入 MCU 选择界面
启动 STM32CubeMX2,在首页点击 MCU,进入芯片型号选择列表。
-
搜索并选中芯片
在 MCU name 输入框中输入 STM32C542RC(或完整型号 STM32C542RCT6),从筛选出的列表中选择对应型号。

- 填写项目信息
输入项目名称 GPIO_Button 和项目保存路径。项目名称避免使用特殊字符,路径建议使用纯英文目录。
3.2 基础配置
工程创建后,软件自动进入 Pinout 视图。时钟配置保持默认即可 :CubeMX2 创建工程后的默认系统主频为 48 MHz,时钟源为 HSI 分频,本实验无需修改。
注意 :本工程的系统时钟为 48 MHz,与之前点灯实验(144 MHz)不同。这是 CubeMX2 的默认配置,不影响 GPIO 功能,HAL_Delay() 仍可正常工作。
3.3 GPIO 配置(PA5 输出)
- 在 Pinout 视图中找到 PA5 引脚。根据 UM3615 手册,向 PA5 写入高逻辑电平("1")即可点亮 LD1。
- 右键点击 PA5,选择 Assign signal → GPIO,把引脚的功能分配给 GPIO 模块。
- 再次右键点击 PA5,选择 Configure GPIO,进入 GPIO 详细配置界面。
- 将 PA5 的 Mode 设置为 Output。
- 保持默认参数:Output level 为 Low,Output mode 为 Push Pull,Pull-up/Pull-down 为 No pull-up and no pull-down,Maximum output speed 为 Low。
- 在 PA5 的配置项中找到 User Label(用户标签)输入框,填入 LD1。
设置别名后,CubeMX2 生成的代码中会自动创建对应的宏定义,例如 LD1_GPIO_Port 和 LD1_Pin,后续在 main.c 中可以直接使用这两个宏来操作 LED,无需再手动记忆 GPIOA 和 GPIO_PIN_5。


3.4 GPIO 配置(PC13 输入)
- 在 Pinout 视图中找到 PC13 引脚。
- 右键点击 PC13,选择 Assign signal → GPIO。
- 再次右键点击 PC13,选择 Configure GPIO,进入 GPIO 详细配置界面。
- 将 PC13 的 Mode 设置为 Input。
- 保持默认参数:Pull-up/Pull-down 为 No pull-up and no pull-down。
- 在 User Label 输入框中填入 B1。
本实验采用轮询方式,不启用外部中断,因此不需要勾选 EXTI 相关选项。

3.5 项目配置
- 点击 Project Settings,进入工程设置页面。
- 在 IDE Format 下拉选项中选择 CMake。
- 在 CMake Toolchain 下拉选项中选择 GCC。
- 确认配置无误后,点击 Generate Code。CubeMX2 会执行配置检查,如果没有错误,开始在指定路径下生成 CMake 工程文件。
- 生成完成后,项目路径下会出现标准 CMake 工程结构,包含
Core/、Drivers/、CMakeLists.txt等。

4. 编程实现
4.1 实现思路
采用 "检测 → 消抖 → 二次确认 → 翻转 → 等待松开" 的轮询方案:
主循环
│
└─ 读取 PC13 电平
│
├─ 非按下(低电平)→ 继续轮询
│
└─ 按下(高电平)
├─ HAL_Delay(20ms) 消抖
├─ 二次确认仍为按下?
│ └─ 否 → 视为抖动,忽略
├─ 是 → 有效按下 → 翻转 PA5 状态
└─ 阻塞等待松开(读到高电平)后才回到轮询
各步骤使用的 HAL 函数:
| 步骤 | HAL 函数 | 作用 |
|---|---|---|
| 读取按键 | HAL_GPIO_ReadPin(B1_PORT, B1_PIN) |
读取 PC13 电平 |
| 消抖延时 | HAL_Delay(DEBOUNCE_TIME_MS) |
延时 20 ms |
| 翻转 LED | HAL_GPIO_TogglePin(LD1_PORT, LD1_PIN) |
切换 PA5 输出电平 |
4.2 关键代码
在 VS Code 中打开生成的 CMake 工程,找到 Core/Src/main.c,添加以下代码。
(1)文件头部添加宏定义
c
/* Private define ------------------------------------------------------------*/
#define DEBOUNCE_TIME_MS 20u /* 按键消抖时间 */
#define B1_PRESSED_STATE HAL_GPIO_PIN_SET /* 按下时 B1(PC13) 为高电平 */
(2)声明按键扫描函数
c
/* Private functions prototype -----------------------------------------------*/
static void Button_Scan(void);
(3)主函数
c
int main(void)
{
if (mx_system_init() != SYSTEM_OK)
{
return (-1);
}
else
{
while (1)
{
Button_Scan();
}
}
}
(4)按键扫描函数
c
/**
* brief: Poll user button B1 (PC13) and toggle onboard LED LD1 (PA5) on each
* valid press. Debounces the press, and waits for the release so that
* holding the button down does not re-trigger.
* retval: none
*/
static void Button_Scan(void)
{
if (HAL_GPIO_ReadPin(B1_PORT, B1_PIN) == B1_PRESSED_STATE)
{
/* A press is detected, confirm it after the debounce time */
HAL_Delay(DEBOUNCE_TIME_MS);
if (HAL_GPIO_ReadPin(B1_PORT, B1_PIN) == B1_PRESSED_STATE)
{
/* Valid press: toggle the onboard LED */
HAL_GPIO_TogglePin(LD1_PORT, LD1_PIN);
/* Wait for the release before scanning again */
while (HAL_GPIO_ReadPin(B1_PORT, B1_PIN) == B1_PRESSED_STATE)
{
}
}
}
}
代码说明:
B1_PORT、B1_PIN、LD1_PORT、LD1_PIN四个宏由 CubeMX2 生成在generated/hal/mx_gpio_default.h,通过main.h链入,在main.c中可直接使用。- 第 1 步检测到高电平后,第 2 步延时 20 ms 消抖,第 3 步再次确认。两次都为低电平才判定为有效按下。
- 第 4 步翻转 LED 状态。
- 第 5 步的
while空循环阻塞等待按键松开,这是实现"按住不重复触发"的关键。松开后回到外层,可响应下一次按下。

5. 编译烧录与运行测试
5.1 编译与烧录
- 打开工程 :用 VS Code 打开 CubeMX2 生成的 CMake 工程文件夹(如
GPIO_Button_cmake)。 - 编译 :点击 VS Code 底部状态栏的 Build 按钮,或使用命令面板执行 CMake 构建。编译完成后,终端应输出
Build finished with exit code 0,无 error。

-
连接开发板 :用支持数据传输的 USB Type-C 线连接 NUCLEO-C542RC 的 ST-LINK USB 口(CN1)。
-
确认设备识别 :打开设备管理器,在"端口 (COM 和 LPT)"下应能看到 STLink COMx 。
-
烧录:点击 VS Code 中的 运行按钮,将固件下载到开发板。

5.2 运行与测试
烧录完成后,程序自动开始运行。依次验证以下功能:
-
初始状态
复位开发板(按下黑色复位按键 B2),观察 LD1。复位后 LD1 应保持熄灭状态,说明 GPIO 初始化正确。
-
按键响应
按下蓝色用户按键 B1,观察 LD1 是否翻转。如果当前 LED 熄灭,按下后应点亮;再次按下,LED 应熄灭。反复测试几次,确认每次按下都能可靠触发翻转。
-
按住不重复
按住 B1 不放,观察 LD1。LED 应该只翻转一次,持续按住期间不会再翻转。
-
松开可再响应
松开 B1 后再次按下,LD1 应能再次翻转,说明等待松开的逻辑正常。
-
消抖验证
快速连续按下 B1 多次,观察 LED 响应。如果消抖正常,每次按下只触发一次翻转,不会因按键机械抖动产生多次翻转。
测试结果:
- 按一下 B1,LD1 翻转一次
- 持续按住 B1,LD1 只翻转一次,不重复触发
- 松开后再次按下,LD1 再次翻转
- 快速连按无明显误触发,20 ms 消抖生效
功能正常。
6. 小结
本实验通过轮询方式实现了按键控制 LED 状态翻转,掌握了 STM32C5 GPIO 输入与输出的基本配置和使用方法。
核心逻辑可以概括为:"检测 → 消抖 → 二次确认 → 翻转 → 等待松开"。其中"等待松开"这一步是保证按住不重复触发、松开可再响应的关键,不可缺少。
需要注意的是,本方案采用阻塞式轮询:HAL_Delay(20) 消抖和等待松开的空循环都会占用主循环,期间无法执行其他任务。对于功能简单的应用这是可接受的;如果系统还有其他实时任务,建议改用外部中断方式或非阻塞状态机。下一篇将介绍用外部中断实现同样的按键控制功能。
版权声明:
欢迎关注 youcans@xidian【嵌入式软件AI编程】专栏
转发必须注明原文链接:
【STM32C5教程】(3)GPIO 按键输入实验 (https://youcans.blog.csdn.net/article/details/167586577)
Copyright by ai4mcu@qq.com 2026
Crated:2026-10