STM32F1基于HAL库的学习记录实用使用教程分享(二、GPIO_Input 按键)

往期内容

STM32F1基于HAL库的学习记录实用使用教程分享(一、GPIO_Output)


前言

本文记录了通过使用STM32F103ZET6单片机进行GPIO_Input的学习

随着嵌入式行业的兴起,于此记录个人的一些学习过程并进行分享,按键的控制即为大部分同学的第二课——按键(GPIO_Input)


声明:本文章在编写过程中,我始终致力于尊重并保护所有原创内容及其知识产权。然而,由于信息来源的多样性和复杂性,可能存在个别内容未明确标注出处、存在事实性错误或无意中侵犯了他人的知识产权的情况。对于任何可能存在的上述问题,我深感歉意,并在此提前向受影响的作者表示最诚挚的歉意。我始终秉持着尊重原创、维护知识产权的原则,绝无意侵犯任何人的合法权益。一旦收到您的反馈,我将立即核实并在第一时间内对文章进行修改。这包括但不限于补充相关引用信息、更正错误内容或删除涉嫌侵权的内容。再次感谢您的关注与支持,期待与您共同营造一个更加美好的知识共享空间。新手文章诸多不足,还望海涵。

一、GPIO_Input

GPIO支持4种输入模式,分别为:浮空输入、上拉输入、下拉输入、模拟输入。模拟输入的部分我们留在后面的ADC部分再详谈。

1.浮空输入(GPIO_Mode_IN_FLOATING)

No pull-up and no pull-down

IO口引脚电平是真实的外部连接器件电压,电平有不确定性。

2.上拉输入(GPIO_Mode_IPU)

Pull-up

I/O口默认通过电阻上拉到VCC,不接外部器件时可以读出高电平
图1-1 上拉输入

3.下拉输入(GPIO_Mode_IPD)

Pull-down

I/O口默认通过电阻下拉到GND,不接外部器件时可以读出低电平
图1-2 下拉输入
图1-2 下拉输入

4.上拉和下拉的区分

用一句话概括:
按键外接GND为上拉,外接VCC为下拉。

原因

上拉输入就像是给IO口里面接了一个小小的电阻,这个电阻的另一头连着电源正极(VCC)。这样一来,如果外面没接啥东西或者接了个接地的按键没按,IO口就会“知道”是高电平,就像是灯一直是亮着的状态。

这种设置适合那些接地的按键,因为一按按键,IO口就能“知道”电平变化,知道按键被按了。

-------------------------------------------------------------------------------------------------------------------

下拉输入也是给IO口里面接了个电阻,但这回电阻的另一头连着的是地(GND)。这样,如果外面啥也没接或者接了个接电源正极的按键没按,IO口就会“感觉”到是低电平,就像是灯一直是关着的状态。当你按下那个接电源正极的按键时,IO口就能察觉到电平的变化,知道有动作发生了。

下拉输入适合那些接电源正极的按键。

二、配置

在选择好芯片并进入配置界面后的操作如下进行

1.RCC

外部的高速和低速时钟均有三个可选项目,具体情况需根据个人的硬件情况进行个性化配置,一般选择高速时钟下的:Crystal/Ceramic Resonator(外部晶体/陶瓷谐振器)如图2-1所示:
图2-1 RCC

2.SYS

(1).Debug

在STM32CubeMX中配置系统(SYS)时,关于调试接口的设置是一个重要环节。默认情况下,调试功能可能被启用,但如果不需要实时调试或希望优化资源使用,可以选择关闭调试(即选择“No Debug”选项)。然而为了开发便利,我们一般都保留调试接口。

在调试协议的选择上,STM32CubeMX提供了SW(Serial Wire)和JTAG两种选项。鉴于SWD(Serial Wire Debug)模式仅需要两个引脚,且兼容性好、调试效率高,因此它是许多开发者的首选。我选择使用SW协议

(2).System Wake-Up

System Wake-Up功能允许STM32微控制器在低功耗模式下被特定的外部事件唤醒。这些外部事件可以包括但不限于外部中断、RTC闹钟、USART接收数据等。

通过配置System Wake-Up功能,微控制器可以在不需要时进入低功耗模式以节省电能,同时在需要时能够快速响应外部事件并恢复正常工作。

(3).Timebase Source

通过对 Timebase Source进行合理配置以确保程序的正确运行。通过选择合适的Timebase Source(如SysTick或TIMx),并合理配置其参数,可以实现高效、可靠的时间管理功能。
图2-2 SYS

3.时钟树

依此点击:PLL、Enable CSS、HCLK(MHz)改为72之后回车即可。
图2-3 时钟树

4.KEY引脚配置

(1).选择引脚和模式

本文是基于上一篇文章的LED后进行的操作,有不了解的同学可以移步STM32F1基于HAL库的学习记录实用使用教程分享(一、GPIO_Output)进行配置。
根据硬件点击所需要使用的引脚,之后在弹窗里选择GPIO_Input,如图2-4 :
图2-4 GPIO_Input

(2).进行细节配置

根据硬件进行细节配置,如图2-5 :

(A).GPIO Pull-up/Pull-down

通过电路的硬件结构进行上拉或下拉配置

(B).User Laber

用户标号,给引脚定义一个易识别的名称,以此以提高代码的可读性和可维护性。我直接定义为:KEY_IN(在此我仅以PE6举例,其他引脚(按键)同理)。
在这里插入图片描述

