Alkaitu:STM32时间轮询判断按键的方式

#include "user_key.h"
#include "stm32f10x.h"


/***************************************************************************************************/
/*移植需要改动4处地方*/
/***************************************************************************************************/ 
 
 
/**************************************移植修改的第1处*************************************************/
/*按键的数量,短按时间,长按时间设置*/
/***************************************************************************************************/
#define KEY_NUM_ALL 2        //按键的总的数量,预设了7个按键,如值超过7的话,记得按例修改代码
#define KEY_SHORT_TIME 20    //短按的持续时间,这个值可以调整按键的灵敏度
#define KEY_LONG_TIME 4000   //长按的持续时间,这个值可以调整按键的灵敏度
/***************************************************************************************************/ 


/**************************************移植修改的第2处**********************************************/
/*按键电平的宏定义,改变按键需要改动这里宏定义,且必须按KEY1-KEY7一次增加*/
/***************************************************************************************************/
#define KEY1 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3)  //按键的状态函数,增加按键,可以按这个格式增加
#define KEY2 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4) 
/***************************************************************************************************/ 


/***************************************************************************************************/
/*此结构体类型无需改动*/
/***************************************************************************************************/
typedef struct
{
  const unsigned char key_press_type;          //按键按下类型设置,1:短按 11:长按 111:短按和长按
	volatile unsigned char key_lock_flag;        //自锁标志,用于保证按键轮询是第一次进入计时,保证一次的准确计时
	volatile unsigned int key_scan_count;        //按键在定时器轮询计数变量,自加
	volatile unsigned char key_short_press_flag; //按键短按标志位
	volatile unsigned char key_long_press_flag;  //按键长按标志位,目前这变量没用到,一般是多次单击会用到这个变量
  volatile unsigned char key_num;              //按键的键值
}KEY_InitTypeDef;
/***************************************************************************************************/


/*************************************移植修改的第3处**********************************************/
/*预设7个按键,如增加新按键,可按格式增加,只允许改动第一个值,只有1,11,111三个值*/
/***************************************************************************************************/
KEY_InitTypeDef key_array[KEY_NUM_ALL] =   
{                                          
  {111,0,0,0,0,0,},
	
	#if KEY_NUM_ALL > 1
  {111,0,0,0,0,0,},
	#endif
	
	#if KEY_NUM_ALL > 2
  {1,0,0,0,0,0,},
	#endif
	
	#if KEY_NUM_ALL > 3
  {1,0,0,0,0,0,},
	#endif
	
	#if KEY_NUM_ALL > 4
  {1,0,0,0,0,0,},
	#endif
	
	#if KEY_NUM_ALL > 5
  {1,0,0,0,0,0,},
	#endif
	
	#if KEY_NUM_ALL > 6
  {1,0,0,0,0,0,},
	#endif
};
/***************************************************************************************************/
 
 
/***************************************移植修改的第4处*****************************************/
/*按键初始化函数,更改按键硬件需要改动此函数*/
/***************************************************************************************************/
void user_key_init(void)
{

	 GPIO_InitTypeDef GPIO_InitStruct; 
	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);

	 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;	
   GPIO_Init(GPIOE, &GPIO_InitStruct);
	 
	 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;
   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
   GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;	
   GPIO_Init(GPIOE, &GPIO_InitStruct);
}	
/*******************************************************************************************/
 

