基于STM32的嵌入式软件开发(6)——GPIO按键输入
一、引言
上篇文章中,介绍了GPIO的输出模式,使用推挽输出,点亮LED灯,并让蜂鸣器发声。本文介绍GPIO作为输入的情况。
二、基于标准固件库配置GPIO输入
1. 看原理图
本次实验使用到按键,我的开发板一共有4个按键:
KEY0 -- PE4; KEY1 -- PE3; KEY2 -- PE2; WK_UP -- PA0;


每个按键的具体连接方式如下:

KEY_UP外接高,所以PA0应配置为下拉,按键没按下时为常低,按键按下,电平由低变高;
KEY0/KEY1/KEY2外界地,所以PE4/PE3/PE2应配置为上拉,按键没按下时为常高,按键按下,电平由高变低
2. 添加工程文件
与GPIO输出相比,FWLIB文件夹中并无变化

Hardware文件夹中添加Key.c文件

同时,添加头文件引用路径

3. 编写代码
LED的相关配置代码参考前一篇文章,本文代码实现的内容为:通过按键控制LED灯的亮灭
Key.c文件中代码如下:
#include "Key.h"
static GPIO_InitTypeDef KEY_UP_init_str =
{
GPIO_Pin_0,
GPIO_Mode_IN,
GPIO_Fast_Speed,
GPIO_OType_PP,
GPIO_PuPd_DOWN,
};
static GPIO_InitTypeDef KEY_012_init_str =
{
GPIO_Pin_4 | GPIO_Pin_3 | GPIO_Pin_2,
GPIO_Mode_IN,
GPIO_Fast_Speed,
GPIO_OType_PP,
GPIO_PuPd_UP,
};
void KEY_init(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOE,ENABLE);
GPIO_Init(GPIOA,&KEY_UP_init_str);
GPIO_Init(GPIOE,&KEY_012_init_str);
}
//按键处理函数
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//0,没有任何按键按下
//1,KEY0按下
//2,KEY1按下
//3,KEY2按下
//4,WKUP按下 WK_UP
//注意此函数有响应优先级,KEY0>KEY1>KEY2>WK_UP!!
u8 KEY_Scan(u8 mode)
{
static u8 key_up=1;//按键按松开标志
if(mode)key_up=1; //支持连按
if(key_up&&(KEY0_Value==0||KEY1_Value==0||KEY2_Value==0||KEY_WAKE_UP==1))
{
delay_ms(10);//去抖动
key_up=0;
if(KEY0_Value==0)return 1;
else if(KEY1_Value==0)return 2;
else if(KEY2_Value==0)return 3;
else if(KEY_WAKE_UP==1)return 4;
}else if(KEY0_Value==1&&KEY1_Value==1&&KEY2_Value==1&&KEY_WAKE_UP==0)key_up=1;
return 0;// 无按键按下
}
其中Key_Scan函数为正点原子参考函数。delay 10ms的目的是为了消抖,即检测到按键按下,等待10ms之后,再检测一次,若按键确实按下,则返回相应的按键值;
Key.h文件代码如下:
#ifndef _KEY_H_
#define _KEY_H_
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "delay.h"
#define KEY_WAKE_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) //PAin(0) //both is ok
#define KEY0_Value PEin(4)
#define KEY1_Value PEin(3)
#define KEY2_Value PEin(2)
extern void KEY_init(void);
extern u8 KEY_Scan(u8);
#endif
main.c中的代码如下:
#include "LED.h"
#include "Key.h"
int main(void)
{
{
// Initinal Functions
delay_init(168);
LED_init();
KEY_init();
delay_ms(500);
}
while (1)
{
{
//Key Test
switch(KEY_Scan(0)):
{
case 1://按键Key0按下
LED0 = !LED0;
break;
case 2://按键Key1按下
LED1 = !LED1;
break;
case 3://按键Key2按下
LED0 = !LED0;
LED1 = !LED1;
break;
case 4://按键WK_UP按下
LED0 = !LED0;
break;
default://无按键按下
break;
}
}
}
}
以上便是基于固件库实现GPIO输入的配置步骤。
三、基于CubeMx实现GPIO输入
CubeMx新工程的建立以及生成代码已在前文提过具体步骤,本文重点介绍GPIO输入的配置
PA0以及PE4/PE3/PE2需要全部配置为GPIO_Input的模式


配置引脚上拉/下拉
而后生成代码
新建key.h文件,内容如下:
#ifndef _KEY_H_
#define _KEY_H_
#include "main.h"
#include "stm32f4xx_hal_gpio.h"
uint8_t KEY_Scan(uint8_t mode);
#define KEY_WAKE_UP HAL_GPIO_ReadPin(KEY_WK_UP_GPIO_Port,KEY_WK_UP_Pin)
#define KEY0_Value HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)
#define KEY1_Value HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)
#define KEY2_Value HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)
typedef enum
{
KEY0 = 1,
KEY1,
KEY2,
KEY_WKUP,
KEY_max
}KEY_all;
#endif
新建key.c文件,内容如下:
#include "key.h"
//按键处理函数
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//0,没有任何按键按下
//1,KEY0按下
//2,KEY1按下
//3,KEY2按下
//4,WKUP按下 WK_UP
//注意此函数有响应优先级,KEY0>KEY1>KEY2>WK_UP!!
uint8_t KEY_Scan(uint8_t mode)
{
static uint8_t key_up=1;//按键按松开标志
if(mode)key_up=1; //支持连按
if(key_up&&(KEY0_Value==0||KEY1_Value==0||KEY2_Value==0||KEY_WAKE_UP==1))
{
HAL_Delay(10);//去抖动
key_up=0;
if(KEY0_Value==0)return KEY0;
else if(KEY1_Value==0)return KEY1;
else if(KEY2_Value==0)return KEY2;
else if(KEY_WAKE_UP==1)return KEY_WKUP;
}else if(KEY0_Value==1&&KEY1_Value==1&&KEY2_Value==1&&KEY_WAKE_UP==0)key_up=1;
return 0;// 无按键按下
}
在main.c文件的while(1)循环中,添加如下代码
uint8_t KeyPress = 0;
KeyPress = KEY_Scan(0);
switch (KeyPress)
{
case KEY0:
HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
break;
case KEY1:
HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
break;
case KEY2:
HAL_GPIO_TogglePin(Beep_GPIO_Port,Beep_Pin);
break;
case KEY_WKUP:
HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
HAL_GPIO_TogglePin(Beep_GPIO_Port,Beep_Pin);
break;
default:
break;
}
而后便可编译运行
四、结语
本文介绍了GPIO作为按键输入时候的配置,分别基于标准固件库和CubeMx+HAL库实现功能。需要注意的关键点有:
- 结合外部按键电路判断GPIO输入上拉/下拉;
- delay 10ms用以消抖;
- Key_Scan()函数中对于支持连按和不支持连按的实现
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)