STM32-按键,内含按键的两类设计以及按键的长按短按、按键消抖、按键按下松开设计

在我们学习STM32的过程中,按键是一个非常重要且必须要掌握的一个板块。下面小编就带大家进入按键模块吧!

一、原理说明

看到上面的原理图,想必大家已经知道该块STM32开发板的按键按下后的返回值应该是0。由于该开发板的按键数量比较少,因此我们直接使用switch即可判断某一个按键是否按下 。

二、部分库函数解析

1、GPIO_ReadInputDataBit函数

2、GPIO_ReadInputData函数

三、代码解析

1、枚举变量与全局变量

c 复制代码
//定义变量 存储上次按键按下的值
unsigned char key_old;

//枚举按键但是KEY0是无效的 为了匹配现实中开发板按键的位置而设立
enum KEY_NUM{KEY0,KEY1,KEY2,KEY3,KEY4,KEY5};

2、GPIO初始化

在GPIO初始换中,我们只需要打开GPIOE时钟,选择GPIO引脚、GPIO的频率、GPIO的模式即可。

c 复制代码
/*
	* @brief The initialization of the button GPIO(按键GPIO的初始化)
	* @param none
	* @retval none
*/
void key_GPIO_init(void)
{
	//声明一个结构体,用于初始化GPIO
	GPIO_InitTypeDef GPIO_InitStructure;
	//开启GPIO的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
	//选择GPIO的引脚为Pin0,Pin2,Pin3
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
	//设置GPIO的速度为50MHz
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	//将GPIO引脚设置成上拉输入模式
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	//GPIOE引脚的初始化
	GPIO_Init(GPIOE,&GPIO_InitStructure);
}

3、按键扫描函数1

小编个人认为按键扫描函数1相对于按键扫描函数2来说,更容易理解,建议大家看懂扫描函数1后再去看扫描函数2。

c 复制代码
/*
	* @brief Determine whether the button is pressed(判断某一个按键是否按下)
	* @param KEY_NUM:one of a button(其中一个按键)
	* @retval key_num:Back to judgment status 0-pressed 1-not pressed(返回判断的状态 0-未按下 1-按下)
*/
int get_key(int KEY_NUM)
{
	//待判断按键的返回状态 0-表示按下 1-表示松开
	int key_num = 3;
	switch(KEY_NUM){
		//判断key1
		case KEY1: key_num = GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_0);break;
		//判断key2
		case KEY2: key_num = GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_1);break;
		//判断key3
		case KEY3: key_num = GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2);break;
		//判断key4
		case KEY4: key_num = GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3);break;
		//判断key5
		case KEY5: key_num = GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_6);break;
		//屏蔽可能出现的干扰
		default: break;
	}
	return key_num;
}

4、按键服务函数1

