stm32实现GPIO输入按键检测

版权声明:均是学习笔记、心得,如有冒犯,请指出,会及时处理。https://blog.csdn.net/qq_27485531 https://blog.csdn.net/qq_27485531/article/details/83315952

1、硬件设计

按键机械触点断开、闭合时,由于按键触点的弹性作用,按键开关不会马上稳定接通或一下就断开,使用按键时就会产生下图中的带纹波信号,需要软件消抖处理滤波

由于用软件消抖处理滤波不方便输入检测,所以提出了如下带有硬件消抖的电路。

从按键的原理图可知,当按键没有被按下时,GPIO引脚通过一个下拉电阻R64使引脚处于低电平状态,当按键被按下时,按键所在的电路导通,VCC通过一个限流电阻R33连接到GPIO引脚,使GPIO引脚的输入状态为高电平,只要我们检测引脚的输入电平为高电平,即可判断按键是否被按下。

同LED工程,为了使工程的移植性更高,是工程更有条理,我们把按键相关的代码独立分开存储,在工程模板上新建“bsp_key.c”及“bsp_key.h”,这些文件可由自己的喜好命名,这些文件不属于STM32标准库的内容,是根据自己的需要编写的。

bsp_keyscan.c中代码如下

#include "bsp_keyscan.h"


/**
	* @brief		配置按键检测用到的I/O口
	* @param		无
	* @retval	        无
	*/
void	key_GPIO_Config(void)
{
	
	GPIO_InitTypeDef	GPIO_key_InitStructure;				
	RCC_AHB1PeriphClockCmd(key1_GPIO_CLK, ENABLE);			//enable AHB1 periphral clock
	RCC_AHB1PeriphClockCmd(key2_GPIO_CLK, ENABLE);			//enable AHB1 periphral clock	
	
	GPIO_key_InitStructure.GPIO_Mode  =  GPIO_Mode_IN;
	GPIO_key_InitStructure.GPIO_OType =  GPIO_OType_PP;
	GPIO_key_InitStructure.GPIO_PuPd  =  GPIO_PuPd_DOWN;
	GPIO_key_InitStructure.GPIO_Speed =  GPIO_Fast_Speed; 	       //keyscan gpio port register configure
	
	GPIO_key_InitStructure.GPIO_Pin   =  key1_pin;
	GPIO_Init(key1_GPIO_PORT,&GPIO_key_InitStructure);		//Initializes the gpio according to the specified parameters in the GPIO_key_InitStructure	

	RCC_AHB1PeriphClockCmd(key2_GPIO_CLK, ENABLE);			//enable AHB1 periphral clock	
	GPIO_key_InitStructure.GPIO_Pin   =  key2_pin;						
	GPIO_Init(key2_GPIO_PORT,&GPIO_key_InitStructure);		//Initializes the gpio according to the specified parameters in the GPIO_key_InitStructure
}


/**按键按下标志宏
  *按按键按下为高电平,设置KEY_ON = 1 , KEY_OFF = 0
	*若按键按下为低电平,设置KEY_ON = 0 , KEY_OFF = 1 即可
	*/


/**
	* @brief		检测是否有按键按下
	* @param		GPIOx:具体的端口,x可以是(A...K)
	* @param		GPIO_PIN:具体的端口位,可以是GPIO_PIN_x(x可以是0...15)
	* @retval		按键的状态
	*			@arg  KEY_ON  :按键按下
	*			@arg	KEY_OFF :按键没按下
	*/
uint8_t	Key_Scan(GPIO_TypeDef* GPIOx , uint16_t GPIO_Pin )
{
	if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON)                  //Detect whether the key is pressed
	{
		while(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON);     //Loosen the detection
		return KEY_ON;
	}
	else
	{
		return KEY_OFF;
	}

}

第一个函数是按键GPIO初始化函数,初始化的流程与LED GPIO 初始化函数 类似,主
要区别是引脚的模式。函数执行流程如下:
(1) 使用 GPIO_InitTypeDef 定义 GPIO 初始化结构体变量,以便下面用于存储 GPIO 配置。
(2) 调用库函数 RCC_AHB1PeriphClockCmd 来使能按键的 GPIO 端口时钟。
(3) 向 GPIO初始化结构体赋值,把引脚初始化成浮空输入模式,其中的 GPIO_Pin 使用宏“KEYx_PIN”来赋值,使函数的实现方便移植。由于引脚的默认电平受按键电路影响,所以设置成“浮空/上拉/下拉”模式均没有区别。
(4) 使用以上初始化结构体的配置,调用 GPIO_Init 函数向寄存器写入参数,完成 GPIO的初始化,这里的 GPIO 端口使用“KEYx_GPIO_PORT”宏来赋值,也是为了程序移植方便。
(5) 使用同样的初始化结构体,只修改控制的引脚和端口,初始化其它按键检测时使用的
GPIO引脚

第二个函数是按键扫描函数,在这里我们定义了一个 Key_Scan 函数用于扫描按键状态。GPIO引脚的输入电平可通
过读取 IDR 寄存器对应的数据位来感知,而 STM32 标准库提供了库函数GPIO_ReadInputDataBit 来获取位状态,该函数输入 GPIO端口及引脚号,函数返回该引脚的电平状态,高电平返回 1,低电平返回 0。Key_Scan 函数中以 GPIO_ReadInputDataBit 的返回值与自定义的宏“KEY_ON”对比,若检测到按键按下,则使用 while 循环持续检测按键状态,直到按键释放,按键释放后 Key_Scan函数返回一个“KEY_ON”值;若没有检测到按键按下,则函数直接返回“KEY_OFF”。若按键的硬件没有做消抖处理,需要在这个 Key_Scan函数中做软件滤波,防止波纹抖动引起误触发。

bsp_keyscan.h的代码如下

#ifndef _BSP_KEYSCAN_H
#define _BSP_KEYSCAN_H
#include "stm32f4xx.h"

/*************************引脚定义***********************/
#define		key1_pin		  GPIO_Pin_0
#define		key1_GPIO_PORT            GPIOA
#define		key1_GPIO_CLK		  RCC_AHB1Periph_GPIOA


#define		key2_pin		  GPIO_Pin_13
#define		key2_GPIO_PORT            GPIOC
#define		key2_GPIO_CLK		  RCC_AHB1Periph_GPIOC


#define		KEY_ON		1
#define		KEY_OFF		0

void	key_GPIO_Config(void);
uint8_t	Key_Scan(GPIO_TypeDef* GPIOx , uint16_t GPIO_Pin );



#endif

以上代码根据按键的硬件连接,把检测按键输入的 GPIO端口、GPIO引脚号以及GPIO端口时钟封装起来.

主函数代码如下

#include "stm32f4xx.h"
#include "bsp_led.h"
#include "bsp_keyscan.h"



int main (void)
{
	LED_Config();
	key_GPIO_Config();
	while(1)
	{
		if(Key_Scan(key1_GPIO_PORT,key1_pin) == KEY_ON )
		{
			LED_R_Toggle;
		}
		if(Key_Scan(key2_GPIO_PORT,key2_pin) == KEY_ON )
		{
			LED_B_Toggle;
		}
	}
	
}

编译运行后,按下KEY1则红灯状态改变,按下KEY2蓝灯状态改变一次(led灯的状态改变具体参照:stm32f4固件库函数点亮LED灯)。

猜你喜欢

转载自blog.csdn.net/qq_27485531/article/details/83315952