使用的是正点原子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);
}
}
}