这里的按键服务函数小编以点亮开发板上的LED灯为例。(想看小编的点亮LED函数可通过链接前往------STM32-八位流水灯

c 复制代码
/*
	* @brief scan the button and perform the corresponding function which is Press and light up or loosen and go out
	*				(扫描按键并且执行相应的功能)
	* @param none
	* @retval none
*/
void scan_key(void)
{
	if(get_key(KEY1) == 0){//按下key1点亮LED1
		LED_ctrl(LED1,LED_ON);
	}else{//松开key1熄灭LED1
		LED_ctrl(LED1,LED_OFF);
	}
	
	if(get_key(KEY2) == 0){//按下key2点亮LED2
		LED_ctrl(LED2,LED_ON);
	}else{//松开key2熄灭LED2
		LED_ctrl(LED2,LED_OFF);
	}
	
	if(get_key(KEY3) == 0){//按下key3点亮LED3
		LED_ctrl(LED3,LED_ON);
	}else{//松开key3熄灭LED3
		LED_ctrl(LED3,LED_OFF);
	}
	
	if(get_key(KEY4) == 0){//按下key4点亮LED4
		LED_ctrl(LED4,LED_ON);
	}else{//松开key4熄灭LED4
		LED_ctrl(LED4,LED_OFF);
	}
	
	if(get_key(KEY5) == 0){//按下key5点亮LED5
		LED_ctrl(LED5,LED_ON);
	}else{//松开key5熄灭LED5
		LED_ctrl(LED5,LED_OFF);
	}
	
	//熄灭无关的LED6、LED7、LED8
	LED_ctrl(LED6,LED_OFF);
	LED_ctrl(LED7,LED_OFF);
	LED_ctrl(LED8,LED_OFF);
}

5、按键扫描函数2

小编个人认为,尽管扫描函数2比扫描函数1跟不容易理解,但是小编更加青睐它。

c 复制代码
/*
	* @brief  scan the button and back to the value
	* @param  none
	* @retval key_val:Back to key number which was pressed(返回被按下按键的值)
*/
unsigned char scan_kbd(void)
{
	//定义一个返回值
	unsigned char key_val = 0;
	//扫描按键的引脚
	unsigned int key_press = GPIO_ReadInputData(GPIOE);
	//排除其他引脚的影响
	key_press = key_press|0xffb0;
	//判断按键是否按下
	switch(key_press)
	{
		//KEY1按下
		case 0xfffe: key_val = 1;break;
		//KEY2按下
		case 0xfffd: key_val = 2;break;
		//KEY3按下
		case 0xfffb: key_val = 3;break;
		//KEY4按下
		case 0xfff7: key_val = 4;break;
		//KEY5按下
		case 0xffbf: key_val = 5;break;
		//所有按键都没按下或者其他可能出现的干扰
		default: key_val = 0;break;
	}
	return key_val;
}

6、按键服务函数2

这里小编是以数码管显示数值为实例的。相对于服务函数1而言,小编在服务函数2中加上了按键消抖、按键松开、按键按下这三个功能。其实这里的按键扫描函数使用函数1应该也是能够达到该效果的,不过小编没有尝试。(小编这里有数码管刷新的具体函数,可前往链接------STM32-刷新数码管

c 复制代码
/*
	* @brief perform the corresponding function which is Press(执行按键按下后的执行相应的函数)
	* @param none
	* @retval none
*/
void key_por(void)
{
	static unsigned int number = 0;
	//定义变量 存储案件是否松开、按下的值
	unsigned char key_up,key_down;
	//按键扫描
	unsigned int key_num = scan_kbd();
	//获取按键是否按下
	key_down = key_num & (key_old ^ key_num);
	//获取按键是否松开
	key_up = ~key_num & (key_old ^ key_num);
	//保存本次按键的值
	key_old = key_num;
	
	if(key_down){//按键消抖 每次只有按键按下后number的值才会加1
		number++;
	}
	
	segbuff[0] = key_num;
	segbuff[1] = key_down;
	segbuff[2] = key_up;
	segbuff[3] = key_old;
	segbuff[5] = number;
}

四、总结

STM32F103ZET6开发板的按键数量相对较少,实现按键扫描函数相对简单。     在我们写按键扫描函数时,第一步需要查阅原理图,观察按键的排列方式;第二步,判断扫描按键使用的方法,即是否需要使用行列扫描法扫描函数,若不需要(也就是按键数量较少、排列简单的前提下)我们可以直接使用switch判断按键是否按下;第三步,若有需要,可以完善按键的功能。

相关推荐
wenchm1 小时前
细说STM32F407单片机轮询方式读写SPI FLASH W25Q16BV
stm32·单片机·嵌入式硬件
委员1 小时前
基于NodeMCU的物联网电灯控制系统设计
单片机·物联网·嵌入式·nodemcu··lu_asr01·gy-302
单片机学习之路1 小时前
【C语言】结构
c语言·开发语言·stm32·单片机·51单片机
m0_748254093 小时前
STM32--超声波模块(HC—SR04)(标准库+HAL库)
stm32·单片机·嵌入式硬件
南城花随雪。3 小时前
单片机:实现FFT快速傅里叶变换算法(附带源码)
单片机·嵌入式硬件·算法
逝灮3 小时前
【蓝桥杯——物联网设计与开发】基础模块8 - RTC
stm32·单片机·嵌入式硬件·mcu·物联网·蓝桥杯·rtc
weixin_4526006910 小时前
串行时钟保持芯片D1380/D1381,低功耗工作方式自带秒、分、时、日、日期、月、年的串行时钟保持芯片,每个月多少天以及闰年能自动调节
科技·单片机·嵌入式硬件·时钟·白色家电电源·微机串行时钟
森旺电子13 小时前
51单片机仿真摇号抽奖机源程序 12864液晶显示
单片机·嵌入式硬件·51单片机
Rorsion15 小时前
各种电机原理介绍
单片机·嵌入式硬件
善 .18 小时前
单片机的内存是指RAM还是ROM
单片机·嵌入式硬件