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

 

posted @ 2023-03-26 14:54  在下彦祖  阅读(94)  评论(0)    收藏  举报