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判断按键是否按下;第三步,若有需要,可以完善按键的功能。

相关推荐
m0_7393128714 分钟前
【STM32】项目实战——OV7725/OV2604摄像头颜色识别检测(开源)
stm32·单片机·嵌入式硬件
徐嵌2 小时前
STM32项目---水质水位检测
stm32·单片机·嵌入式硬件
徐嵌2 小时前
STM32项目---畜牧定位器
c语言·stm32·单片机·物联网·iot
lantiandianzi2 小时前
基于单片机的老人生活安全监测系统
单片机·嵌入式硬件·生活
IT B业生12 小时前
51单片机教程(六)- LED流水灯
单片机·嵌入式硬件·51单片机
一枝小雨12 小时前
51单片机学习心得2(基于STC89C52):串口通信(UART)
单片机·嵌入式硬件·51单片机
IT B业生13 小时前
51单片机教程(一)- 开发环境搭建
单片机·嵌入式硬件·51单片机
海绵波波10715 小时前
Webserver(4.8)UDP、广播、组播
单片机·网络协议·udp
好想有猫猫15 小时前
【51单片机】串口通信原理 + 使用
c语言·单片机·嵌入式硬件·51单片机·1024程序员节
stm 学习ing17 小时前
C语言 循环高级
c语言·开发语言·单片机·嵌入式硬件·算法·嵌入式实时数据库