1. 按键信号是如何识别的?
一般来说,按键的两个引脚的一端通过电阻上拉到高电平,另一端则接地。
在没有按键按下的时候,输入引脚为高电平,当有按键按下,输入引脚则为低电平。通过反复读取按键输入引脚的信号,然后识别高低电平来判断是否有按键触发。
2. 为什么去抖动?
按键的输入引脚有低电平产生不代表一定是有按键按下,也许是干扰信号 , 因此,需要通过去抖动处理,将这些干扰信号过滤,从而获得真实的按键触发信号。
3. 如何去抖动
首次检测到按键输入引脚有低电平后,稍作延时,再次读取该引脚,如还是低电平,则确认为按键触发信号;否则,判断为干扰信号,不予处理。
GPIO_PinState HAL_GPIO_ReadPin( GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
参数1:GPIOx,端口号,如:GPIOB,GPIOF。
参数2:GPIO_Pin,引脚号,如:GPIO_PIN_9,GPIO_PIN_12。
返回值:GPIO_PinState,引脚的电平状态。
应用举例:判断PE3引脚的输入信号,若为低电平,则将PB5引脚控制的LED灯的开关状态切换。
if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_3) == GPIO_PIN_RESET)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5);
}
第一部分:根据开发板原理图,配置STM32CubeMX
1.开发板LED灯部分原理图如图所示:
由原理图不难看出,LED0的阴极与PB5引脚直接相连,LED1的阴极与PE5引脚直接相连,控制时,引脚为低电平,对应LED灯发光;引脚为高电平。对应LED灯熄灭。
2.开发板按键部分原理图如图所示:
从原理图中可以看出,两个用户自定义按键KEY0和KEY1中,分别与PE4和PE3引脚相连,此处画的不是很完整,完整的图应该如下图所示,是带上拉电阻的:
以KEY0为例,从带上拉电阻的按键示意图中可以看出,如果按键没有按下的话,上拉电阻左侧与地是不通的,那么PE4就会为高电平,如左下图所示;如果按键按下后,上拉电阻左侧与地直接连接,PE4和地等电位,为低电平。
关于上拉电阻,我的理解是这样的:电源到器件引脚上的电阻叫上拉电阻,作用是平时使该引脚为高电平,地到器件引脚上的电阻叫下拉电阻,作用是平时使该引脚为低电平。
也就是说,上下拉的目的都是给IO口设置一个默认的状态,上下拉电阻也不能够随意取消,这里以上拉电阻为例,起作用是给IO口默认高电平的状态。如果没有上拉电阻,电源直接接在IO口上,按键没有按下的时候,是高电平没有问题,如果按键按下了,就会造成电源和地直接相连的情况。
至于为什么按键没有按下的时候,IO口默认为高电平,在这里我是这么理解的:IO口的高低电平,是相对于地来说的,我们看电源到地的回路,如果按键没有按下,相当于IO口和地之间的阻抗很大,这样的话按键没有按下PE4口是为高电平的,如果阻抗接近无穷的话,PE4对地电压是为5V。
3.配置STM32CubeMX
过程和之前大致相同,详见1.STM32的GPIO开发基础中的相同部分。
需要注意的是,在这里和按键相连的引脚,需要使用Input模式和上拉电阻状态。
第二部分:Keil5中代码的编写
按键扫描的过程中,需要进行去抖动操作,也就是当按键按下后,过一段时间再去判定,按键是不是真的按下了。在这里需要延时函数,如果不是特别精确的延时,用while循环即可:
void Delay(unsigned int t) //延时函数
{
while(t--);
}
扫描按键的时候,大体流程,就是判断与按键相连的IO口是否为指定电平:如果IO口为低电平,即为按键按下
void Scan_Keys()
{
if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//检测按键对应IO口是否为低电平,即按键是否按下
{
Delay(1000);//延时函数,去抖动操作
if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//检测按键是否真的按下了
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5);
while(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET);//如果按键对应IO口,为低电平,即按键按下一直未抬起,则一直执行循环,等按键抬起后,跳出循环
}
这样写代码会比较麻烦,每一个按键都需要写对应引脚,很麻烦,为了避免这种情况,可以在代码前面进行宏定义,也可以在配置STM32CubeMx的时候直接添加User Label标签来解决问题:
/* USER CODE BEGIN PD */
#define KEY1 HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)
#define KEY0 HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)
/* USER CODE END PD */
低电平也可以直接用0来简化,这个是在gpio的文件中有说明的,可以直接使用,简化后的扫描按键代码如图所示:
/* USER CODE BEGIN 0 */
void Delay(unsigned int t) //延时函数
{
while(t--);
}
void Scan_Keys()
{
if(KEY1==0)
{
Delay(1000);
if(KEY1==0) //与if(KEY1==0)等价
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5);
while(KEY1==0);
}
}
if(KEY0==0)
{
Delay(1000);
if(KEY0==0) //与if(KEY0==0)等价
{
while(KEY0==0);//按下按键时,KEY0为低电平,一直执行while(1)循环,松开后再执行后续操作
HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_5);
while(KEY0==0);
}
}
}
/* USER CODE END 0 */
main函数直接调用扫描按键函数即可:
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
Scan_Keys();
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
在这里也可以体会到,按下按键切换状态,与按下按键,松开之后再切换状态的区别,KEY1是按下即翻转电平,前面详细描述过;KEY0则是在判断按键真正按下去之后,再判断一下按键是否抬起,抬起后再执行后续操作。
写完代码后,在Keil5里编译好后,就可以下载到单片机中。
配套源码:利用STM32F103ZET6开发板基于HAL库的STM32学习笔记二:按键开发基础例程
参考内容:
以上内容为本人学习b站小蜜蜂老师的基于STM32CubeMX的嵌入式开发基础教程所做的笔记,其中有一些为个人的理解与感悟,如有疏漏之处,敬请大佬指正。
版权声明:本文为CSDN博主「砍省小苏苏」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_46301543/article/details/122453600
1. 按键信号是如何识别的?
一般来说,按键的两个引脚的一端通过电阻上拉到高电平,另一端则接地。
在没有按键按下的时候,输入引脚为高电平,当有按键按下,输入引脚则为低电平。通过反复读取按键输入引脚的信号,然后识别高低电平来判断是否有按键触发。
2. 为什么去抖动?
按键的输入引脚有低电平产生不代表一定是有按键按下,也许是干扰信号 , 因此,需要通过去抖动处理,将这些干扰信号过滤,从而获得真实的按键触发信号。
3. 如何去抖动
首次检测到按键输入引脚有低电平后,稍作延时,再次读取该引脚,如还是低电平,则确认为按键触发信号;否则,判断为干扰信号,不予处理。
GPIO_PinState HAL_GPIO_ReadPin( GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
参数1:GPIOx,端口号,如:GPIOB,GPIOF。
参数2:GPIO_Pin,引脚号,如:GPIO_PIN_9,GPIO_PIN_12。
返回值:GPIO_PinState,引脚的电平状态。
应用举例:判断PE3引脚的输入信号,若为低电平,则将PB5引脚控制的LED灯的开关状态切换。
if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_3) == GPIO_PIN_RESET)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5);
}
第一部分:根据开发板原理图,配置STM32CubeMX
1.开发板LED灯部分原理图如图所示:
由原理图不难看出,LED0的阴极与PB5引脚直接相连,LED1的阴极与PE5引脚直接相连,控制时,引脚为低电平,对应LED灯发光;引脚为高电平。对应LED灯熄灭。
2.开发板按键部分原理图如图所示:
从原理图中可以看出,两个用户自定义按键KEY0和KEY1中,分别与PE4和PE3引脚相连,此处画的不是很完整,完整的图应该如下图所示,是带上拉电阻的:
以KEY0为例,从带上拉电阻的按键示意图中可以看出,如果按键没有按下的话,上拉电阻左侧与地是不通的,那么PE4就会为高电平,如左下图所示;如果按键按下后,上拉电阻左侧与地直接连接,PE4和地等电位,为低电平。
关于上拉电阻,我的理解是这样的:电源到器件引脚上的电阻叫上拉电阻,作用是平时使该引脚为高电平,地到器件引脚上的电阻叫下拉电阻,作用是平时使该引脚为低电平。
也就是说,上下拉的目的都是给IO口设置一个默认的状态,上下拉电阻也不能够随意取消,这里以上拉电阻为例,起作用是给IO口默认高电平的状态。如果没有上拉电阻,电源直接接在IO口上,按键没有按下的时候,是高电平没有问题,如果按键按下了,就会造成电源和地直接相连的情况。
至于为什么按键没有按下的时候,IO口默认为高电平,在这里我是这么理解的:IO口的高低电平,是相对于地来说的,我们看电源到地的回路,如果按键没有按下,相当于IO口和地之间的阻抗很大,这样的话按键没有按下PE4口是为高电平的,如果阻抗接近无穷的话,PE4对地电压是为5V。
3.配置STM32CubeMX
过程和之前大致相同,详见1.STM32的GPIO开发基础中的相同部分。
需要注意的是,在这里和按键相连的引脚,需要使用Input模式和上拉电阻状态。
第二部分:Keil5中代码的编写
按键扫描的过程中,需要进行去抖动操作,也就是当按键按下后,过一段时间再去判定,按键是不是真的按下了。在这里需要延时函数,如果不是特别精确的延时,用while循环即可:
void Delay(unsigned int t) //延时函数
{
while(t--);
}
扫描按键的时候,大体流程,就是判断与按键相连的IO口是否为指定电平:如果IO口为低电平,即为按键按下
void Scan_Keys()
{
if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//检测按键对应IO口是否为低电平,即按键是否按下
{
Delay(1000);//延时函数,去抖动操作
if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//检测按键是否真的按下了
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5);
while(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET);//如果按键对应IO口,为低电平,即按键按下一直未抬起,则一直执行循环,等按键抬起后,跳出循环
}
这样写代码会比较麻烦,每一个按键都需要写对应引脚,很麻烦,为了避免这种情况,可以在代码前面进行宏定义,也可以在配置STM32CubeMx的时候直接添加User Label标签来解决问题:
/* USER CODE BEGIN PD */
#define KEY1 HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)
#define KEY0 HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)
/* USER CODE END PD */
低电平也可以直接用0来简化,这个是在gpio的文件中有说明的,可以直接使用,简化后的扫描按键代码如图所示:
/* USER CODE BEGIN 0 */
void Delay(unsigned int t) //延时函数
{
while(t--);
}
void Scan_Keys()
{
if(KEY1==0)
{
Delay(1000);
if(KEY1==0) //与if(KEY1==0)等价
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5);
while(KEY1==0);
}
}
if(KEY0==0)
{
Delay(1000);
if(KEY0==0) //与if(KEY0==0)等价
{
while(KEY0==0);//按下按键时,KEY0为低电平,一直执行while(1)循环,松开后再执行后续操作
HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_5);
while(KEY0==0);
}
}
}
/* USER CODE END 0 */
main函数直接调用扫描按键函数即可:
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
Scan_Keys();
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
在这里也可以体会到,按下按键切换状态,与按下按键,松开之后再切换状态的区别,KEY1是按下即翻转电平,前面详细描述过;KEY0则是在判断按键真正按下去之后,再判断一下按键是否抬起,抬起后再执行后续操作。
写完代码后,在Keil5里编译好后,就可以下载到单片机中。
配套源码:利用STM32F103ZET6开发板基于HAL库的STM32学习笔记二:按键开发基础例程
参考内容:
以上内容为本人学习b站小蜜蜂老师的基于STM32CubeMX的嵌入式开发基础教程所做的笔记,其中有一些为个人的理解与感悟,如有疏漏之处,敬请大佬指正。
版权声明:本文为CSDN博主「砍省小苏苏」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_46301543/article/details/122453600
暂无评论