通过按键扫描函数实现STM32按键长短按

使用的是正点原子STM32F103ZET6为基础的开发板,有三个按键:KEY0、KEY1、KEY_UP(也叫作WK_UP),其中K0和K1按下后,IO口会检测到低电平,WKup按下后,IO口会检测到高电平。

{连按型:按下按键下。只要不松开,会一直有效果,

不支持连按:按下后,就视为触发一次。}

支持连按型:以WK_UP按键为例,由于WK_UP按下后,会在IO口检测到高电平,设计思路是:当按键扫描函数检测到WK_UP为低电平,不会判断WK_UP已经按下,只有检测到WK_UP口为高电平时,才会判断已经按下。(长按

不支持连按型:同样以WK_UP为例。当按键扫描函数检测到按键为高电平,并且上一次扫描为低电平,才会判断本次按键按下。就算后面不松开按键,但在没有扫描到电平的变化,因此后面的不会被判断为有效。(短按

由此可知,在编写程序时需要注意。在短按模式下,我们必须要调用上一次按键扫描的结果,只有函数扫描发现上一次结果与本次扫描结果不同,才会判断本次短按有效。因此,需要用到C语言中的关键字“Static”

Static:申明的局部变量存储在静态存储区,在函数调用结束后不会被释放,他的值会一直保留下来。所以说Static申明的局部变量具有记忆功能。

//下面两个函数有何区别?

int getValue(void)
{
 int flag=0;
 flag++;
 return flag //flag此时的值为1
}


int getValue(void)
{
 static int flag=0;
 flag++;
 return flag //flag此时的值为0
}

那么,在支持长按的一般思路为

u8 KEY_Scan(void) //u8用于存储char类型数据
{
 if(KEY按下)
 {
  delay_ms(10); //延时函数用于防抖
  if(KEY确实按下)
   {
    return KEY_Value;
   }
  return无效值
 }
}

支持短按的一般思路:

u8 KEY_Scan(void)
{
 static u8 key_up=1; //使用static申明变量key_up,如果为1,则表示按键松开,反之亦然,第一次调 
                     //用为1。该变量只会初始化一次。
 if (key_up&&KEY按下)
 {
  delay_ms(10);      //延时,防抖
  key_UP=0;          //赋值key_up为0,表示此次已经按下
  if(KEY确实按下)
   {
    return KEY_VALUE;
   }
 }
  else if(KEY没有按下)
  return没有按下
}

将长短按合二为一的一般思路:

u8 KEY_Scan(u8 mode) //mode=1,表示支持长按;mode=0,表示支持短按
{
 static u8 key_up=1; //使用static申明变量key_up,如果为1,则表示按键松开,反之亦然,第一次调 
                     //用为1。该变量只会初始化一次
 if(mode==1)key_up=1;//支持长按,即支持长按时,变量key_up一直等于1
 if (key_up&&KEY按下)
 {
  delay_ms(10);      //延时,防抖
  key_UP=0;          //赋值key_up为0,表示此次已经按下
  if(KEY确实按下)
   {
    return KEY_VALUE;
   }
 }
  else if(KEY没有按下)
  return没有按下
}

程序源码

1、头文件

#define KEY0  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)   //读取按键0
#define KEY1  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)   //读取按键1
#define WK_UP   GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) //读取按键3(WK_UP) 

#define KEY0_PRES 	1	//KEY0按下
#define KEY1_PRES	2	//KEY1按下
#define WKUP_PRES   3	//KEY_UP按下(即WK_UP/KEY_UP)


void KEY_Init(void);    //IO初始化
u8 KEY_Scan(u8);  	    //按键扫描函数					    
#endif

按键扫描函数的定义为:

//按键处理函数
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//0,没有任何按键按下
//1,KEY0按下
//2,KEY1按下
//3,KEY3按下 WK_UP
//注意此函数有响应优先级,KEY0>KEY1>KEY_UP!!
u8 KEY_Scan(u8 mode)
{	 
	static u8 key_up=1;//按键按松开标志
	if(mode)key_up=1;  //支持连按		  
	if(key_up&&(KEY0==0||KEY1==0||WK_UP==1))
	{
		delay_ms(10);//去抖动 
		key_up=0;
		if(KEY0==0)return KEY0_PRES;
		else if(KEY1==0)return KEY1_PRES;
		else if(WK_UP==1)return WKUP_PRES;
	}else if(KEY0==1&&KEY1==1&&WK_UP==0)key_up=1; 	    
 	return 0;// 无按键按下
}

2、主函数程序 (长按)

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "beep.h"


 int main(void)
 {
 	vu8 key=0;	
	delay_init();	    	  //延时函数初始化	  
	LED_Init();		  		  //初始化与LED连接的硬件接口
	BEEP_Init();         	//初始化蜂鸣器端口
	KEY_Init();         	//初始化与按键连接的硬件接口
//	LED0=0;					    //先点亮红灯
	while(1)
	{
 		key=KEY_Scan(1);	//得到键值
	   	if(key)
		 switch(key)
			{				 
				case WKUP_PRES:	//控制蜂鸣器
					BEEP=!BEEP;
					break; 
				case KEY1_PRES:	//控制LED1翻转	 
					LED1=!LED1;
					break;
				case KEY0_PRES:	//控制LED0翻转 
					LED0=!LED0;
					break;
			}else 
			     {
				  BEEP=0;
			      LED1=1;
			      LED0=1;
      			  delay_ms(10);
				 }
	}	 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值