/***************************************************************************************************************/
/*此函数必须放置到定时器中断服务函数中,轮询判断按键状态*/
/*如按键超过7个,按次格式依次增加即可,此函数移植无需改动*/
/**************************************************************************************************************/
void user_key_scan(void)
{
  unsigned char i,key_IOvaule;         //定义按键的电压变量
	for(i = 0;i < KEY_NUM_ALL; i++)      //轮询按键电平
	{
	  switch(i)
		{
		  case 0: if(KEY1 == 1){key_IOvaule = 1;}else{key_IOvaule = 0;};break;  //条件编译方式预设了7个按键
																																						//超过7个按格式增加即可
			#if KEY_NUM_ALL > 1
			case 1: if(KEY2 == 1){key_IOvaule = 1;}else{key_IOvaule = 0;};break;   //判断按键电平
			#endif
			
			#if KEY_NUM_ALL > 2
  		case 2: if(KEY3 == 1){key_IOvaule = 1;}else{key_IOvaule = 0;};break;
      #endif
			
			#if KEY_NUM_ALL > 3
		  case 3: if(KEY4 == 1){key_IOvaule = 1;}else{key_IOvaule = 0;};break;
			#endif
			
			#if KEY_NUM_ALL > 4
		  case 4: if(KEY5 == 1){key_IOvaule = 1;}else{key_IOvaule = 0;};break;
			#endif
			
			#if KEY_NUM_ALL > 5
		  case 5: if(KEY6 == 1){key_IOvaule = 1;}else{key_IOvaule = 0;};break;
			#endif
			
			#if KEY_NUM_ALL > 6
		  case 6: if(KEY7 == 1){key_IOvaule = 1;}else{key_IOvaule = 0;};break;
			#endif
		}
		if(key_array[i].key_press_type == 1)                         //判断按键需要做什么类型的检测 
		{                                                            //做短按判断
		  switch(key_IOvaule)
			{
			  case 1: key_array[i].key_scan_count = 0;                  //按键没按下,计数清零
				        key_array[i].key_lock_flag = 0;                   //自锁标志清零
								break;
				case 0: if(key_array[i].key_lock_flag == 0)               //按键按下并且是第一次按下
                {
								  key_array[i].key_scan_count++;                  //计数时间开始
									if(key_array[i].key_scan_count > KEY_SHORT_TIME)  //计数时间大于设定的值,按键短按下
									{
									  key_array[i].key_scan_count = 0;               //计数清零
										key_array[i].key_lock_flag = 1;                //完成了一次短按判断.标志清零,避免重复请进入
										key_array[i].key_num = 1;                      //给按键赋键值,短按
									}
								};break;							
			}
		}
		if(key_array[i].key_press_type == 11)                         //判断按键需要做什么类型的检测 
		{                                                             //做长按判断
		  switch(key_IOvaule)
			{
			  case 1: key_array[i].key_scan_count = 0;                  //按键没按下,计数清零
				        key_array[i].key_lock_flag = 0;                   //自锁标志清零
								break;
				case 0: if(key_array[i].key_lock_flag == 0)               //按键按下并且是第一次按下
                {
								  key_array[i].key_scan_count++;                  //计数时间开始
									if(key_array[i].key_scan_count > KEY_LONG_TIME) //计数时间大于设定的值,按键长按下     
									{
									  key_array[i].key_scan_count = 0;              //计数清零
										key_array[i].key_lock_flag = 1;               //完成了一次短按判断.标志清零,避免重复请进入
										key_array[i].key_num = 11;                    //给按键赋键值,长按
									}
								};break;							
			}
		}
		if(key_array[i].key_press_type == 111)                        //判断按键需要做什么类型的检测 
		{                                                             //做短按和长按一起判断
		  switch(key_IOvaule)
			{
			  case 1: key_array[i].key_scan_count = 0;                  //按键没按下,计数清零
				        key_array[i].key_lock_flag = 0;                   //自锁标志清零
								if(key_array[i].key_short_press_flag == 1)        //按键松开会跳到这,最终判定为短按
								{
								  key_array[i].key_short_press_flag = 0;          //短按标志清零
									key_array[i].key_num = 1;                       //给按键赋键值,短按
								};break;
				case 0: if(key_array[i].key_lock_flag == 0)               //按键按下并且是第一次按下
                {
								  key_array[i].key_scan_count++;                   //计数时间开始
									if(key_array[i].key_scan_count > KEY_SHORT_TIME)   //计数时间大于设定的值, 属于按键短按
									{                                                  
										key_array[i].key_short_press_flag = 1;           //设置短按标志位,初步判断为短按
									}                                         //接下来等待计时,可以判断按键是松开还是继续按着
								}
								if(key_array[i].key_scan_count > (KEY_LONG_TIME - KEY_SHORT_TIME))
								{                                                 //按键计时接着增加,大于设定的长按时间
                   key_array[i].key_scan_count = 0;               //计时清零
                   key_array[i].key_lock_flag = 1;                //设置自锁标志,完成一个长按判断,放置重复进入
                   key_array[i].key_short_press_flag = 0;	        //清除短按标志
                   key_array[i].key_num = 11;										  //给按键赋键值,长按
                };break;								
			}
		}
	}
}
/*********************************************************************************************************************/


