前言
本文是本人备赛物联网赛项的学习笔记,主要供本人学习、复习,不是经验分享或教学,若有错误,大佬轻喷。
一、按键基本知识
1. 按键的分类及核心差异
| 类型 | 代表实例 | 核心特点 | 适用场景 |
|---|---|---|---|
| 触点式开关按键 | 机械式开关、导电橡胶式开关 | 造价低,结构简单;但存在机械抖动 | 微机系统、单片机应用(最常用) |
| 无触点式开关按键 | 电气式按键、磁感应按键 | 寿命长,无机械抖动;成本较高 | 对稳定性和寿命要求高的场景 |
**为什么要分这两类?**本质是 "成本" 与 "性能" 的权衡:触点式满足大部分普通场景需求,性价比高,所以微机系统中最常见;无触点式解决了机械磨损和抖动问题,但造价高,只在特殊场景使用。
2. 单片机中按键的作用
- 复位按键:有专属复位电路,仅负责复位功能(硬件层面的专属作用);
- 其他功能按键:通过 "开关通断" 向 MCU(微控制器)传递控制指令或输入数据,比如切换模式、触发动作等;
- 核心逻辑:按键按下 / 释放 → MCU 识别状态 → 执行对应功能程序 → 返回主程序。
3. 机械按键的 "抖动问题"(关键难点)
- 什么是抖动?:机械按键按下或释放时,由于金属触点的弹性形变,不会立刻稳定通断,会在 5~10ms 内快速通断多次(即 "触点机械抖动");
- 为什么要重视?:如果直接检测抖动期间的通断状态,MCU 会误判为 "多次按下 / 释放",导致程序逻辑出错(比如按一次按键,设备却执行多次操作);
- 解决思路:通过 "消抖" 处理,等待抖动结束后再检测状态,确保识别的是真实按键动作。
二、硬件解读(连接逻辑 + 电平判断)
1. 开发板硬件配置(蓝桥杯物联网开发板)
- 核心按键:2 个可编程按键(ASW1、ASW2),分别连接 MCU 的 PA8 引脚 和 PB8 引脚;
- 电平判断逻辑:
- 未按下:PA8/PB8 为 高电平(GPIO_PIN_SET);
- 按下时:PA8/PB8 为 低电平(GPIO_PIN_RESET);
- 为什么是这样?:硬件设计中按键一端接 GND,另一端通过上拉电阻接 VDD,未按下时引脚被拉为高电平,按下后直接接地变为低电平。
2. GPIO 引脚与外设对应关系(核心连接桥梁)
| GPIO 引脚序号 | GPIO 引脚名称 | 外设 | GPIO 功能 | 备注 |
|---|---|---|---|---|
| - | PA8 | 按键 ASW1 | 输入 | 检测按键通断状态 |
| - | PB8 | 按键 ASW2 | 输入 | 检测按键通断状态 |
关键理解:GPIO 引脚是 MCU 与外部设备(如按键)通信的 "接口",按键作为输入设备,通过 GPIO 引脚向 MCU 传递 "通 / 断" 信号。
三、CubeMX 配置(知其所以然:为什么这么配)
配置要求:将 PA8 和 PB8 设为「输入模式」
- 配置原因:按键是 "输入设备",MCU 需要通过 GPIO 引脚 "读取" 按键的通断状态(高 / 低电平),因此引脚必须设为输入模式;
- 配置逻辑:输入模式下,GPIO 引脚仅接收外部信号(如按键的电平变化),不向外输出信号,符合按键的工作原理。

四、MDK 代码实战(逐行理解:代码为什么这么写)
1. 核心前提:消抖时间的确定
- 抖动时间:机械按键的抖动通常为 5~10ms;
- 消抖逻辑:预留 20ms 消抖时间(覆盖最大抖动周期),确保检测到的是按键稳定后的状态;
- 消抖流程:(此处预留图片位置:按键抖动与稳定期示意图,标注按下抖动 20ms、稳定期、释放抖动 20ms)

2. 按键读取函数(zsdz_read_ASW)
函数声明(.h 文件)

- 为什么要宏定义状态?:用直观的名称(APP_ON/OFF)替代数字,避免后续代码中混淆,提高可读性和可维护性;
- 为什么要在.h 文件声明函数?:C 语言中,函数需先声明后调用,.h 文件相当于 "函数说明书",让 main.c 等其他文件能识别该函数。
函数实现(.c 文件)

代码逐句解读(知其所以然)
HAL_GPIO_ReadPin(ASWx, GPIO_PIN_8):读取指定引脚(ASWx 的 PIN8)的电平,GPIO_PIN_RESET对应低电平(按键按下);- 第一次检测低电平:只是初步判断可能有按键操作,但不确定是抖动还是真实按下;
HAL_Delay(20):核心消抖步骤,等待 20ms 让机械触点稳定,过滤掉抖动带来的虚假信号;- 第二次检测低电平:确认是稳定的低电平,说明按键确实被按下(排除抖动);
while (HAL_GPIO_ReadPin(ASWx, GPIO_PIN_8) == GPIO_PIN_RESET):等待按键释放,直到引脚回到高电平,避免长按期间函数反复返回 "按下" 状态,导致程序误执行。
3. main 函数中调用(如何使用按键函数)

- 调用逻辑:在主循环中持续检测按键状态,一旦检测到 "按下"(APP_ON),就执行对应的外设控制函数(如
zsdz_write_AL控制 LED); - 为什么在 while (1) 中调用?:单片机程序是循环执行的,持续检测才能实时响应按键操作。