单片机按键操作详解:单击、双击和长按功能实现

按键


按键实现的几种方式

  • 按键
  • 一、等待按键释放
  • 方式1
  • 方式2
  • 方式3
  • 二,无需等待按键释放
  • 三,按键长按或短按
  • 四、单击,双击,长按

  • 一、等待按键释放

    方式1

    #define		key		PX.X//定义按键的脚位
    //-----------------------------------------
    void	Scan_Key0(void)
    {
    	if(key==0)
    	{
    		delay(10);//10ms消抖
    		if(key==0)
    		{
    			//Add your code			if(on) on	= 0; else on = 1;
    			while(key==0)	//等待按键释放
    				nop;
    		}
    	}
    }
    

    方式2

    #define		key		PX.X//定义按键的脚位
    //--------------------------------------------
    void	Scan_Key0(void)
    {
    	int Icnt = 1000;
    	while(1)
    	{
    		if(!key)
    		{
    			Icnt--;	//用连续稳定值,去除按键抖动或其他信号干扰(如电源抖动,高频信号干扰)
    			if(Icnt==0)
    			{
    				//User add code			if(on) on	= 0; else on = 1;
    				while(key==0)	//等待按键释放
    					nop;
    				break;
    			}
    		}
    		else
    		{
    			break;			//有一个点不稳定就放弃
    		}
    	}
    }
    

    方式3

    #define		key		PX.X//定义按键的脚位
    //-------------------------------------------------
    void	Scan_Key0(void)
    {
    	if(key==0)
    	{
    		delay(10);//10ms消抖
    		int Icnt = 500;
    		while(key==0)
    		{
    			icnt--;
    			if(icnt==0)
    			{
    				//User add code			if(on) on	= 0; else on = 1;
    				while(key==0)	//等待按键释放
    					nop;
    			}
    		}
    	}
    }
    

    二,无需等待按键释放

    #define	key		Px.x//定义按键的脚位
    int		Key_Sign;	
    int 	Key_Icnt;
    
    void	Scankey(void)
    {
    	if(Key_Sign)
    	{
    		if(!Key)//判断按键是否按下
    		{
    			delay(10);//10ms消抖
    			Key_Icnt--;
    			if(Key_Icnt==0)//判断按键是否真的按下
    			{
    				Key_Sign = 0;//按键按下,开始进入松开扫描
    				//================
    				//user code
    				//================
    			}
    		}
    		else
    		{
    			Key_Icnt = 200;
    		}
    	}
    	else
    	{
    		if(Key)//扫描按键是否松开
    		{
    			Key_Sign = 1;//按键松开,开始进入按键扫描
    			Key_Icnt = 200;
    		}
    	}
    }
    

    三,按键长按或短按

    #define		Key		Px.x//定义按键的脚位
    
    int		Work_Off_Sign;
    int	    Key_Keep;
    int	    Key_Long_Sign;
    int		Delay1;
    int		Delay0;
    
    void	Scankey(void)
    {
    	if(Key_Keep==0)
    	{
    		Delay1 = 100;
    		if(Key==0)//判断是否有可能有按键
    		{
    			delay(10);//10ms消抖
    			Delay0--;
    			if(Delay0==0)//判断按键是否确定触发
    			{
    				Key_Keep = 1;
    				Key_Long_Sign = 0;
    				word Delay_Icnt = 0;
    				while(!Key)//等待,判断按键是否有长按
    				{
    				   delay(10);//10ms消抖
    					Delay_Icnt++;
    					if(Delay_Icnt >= 500)//大于一定时间确定长按
    					{
    						Key_Long_Sign = 1;
    						break;//确定长按后退出按键扫描进行下面的程序
    					}
    				}
    				if(Key_Long_Sign)//长按
    				{
    					Work_Off_Sign = 1;
    				}
    				else//短按
    				{
    					Work_Off_Sign = 0;
    				}
    			}
    		}
    		else
    		{
    			Delay0 = 100;
    		}
    	}
    	else
    	{
    		Delay0 = 100;
    		if(Key)
    		{
    			delay(10);//10ms消抖
    			Delay1--;
    			if(Delay1==0)
    			{
    				Key_Keep = 0;
    			}
    		}
    		else
    		{
    			Delay1 = 100;
    		}
    	}
    }
    

    四、单击,双击,长按

    #define KEY_DOWN_return           1  //单击
    #define KEY_Double_return         2  //双击
    #define KEY_Long_return           3  //长按
    #define KEY_LONG_FREE_return      6  //长按结束
    
    #define double_time_MIN       80  //双击按键,在这个时间范围内,按下两次则认为有效
    #define Long_press_time_MAX   120  //长按,超过这个时间则认为是长按;
    #define Dithering_MIN         5  //消抖值
    #define UP_KEY_Count        5  //抬起值
    
    #define KEY_UP      1//按键抬起
    #define KEY_Down    0//按键按下
    
    #define KEY_Number_MAX  1 //按键个数,开辟多少字节数组
    
    #define KEY1_adder    0 //按键计数数组地址
    //#define KEY2_adder   1 //按键计数数组地址
    //#define KEY3_adder   2 //按键计数数组地址
    
    #define  Read_Key1_Value    GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10)//读取按键1的值
    
    unsigned int  KEY_Count_time[KEY_Number_MAX];//按键计时,调用的时候,要填按键地址,避免重复
    unsigned char KEY_up_clsse_time[KEY_Number_MAX];//按键抬起取消计时,
    unsigned char KEY_Count_down[KEY_Number_MAX];//按键按下次数
    unsigned char KEY_Dithering[KEY_Number_MAX];//按键消抖
    
    unsigned char KEY_event[KEY_Number_MAX];//按键的事件
    unsigned char KEY_Read[KEY_Number_MAX];//按键读取状态
    
    /*
        * @name   Button_all_state
        * @brief  MUC按键检测
        * @param
        * @retval None
        * othen: 历遍所有的按键
    */
    void  Button_all_state()
    {
    
        KEY_Read[KEY1_adder]=Read_Key1_Value;
        //  KEY_event[KEYX_adder]=Read_KeyX_Value;
    }
    /*
        * @name   KEY_Detect
        * @brief
        * @param
        * @retval None
        * othen:按键检查函数,传递不同的值,实现不同的按键按下
    */
    void  KEY_Detect()
    {
        unsigned char i=0;
        Button_all_state();//更新按键状态
    
       for(i=0;i<KEY_Number_MAX;i++) //历遍
       {
           if(KEY_Read[i]==KEY_Down)//按键按下
           {
    
    
               if(KEY_Dithering[i] > Dithering_MIN)//消抖值
               {
    
                   if(KEY_Count_time[i] >= Long_press_time_MAX)
                   {
                       KEY_event[i] = KEY_Long_return;
                   }
                   else
                   {
                       KEY_Count_time[i]++;
                   }
                   if(KEY_up_clsse_time[i] != 0)
                   {
                       KEY_up_clsse_time[i] =0;
                       KEY_Count_down[i]++;
                   }
               }
               else
               {
                   KEY_Dithering[i]++;
                   KEY_Read[i]=0;//按键刷新
               }
    
           }
           else//按键松开
           {
    
               if( ++KEY_up_clsse_time[i] > UP_KEY_Count) {//按键抬起
    
                   if ((KEY_Count_time[i] < double_time_MIN)&& ( KEY_Count_down[i] >= 2) ) { //双击
                         KEY_event[i] =  KEY_Double_return;
                         KEY_up_clsse_time[i] = UP_KEY_Count;
                   }
                   else if((KEY_Count_time[i] > 1)&&(KEY_Count_time[i] < Long_press_time_MAX)){ //单击
                         KEY_event[i] = KEY_DOWN_return ;
                         KEY_up_clsse_time[i] = UP_KEY_Count;
                   }
                   else if(KEY_Count_time[i] > Long_press_time_MAX){ //长按抬起
                       KEY_event[i] = KEY_LONG_FREE_return;
                       KEY_up_clsse_time[i] = UP_KEY_Count;
                   }
                   KEY_up_clsse_time[i] =0;
                   KEY_Count_time[i]= 0;//按键计时更新
                   KEY_Dithering[i] = 0;//消抖更新
                   KEY_Read[i]=0;//按键刷新
                   KEY_Count_down[i]=0;
               }
    
           }
    
       }
    }
    

    调用

              KEY_Detect();
              if(KEY_event[KEY1_adder] ==  KEY_DOWN_return )
              {
                  printf("单击\r\n");
                  KEY_event[KEY1_adder]=0;
              }
              else if(KEY_event[KEY1_adder] ==  KEY_Double_return  )
              {
                  printf("双击\r\n");
                  KEY_event[KEY1_adder]=0;
              }
              else if(KEY_event[KEY1_adder] ==  KEY_Long_return )
              {
                  printf("长按\r\n");
                  KEY_event[KEY1_adder]=0;
              }
    
    物联沃分享整理
    物联沃-IOTWORD物联网 » 单片机按键操作详解:单击、双击和长按功能实现

    发表评论