用户注册



邮箱:

密码:

用户登录


邮箱:

密码:
记住登录一个月忘记密码?

发表随想


还能输入:200字
云代码 - c代码库

各种按键模式的扫描

2017-12-25 作者:杰瑞鼠举报

[c]代码库

#ifndef __KEY_H
#define __KEY_H	 
#include "common.h" 

//////////////////////////////////////////////////////////////////////////////////	 

//按键IO端口定义
#define KEY0 		PFin(9)   
#define KEY1 		PFin(8)		
#define KEY2 		PFin(7)		
#define KEY3 	  PFin(6)		


//按键值定义
#define KEY0_DATA	  1
#define KEY1_DATA	  2
#define KEY2_DATA	  3
#define KEY3_DATA   4

//变量声明
extern u8   keydown_data;    //按键按下后就返回的值
extern u8   keyup_data;      //按键抬起返回值
extern u16  key_time;
extern u8   key_tem; 

//函数声明
void KEY_Init(void);	      //IO初始化
void key_scan(u8 mode);  		//按键扫描函数	

#endif
#include "key.h"

/*********************************************************************************
**********************MCU启明 STM32F407应用开发板(高配版)*************************
**********************************************************************************
* 文件名称: key.c                                                                *
* 文件简述:按键扫描程序                                                         *
* 创建日期:2015.10.03                                                           *
* 版    本:V1.0                                                                 *
* 作    者:Clever                                                               *
* 说    明:该按键扫描,包涵各种按键模式的扫描                                   * 
**********************************************************************************
*********************************************************************************/

/**
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~按键模式剖析~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
一、按键返回值,即按键扫描结果值,分为以下几种情况
		1、按键按下未抬起时的返回值,对应代码中 keydown_data 变量的值
		2、按键按下抬起后才返回的值,对应代码中 keyup_data   变量的值
		3、按任意键有效,只需在程序中判断key_time>某个值,该值取决于执行一次扫描函数的
		   时间长短,扫描函数时间长,相应这该值就小,反之亦然。
		4、需要长按一个键一段时间才执行相应的程序,就需要该键键值key_tem与key_time
		   配合使用,即实现某个按键(key_tem)长按多久(key_time)后执行相应的程序
二、按键使用模式
    1、单按:按键按下(一直按着)只返回一次有效按键值
		2、连按:按键一直按着每执行一次按键扫描函数就返回一次按键值
		3、void key_scan(u8 mode) 中 mode   0:单按   1:连按
三、按键使用注意事项;
    1、当使用抬起返回值keyup_data时,按键的连按模式无效,因为键抬起才返回按键值,你
		   按再久都没用,所以在使用keyup_data时,模式mode必须设置为0
		2、如果需要keydown_data与key_time配合构成长按,模式mode需设置为1,才可用
		3、如果需要keyup_data与key_time配合构成长按,就要对程序作出相应的改动,在函数的
		   末尾,将 key_time=0; 改为 key_tem=0;就可以使用长按一个按键一段时间,等时间到
			 并且按键抬起才执行相应的代码。不过这样改动,按任意键就失效了,因为按键抬起没
			 把key_time清零,key_time一直有值。或者用户还是需要任意键有效就要自己在相应的
			 代码中把key_time清零。这种长按配合使用在实际是很少用到的。
**/

u8  keydown_data=0x00;    //按键按下后就返回的值
u8  keyup_data=0x00;      //按键抬起返回值
u16  key_time=0x00;       //按键按下之后的时间计数,该值乘以扫描一次按键函数的时间就等于按键按下的时间

u8  key_tem=0x00;         //长按的按键值与按键扫描程序过渡变量
u8  key_bak=0x00;         //按键扫描程序过渡变量

//按键IO口初始化函数
void KEY_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);    //使能GPIOF时钟
 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9; //KEY0 KEY1 KEY2 KEY3对应引脚
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;             //普通输入模式
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;       //100M
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;             //上拉
  GPIO_Init(GPIOF, &GPIO_InitStructure);                   //初始化GPIOF6,7,8,9
} 
/****************************************************************************
* 名    称: void key_scan(u8 mode)
* 功    能:按键扫描函数
* 入口参数:mode:0:单按 
                  1: 连按
* 返回参数:无
* 说    明:响应优先级,KEY0>KEY1>KEY2>KEY3
****************************************************************************/
void key_scan(u8 mode)
{	   
	 keyup_data=0;         //键抬起后按键值一次有效
	
	if(KEY0==0||KEY1==0||KEY2==0||KEY3==0)   //有键正按下
	{
		if(KEY0==0)      key_tem=1;
		else if(KEY1==0) key_tem=2;
		else if(KEY2==0) key_tem=3;
		else if(KEY3==0) key_tem=4;
		
		  if (key_tem == key_bak)      //有键按下后第一次扫描不处理,与else配合第二次扫描有效,这样实现了去抖动
			  {
				   key_time++;             //有键按下后执行一次扫描函数,该变量加1
					 keydown_data=key_tem;   //按键值赋予keydown_data
					
					 if( (mode==0)&&(key_time>1) )//key_time>1按键值无效,这就是单按,如果mode为1就为连按
					    keydown_data=0;
       	}
	    else                             //去抖动      
	      {
		       key_time=0;
		       key_bak=key_tem;
	      }
		
	}
	else       //键抬起
		{
	     if(key_time>2)            //按键抬起后返回一次按键值
	        {
		        keyup_data=key_tem;  //键抬起后按键值赋予keydown_data            						
	       	}
				key_bak=0;               //要清零,不然下次执行扫描程序时按键的值跟上次按的值一样,就没有去抖动处理了
	      key_time=0;
				keydown_data=0;		
	  }    
}


分享到:
更多

网友评论    (发表评论)


发表评论:

评论须知:

  • 1、评论每次加2分,每天上限为30;
  • 2、请文明用语,共同创建干净的技术交流环境;
  • 3、若被发现提交非法信息,评论将会被删除,并且给予扣分处理,严重者给予封号处理;
  • 4、请勿发布广告信息或其他无关评论,否则将会删除评论并扣分,严重者给予封号处理。