土木本科生的 STM32 探索之旅:按键控 LED 的 “亮灭 + 翻转” 实战
摘要:本文介绍了STM32开发中从基础LED控制升级到按键交互控制的实践过程。通过STM32F103VET6开发板,实现了按键A控制LED0亮灭(按下亮/松开灭)和按键B控制LED1状态翻转的功能。文章详细讲解了硬件原理图分析、GPIO模式设置(上拉输入)、软件消抖处理等关键步骤,并分享了调试过程中遇到的典型问题及解决方法。作者作为土木专业学生,通过实践加深了对GPIO输入输出逻辑、硬件软件协同工
一、从 “单纯亮灯” 到 “交互控制”
作为系列文章里的“土木跨界STM32选手”,上一篇刚搞定了“点亮板载LED小灯或者是使小灯闪烁”的基础实验——当时不过是让STM32的IO口输出高低电平,像给LED下了个“固定指令”,亮或灭都由代码写死,算是和STM32的“输出功能”打了个照面。
但实际项目里哪有这么“单向”的控制?比如后续想做土木监测里的“传感器触发报警灯”,就得让硬件“接收输入信号→做出对应反应”。而这次的实验,就是把“按键(输入)”和“LED(输出)”连起来,从“单纯亮灯”升级到“交互控制”:
不是我写死LED的状态,而是按键按下去,LED才听指令——按下按键a,LED0跟着亮;松开按键a,LED0跟着灭;按一下按键b,LED1还能自己“切换状态”。
对我这个土木生来说,这步是从“会让硬件‘动起来’”,到“能让硬件‘听指令动’”的小突破,也是后续做更复杂的“输入-输出联动”(比如传感器触发设备)的基础。
二、实战准备:硬件 + 软件
软硬件都是延用之前几次实验的东西,
硬件:STM32F103VET6 开发板、st-link、杜邦线若干
软件:STM32 Cube IDE
其他准备:原理图

已经连接好st-link的白羊座板子

STM32 Cube IDE
原理图网址如下:
三、原理:按键与 LED 的 “控制逻辑”
实验目标:
1、按下按键a,led0亮起,而松开按键a,led0熄灭;
2、按一下按键b,led1的亮灭状态实现翻转(由亮转灭或者由灭转亮)

图片取自高博士的ppt
白羊座-STM32F103VET6 开发板的相关ppt链接如下:
1 课件pptx · gaoyanzeng/drg_st_2_f103vet6 - 码云 - 开源中国

下面我将会从我个人学习以后的角度来讲一讲原理,如果大家没有听明白的地方,也可以去看专业人员录制的相关视频,视频链接如下:
高博士-白羊座-STM32F103VET6:[04-03]实验1_按键控制LED亮灭_哔哩哔哩_bilibili
keysking(对应白色板子,白羊座-STM32F103C8T6芯片和部分代码略有不同,但是原理是相同的):【STM32入门教程-2025】第4集 按键控制小灯 GPIO输入 | keysking的stm32教程_哔哩哔哩_bilibili
下面我将对按键的原理图进行简单的讲解。
从我提供的网站中,打开STM32F103VET6的原理图,找到按键A和按键B的原理图。

图里有 2 个独立的按键电路,分别对应 “按键 A” 和 “按键 B”。 “按键 A” 和 “按键 B”原理是相同的,所以就以按键A为例。
按键 A(对应 K1 按键),连接的STM32F103VET6引脚是pa0,通过 K1 按键接GND,也就是低电平。工作逻辑,简单地来说就是,如果pa0是高电平3.3v,当按键按下时,引脚通过按键直接连到GND,就导通了,1234全部是低电平0;若是按键没有按下,1和2那里还是高电平,只有3和4是低电平0。
那要怎么实现:按下按键a,led0亮起,而松开按键a,led0熄灭?
大白话:
按键A按下,即k1位置处的拨片连通了,pa0连通到了地,一条线导通了,对应的led0小灯亮起,也就是pb0变为低电平。(pa0由高电平变为低电平,pb0也为低电平,此时的led0小灯亮起。本括号里面的解释是为了等会软件上面做判定使用)
按键A松开,即k1位置处的拨片断开了,pa0连通到了地,一条线导通了,对应的led0小灯亮起,也就是pb0变为低电平。(pa0由低电平变为高电平,pb0也为高电平,此时的led0小灯熄灭。本括号里面的解释是为了等会软件上面做判定使用)

那怎么实现按一下按键b,led1的亮灭状态实现翻转(由亮转灭或者由灭转亮)?
这里的原理会和上一个原理类似,在软件的操作中,用时翻转高电平的函数即可以是原来的高电平输出低电平,原来是低电平的地方输出高电平。

