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

相关推荐
gscsded2 小时前
C2000 GPIO 配置笔记
单片机
Sakuyu434682 小时前
STM32基础
stm32·单片机·嵌入式硬件
gscsded2 小时前
C2000 CPU Timer 学习笔记
单片机
iCxhust4 小时前
AD0808调试笔记
笔记·单片机·嵌入式硬件·操作系统·微机原理·8088单板机
木子单片机4 小时前
基于51单片机的步进电机调速系统设计
单片机·嵌入式硬件·51单片机·keil
三易串口屏5 小时前
实验10 物理按键实验
单片机·51单片机·串口屏·串口协议·uart 通信·嵌入式 ui
深圳光特通信豆子5 小时前
10Mb/s TTL单模双纤光收发模块技术规格手册
单片机·嵌入式硬件
一路往蓝-Anbo5 小时前
第六章:RTOS 任务 —— 任务逻辑与并发的 TDD 路径
网络·stm32·单片机·嵌入式硬件·tdd
星夜夏空995 小时前
STM32单片机学习(20) —— 利用中断实现串口通信(填前面的坑)
stm32·单片机·学习
wengqidaifeng6 小时前
2026年电赛校赛备战MSPM0G3507+keil讲解(上)-----2025年电赛E题小车篇
单片机·嵌入式硬件·电赛