/*********************************************************************************************/
/*此函数获取按键键值,如按键个数小于7,移植无需改动,参数为按键的序号key_id:1-7,返回值1,11,111三种*/
/*如按键超过7个,按次格式依次增加即可*/
/*********************************************************************************************/
unsigned char key_get_num(unsigned char key_id)                            
{                                                                          
  unsigned char key_local_param;                                         
	switch(key_id)                                                          
	{                                                                        
		case 1: key_local_param = key_array[0].key_num;break;
    
		#if KEY_NUM_ALL > 1
		case 2: key_local_param = key_array[1].key_num;break;
    #endif
		
		#if KEY_NUM_ALL > 2
		case 3: key_local_param = key_array[2].key_num;break;
    #endif 
		
		#if KEY_NUM_ALL > 3
		case 4: key_local_param = key_array[3].key_num;break;
    #endif
		
		#if KEY_NUM_ALL > 4
		case 5: key_local_param = key_array[4].key_num;break;
    #endif 
		
		#if KEY_NUM_ALL > 5
		case 6: key_local_param = key_array[5].key_num;break;
    #endif
		
		#if KEY_NUM_ALL > 6
		case 7: key_local_param = key_array[6].key_num;break;
    #endif
  }	                                                                       
	return key_local_param;	
}   
/***************************************************************************************/


/***************************************************************************************/
/*此函数清除按键键值,如按键个数小于7,移植无需改动,参数为按键的序号key_id:1-7*/
/*如按键超过7个,按次格式依次增加即可*/
/***************************************************************************************/
void key_clear_num(unsigned char key_id)
{
  switch(key_id)
	{
	  case 1: key_array[0].key_num = 0;break;
		
		#if KEY_NUM_ALL > 1
		case 2: key_array[1].key_num = 0;break;
		#endif
		
		#if KEY_NUM_ALL > 2
	  case 3: key_array[2].key_num = 0;break;
		#endif
		
	  #if KEY_NUM_ALL > 3
		case 4: key_array[3].key_num = 0;break;
		#endif
		
		#if KEY_NUM_ALL > 4
	  case 5: key_array[4].key_num = 0;break;
		#endif
		
		#if KEY_NUM_ALL > 5
	  case 6: key_array[5].key_num = 0;break;
		#endif
		
		#if KEY_NUM_ALL > 6
	  case 7: key_array[6].key_num = 0;break;
		#endif
	}
}                                                                     
/*************************************************************************************/
#ifndef _user_key_h_
#define _user_key_h_



/**************************/
/*按键初始化,移植需改动*/
void user_key_init(void);
/**************************/


/******************************************************/
/*此函数必须放置到定时器中断服务函数中,轮询判断按键状态*/
/*如按键超过7个,按次格式依次增加即可,此函数移植无需改动*/
void user_key_scan(void);
/*****************************************************/


/*****************************************************/
/*这两个函数配合使用,在主函数调用*/
/*如按键超过7个,按次格式依次增加即可,此函数移植无需改动*/
/*主要使用这两个函数,获取按键的键值和清除按键的键值*/
/*获取按键的键值后必须清除按键的键值*/
/*注意获取和清除的编号一定要对应,不然容易出现按键一直处于长按或者短按*/
unsigned char key_get_num(unsigned char key_id);
void key_clear_num(unsigned char key_id);
/*****************************************************/


#endif



  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值