6.工程项目生成

(1).项目及编译器

(A).Project Name

给工程起个名字

(B).Project Location

给工程选个存放位置,避免中文路径

©.Toolchain/lDE

IDE选择,我在这里选择的是MDK-ARM(即Keil 5)
图2-8 项目命名及选择编译器

(2).代码生成

以下配置勾选后点击界面右上角的:GENERATE CODE

(A).Copy all used libraries into the project folder

将所有使用过的库复制到项目文件夹中

(B).Generate peripheral initialization as a pair of’c/.h’ files per peripheral

每个外设生成独立的’.c/.h’文件
图2-9 代码生成

三、程序

sys.h、led.h、stm32f1xx_it.c和stm32f10x_it.h在我的第一篇博客STM32F1基于HAL库的学习记录实用使用教程分享(一、GPIO_Output)里。

1.HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

此函数用于读取引脚状态,通过GPIO的IDR寄存器读取。
电平输出HAL函数
GPIOX代表目标引脚的端口号,例如GPIOE。
GPIO_Pin代表目标引脚的引脚号,例如GPIO_Pin_6。
由于我在User Laber中已将PE6定义标签“KEY_IN”故在main.h中可找到宏定义:

/* Private defines -----------------------------------------------------------*/
#define KEY_IN_Pin GPIO_PIN_6
#define KEY_IN_GPIO_Port GPIOE

故按键的检测程序为

  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  //有按键(PE6)按下
	  if(HAL_GPIO_ReadPin(KEY_IN_GPIO_Port,KEY_IN_Pin) == GPIO_PIN_RESET)
	  {
		  /* 软件消抖 */
		  HAL_Delay(20);	  
		  /* 等待按键1松开 */
		  while(HAL_GPIO_ReadPin(KEY_IN_GPIO_Port,KEY_IN_Pin) != GPIO_PIN_SET);//当按键松开后才执行后续程序,否则将不断在while里循环	
		  HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);/* 翻转LED*/
	  }
  }
  /* USER CODE END 3 */

以此实现按键控制小灯状态的功能。

2.按键消抖

方法一:软件消抖

一般来讲,大部分的消抖方案是使用10~20ms的延时程序进行消抖,这是由于在使用机械按键的时候会产生不稳定的前沿抖动,若不消去抖动的话,在CPU的高速运行状态下极易出现判断失误,当抖动消失后再一次检测键的状态,如果仍保持新电平状态,则确认为真正有键按下。如下代码为普遍的写法逻辑。

 //有按键(PE6)按下
  if(HAL_GPIO_ReadPin(KEY_IN_GPIO_Port,KEY_IN_Pin) == GPIO_PIN_RESET)
  {
	  /* 软件消抖 */
	  HAL_Delay(20);	  
	  /* 等待按键1松开 */
	  if(HAL_GPIO_ReadPin(KEY_IN_GPIO_Port,KEY_IN_Pin) == GPIO_PIN_RESET)
	  {
	  HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);/* 翻转LED*/
	  while(HAL_GPIO_ReadPin(KEY_IN_GPIO_Port,KEY_IN_Pin) != GPIO_PIN_SET);//当按键松开后才执行后续程序,否则将不断在while里循环
	  }  	
  }
  /* USER CODE END 3 */

方法二:硬件消抖

在学习的过程中,我了解到在按键数量不大的情况下可以使用RS触发器进行消抖操作。为了深入理解,我选择用Proteus进行仿真观察一下,如图3-1。由于精力的原因,没做成动画,仅是简单进行截图演示。
图3-1 RS触发器与普通的按键电路
对于RS触发器的原理,简单概括为即使有抖动但是在经过双稳态电路之后,便可输出“漂亮”的矩形波
其对比效果如下图,黄色为RS触发器,蓝色为普通的按键:
图3-2 RS触发器
请添加图片描述

3.其他方法

由于在程序代码中,添加过多延时会浪费CPU资源,造成影响其他功能的使用并产生实时数据滞后性的可能。在后期我将介绍利用中断和ADC的方式进行按键的判断。而在实际应用中,这些方法往往更常用更好用。

四、演示效果

按键

总结

本篇内容略少,但这也是为后期的内容做铺垫衔接。后面的关键按键的内容“干货”会更多一些,敬请期待。

又是经过一个充实而忙碌的夜晚,深知文章中仍不免有诸多省略和未及细讲之处。对于那些在阅读过程中仍感意犹未尽、存有疑问的同学,建议大家不妨拓宽视野,多阅读几篇来自不同作者、风格各异的优秀文章。相信通过多角度、多层次的学习,你们定能集百家之长从而对单片机有更加深入和全面的理解。

在此,我的初衷不仅是为初学者提供一份学习路上的指引,也是对自己学习历程的一次回顾与总结。通过分享,我希望能激发更多人对单片机技术的兴趣,共同探索这片充满挑战与机遇的领域。

为了保持内容的连贯性和避免不必要的重复,我计划在未来的博客中,对于本文中已提及但未深入展开的话题,将通过链接的方式引导大家回到本文进行查阅。同时,我也将不断优化和完善文章内容,力求为大家提供更加准确、全面、易于理解的学习资源。

下期预告——关于外部中断和对于双击和长按方法的检测的学习分享。

感谢大家的关注与支持!


参考文献引用

【野火】按键消抖模块的设计与验证

  • 18
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

藤樂.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值