(哈哈,可能原理这里,我自己讲的也许会有一些错误,会导致大家听了以后还会有点懵。看看网课或者咨询一下AI也行,不好意思啦,我个人的专业性可能还不够)
从学习中,遇到了更难的专业性内容,暂时会听不明白,就比如在高博士的讲解视频中,涉及到了寄存器的东西,很多原理性知识听不明白可以先放一放,先跟着做,学会用,会用了以后再回过头来看一看理论的讲解,兴许就能明白了一些东西。
四、软件上的实战(可以使用AI指导实验)
1、按键无消抖的情况
打开cubeide软件,新建项目。

使用已经收藏过的,点击星星⭐找到目前使用的芯片,或者在框框中搜索STM32F103VET6 ,项目名称:Key_Control_LED


为了避免f103芯片被锁,设置debug模式。

两个led小灯的gpio设置,我这里是选择led0(pb0)、led1(pb1)。

将我们的实验目标,选择的引脚和原理图发送给AI,它给出了参数的设置建议。



(由于是参考了AI给定的指导,我这里失败了一次,按键b按下,并未成功实现小灯的翻转,原因是设置错了gpio mode,都应该修改为pull-up,上拉输入。可见有时候对原理的理解不够准确,AI会带偏我们。)

在图形化配置中,重新修改gpio的模式,如下图所示。

根据AI的指导过程,我们设好gpio后,保存并生成代码。

在while循环中,增加我们自己的代码,(可以使用AI辅助代码的编写,修改存在的问题,代码解析)。
/* USER CODE BEGIN WHILE */
while (1)
{
// ---------- 按键a(PA0)控制LED0(PB0):按下亮、松开灭 ----------
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET)
// 检测按键a是否按下:PA0配置为上拉输入,如果读到按键a被按下,也就是PA0被拉为低电平
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
// 点亮LED0:就给PB0引脚写入低电平(原理图可知,pb0低电平点亮)
}
else // 否则,按键a松开
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
// 熄灭LED0:给PB0引脚写入高电平(原理图可知,pb0高电平熄灭)
}
// ---------- 按键b(PC13)控制LED1(PB1):按下翻转(无消抖) ----------
if(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_RESET)
// 检测按键b是否按下:PC13上拉输入,按下b,pc13=低电平(GPIO_PIN_RESET)
{
while(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_RESET){} // 一直等待着,直到按键松开
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1); // 翻转pb1的高低电平来实现LED1的亮灭状态变化
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */

编译下载,观察实验的效果。




烧录好了以后,我们会发现,按键a这里按下led0亮起,松开熄灭没有问题。但是按键b按下,小灯亮起,有时候按下两次小灯才熄灭,又或者是按下以后,闪了一下迅速熄灭等情况出现。这里就是涉及到了物理按键消抖的问题了,可以在软件上面使用代码来延时消抖。
2、软件消抖的情况
消抖的原理,可以在哔哩哔哩上面观看高博士或者是keysking的视频。
[04-04]实验2_按键的软件消抖_哔哩哔哩_bilibili
由于我不是这个专业的学生,可能在原理的理解上会有些吃力或者滞后,我就不讲原理了,暂时就不耽误大家的时间了,我这里直接提供相关的代码吧。

只需要在while循环中,加入按键b的消抖代码,可以用延迟的方式消抖。详细的代码如下:
重新编译并下载,观察实验的效果
// ---------- 按键b(PC13)控制LED1(PB1):按下翻转(无消抖) ----------
if(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_RESET)
// 检测按键b是否按下:PC13上拉输入,按下b,pc13=低电平(GPIO_PIN_RESET)
{
HAL_Delay(10); // 软件消抖:延时10毫秒(或者20毫秒也可以)过滤按键机械抖动
// 二次确认按键是否真的按下,避免抖动误触发
if(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_RESET)
{
while(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_RESET){} // 一直等待着,直到按键松开
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1); // 翻转pb1的高低电平来实现LED1的亮灭状态变化
}
}

相比之下,加入延时以后,实验的效果好了很多。
五、总结与思考
1、致谢keysking、高博士_嵌入式的助力
2、作为一个土木背景的嵌入式新手,这次实验算是把 “GPIO 输入输出” 的逻辑从 “纸面概念” 落地到了实际,至少实验是成功了:
有些明白了上拉 / 下拉输入的电平逻辑:之前总搞反 “按下 = 高 / 低电平”,直到实际调代码才明白 —— 上拉输入的按键,按下是低电平(GPIO_PIN_RESET),必须和代码判断条件对应;摸清了 “硬件和软件的绑定关系”:LED 点亮逻辑得看原理图(PB0/PB1 是低电平点亮),不能盲目写代码里的高低电平;
理解了软件消抖的本质:一开始没加消抖时,按键按一次 LED 翻好几次,加了 10ms 延时 + 二次确认后才稳定,这才懂 “机械按键的物理抖动会影响软件逻辑”。这次实验踩的坑,其实是嵌入式 “硬件 + 软件” 联动的典型问题
3、由于近期临近期末考试,本期文章相关的视频,将会哔哩哔哩视频逐步更新,敬请期待。
更多推荐


所有评论(0)