往期内容
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,不接外部器件时可以读出高电平
3.下拉输入(GPIO_Mode_IPD)
Pull-down
I/O口默认通过电阻下拉到GND,不接外部器件时可以读出低电平
图1-2 下拉输入
4.上拉和下拉的区分
用一句话概括:
按键外接GND为上拉,外接VCC为下拉。
原因
上拉输入就像是给IO口里面接了一个小小的电阻,这个电阻的另一头连着电源正极(VCC)。这样一来,如果外面没接啥东西或者接了个接地的按键没按,IO口就会“知道”是高电平,就像是灯一直是亮着的状态。
这种设置适合那些接地的按键,因为一按按键,IO口就能“知道”电平变化,知道按键被按了。
-------------------------------------------------------------------------------------------------------------------
下拉输入也是给IO口里面接了个电阻,但这回电阻的另一头连着的是地(GND)。这样,如果外面啥也没接或者接了个接电源正极的按键没按,IO口就会“感觉”到是低电平,就像是灯一直是关着的状态。当你按下那个接电源正极的按键时,IO口就能察觉到电平的变化,知道有动作发生了。
下拉输入适合那些接电源正极的按键。
二、配置
在选择好芯片并进入配置界面后的操作如下进行
1.RCC
外部的高速和低速时钟均有三个可选项目,具体情况需根据个人的硬件情况进行个性化配置,一般选择高速时钟下的:Crystal/Ceramic Resonator(外部晶体/陶瓷谐振器)如图2-1所示:
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),并合理配置其参数,可以实现高效、可靠的时间管理功能。
3.时钟树
依此点击:PLL、Enable CSS、HCLK(MHz)改为72之后回车即可。
4.KEY引脚配置
(1).选择引脚和模式
本文是基于上一篇文章的LED后进行的操作,有不了解的同学可以移步STM32F1基于HAL库的学习记录实用使用教程分享(一、GPIO_Output)进行配置。
根据硬件点击所需要使用的引脚,之后在弹窗里选择GPIO_Input,如图2-4 :
(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).代码生成
以下配置勾选后点击界面右上角的: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’文件
三、程序
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。由于精力的原因,没做成动画,仅是简单进行截图演示。
对于RS触发器的原理,简单概括为即使有抖动但是在经过双稳态电路之后,便可输出“漂亮”的矩形波
其对比效果如下图,黄色为RS触发器,蓝色为普通的按键:
3.其他方法
由于在程序代码中,添加过多延时会浪费CPU资源,造成影响其他功能的使用并产生实时数据滞后性的可能。在后期我将介绍利用中断和ADC的方式进行按键的判断。而在实际应用中,这些方法往往更常用更好用。
四、演示效果
<iframe allowfullscreen="true" data-mediaembed="csdn" frameborder="0" id="ola0Ye4J-1722476838321" src="https://live.csdn.net/v/embed/414219"></iframe>按键
总结
本篇内容略少,但这也是为后期的内容做铺垫衔接。后面的关键按键的内容“干货”会更多一些,敬请期待。
又是经过一个充实而忙碌的夜晚,深知文章中仍不免有诸多省略和未及细讲之处。对于那些在阅读过程中仍感意犹未尽、存有疑问的同学,建议大家不妨拓宽视野,多阅读几篇来自不同作者、风格各异的优秀文章。相信通过多角度、多层次的学习,你们定能集百家之长从而对单片机有更加深入和全面的理解。
在此,我的初衷不仅是为初学者提供一份学习路上的指引,也是对自己学习历程的一次回顾与总结。通过分享,我希望能激发更多人对单片机技术的兴趣,共同探索这片充满挑战与机遇的领域。
为了保持内容的连贯性和避免不必要的重复,我计划在未来的博客中,对于本文中已提及但未深入展开的话题,将通过链接的方式引导大家回到本文进行查阅。同时,我也将不断优化和完善文章内容,力求为大家提供更加准确、全面、易于理解的学习资源。
下期预告——关于外部中断和对于双击和长按方法的检测的学习分享。
感谢大家的关注与支持!