使用按键控制STM32 LED灯亮灭
之前我们已经实现了LED灯的亮灭,我们对LED灯的结构应该有一个大致的了解。接下来我们对按键控制led进行学习。
首先我们要了解一下按键的结构。按键结构如图。
由此可知,此处我们有两种按键,一种是普通的按键KEY0, KEY1(KEY2),他们连接的串口分别是PE4, PE3(PE2),对应的GPIO口为GPIOE;另一种是重置按键WAKE_UP_KEY,它连接的串口为PA0,对应的GPIO口为GPIOA。这两种按键的区别是阴极(非严格意义上的)的极性,普通按键KEY0的阴极接地,按键未按下的时候呈现高阻态,需要一个稳定的高电平,来维护未按下的状态,于是我们采用上拉输入,来获得一个稳定的高电平;相应的,WAKE_UP_KEY阴极接VCC,当未按下的时候呈现高阻态,需要一个稳定的低电平来维持稳定的未按下状态,于是我们选用下拉输入,来获得稳定的低电平。
总结而言,WAKE_UP_KEY采用下拉输入,KEY0/1/2采用上拉输入,对应的GPIO_IniyTypeDef结构体的成员为Pull。
之后我们再介绍一个针对按键非常重要的知识点——软件消抖:
我们知道,由于按键中的金属弹性,在按下松开的时候会有一定的不稳定干扰,信号会很乱,导致单片机对按键状态的误判,因此,我们需要了解软件消抖。
接下来直接给出一段按键扫描的程序,其中包含了软件消抖的应用:
uint8_t key_scan(void){
if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2) == 0){
delay_ms(10);
while(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2) == 0){
return 1;
}
}
delay_ms(10);
return 0;
}
以key2为例,软件消抖的原理就是在按键按下后,由触发的低电平给我们的HAL_GPIO_ReadPin()函数一个低电平信号,然后我们采取10ms的延时来消抖,再接受稳定的低电平信号,返回1值表示按键已经按下;松开时候也同理,我们的按键在按下之前一直是低电平,当我们的按键松开时候,按键输出高电平,while循环的条件被破坏,跳出循环和if语句,然后进行后一个延迟,然后在返回0表示没有按下。
这里的HAL_GPIO_ReadPin()函数有两个参数,第一个是对应的GPIO,第二个是对应的GPIO口,作用是读取实时的串口值。
那么接下来我们就进行相应程序文件的编写
key.h:
#ifndef __KEY_H
#define __KEY_H
#include "./SYSTEM/sys/sys.h"
void key_init(void);
uint8_t key_scan(void);
#endif
key.c:
#include "./BSP/KEY/key.h"
void key_init(void){
GPIO_InitTypeDef gpio_init_struct;
__HAL_RCC_GPIOE_CLK_ENALBE();
gpio_init_struct.Pin = GPIO_PIN_2;
gpio_init_struct.Mode = GPIO_MODE_INPUT;
gpio_init_struct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOE, &gpio_init_struct);
}
uint8_t key_scan(void){
if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2) == 0){
delay_ms(10);
while(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2) == 0){
return 1;
}
}
delay_ms(10);
return 0;
}
key_init()和之前的led_init()是类似的,对GPIOE串口进行初始化。
因为KEY2的pin脚为PE2所以设置为GPIO_PIN_2;这里由于是接受按键的输入,所以使用GPIO_MODE_INPUT;上面已经解释过了,使用上拉输入;输入模式不需要调整输出的速度,故不作设置。
对key_scan()函数就不做解释了,上面解释过了。注意这里的key_scan()的类型需要设置为uint8_t,它需要返回一个值来表示相应按键的按下。
之后我们再来编写主函数
main.c:
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.h"
int main(){
HAL_init();
sys_stm32_clock_init(RCC_PLL_MUL9);
delay_init(72);
key_init();
led_init();
while(1){
if(key_scan() ){
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5);
}
else{
delay_ms(10);
}
}
}
于是我们就能通过一个按键开启对led灯的控制了。