单片机按键处理:短按与长按区分方法详解(软件02)

本文目录

  •     本篇前言
  •     代码思路
  •     实操练习
  • 本篇前言

            今天接着上篇与大家继续分享软件方面关于按键事件的处理,上篇软件01篇已提到整个软件框架时基的处理,其中提到了关于按键的处理,这篇将具体地介绍按键处理的思路与实例。

            话不多说,加个封面图直接开始。

    代码思路

            按键扫描函数思路:

            1.判断GPIO按键按下。

            2.记录按下时间,判断按下时间是否满足按键消抖时间(短按时间)。

            3.满足短按时间后,标记按键按下标志位。

            4.随着按下时长是否满足长按时间,并且按键是首次使用(防止一直进行这长按操作)。

            5.判断按键是否释放,释放后,根据按下标记与按键是否为首次使用标记,是否执行短按操作,接着,重置按下时间、按下标记、按键使用标记。

    实操练习

            设计三个按键各自按下的短按(50ms),长按(3s)的处理。

            单片机硬件平台不要求,可移植到任何平台。

            按键扫描函数zj_app_key_scan.c

    #define FALSE        0
    #define TRUE         0
    
    #define BSP_KEY_1_GPIO_PIN      	    GPIO_PIN_3
    #define BSP_KEY_1_GPIO_PORT     	    GPIOB
    #define BSP_KEY_1_GET 			    !GPIO_ReadInputDataBit(BSP_KEY_1_GPIO_PORT,BSP_KEY_1_GPIO_PIN)
    
    #define BSP_KEY_2_GPIO_PIN      	    GPIO_PIN_4
    #define BSP_KEY_2_GPIO_PORT     	    GPIOB
    #define BSP_KEY_2_GET 			    !GPIO_ReadInputDataBit(BSP_KEY_2_GPIO_PORT,BSP_KEY_2_GPIO_PIN)
    
    #define BSP_KEY_3_GPIO_PIN      	    GPIO_PIN_5
    #define BSP_KEY_3_GPIO_PORT     	    GPIOB
    #define BSP_KEY_3_GET 			    !GPIO_ReadInputDataBit(BSP_KEY_3_GPIO_PORT,BSP_KEY_3_GPIO_PIN)
    
    #define KEY_1_LONG_CHECK_MS      3000
    #define KEY_1_SHORT_CHECK_MS     50
    
    #define KEY_2_LONG_CHECK_MS      3000
    #define KEY_2_SHORT_CHECK_MS     50
    
    #define KEY_3_LONG_CHECK_MS      3000
    #define KEY_3_SHORT_CHECK_MS     50
    
    uint16_t eKey_1_press_time 	    = 0;
    uint8_t eKey_1_press_flag 		= 0;
    uint8_t eKey_1_used_flag 		= 0;
    
    uint16_t eKey_2_press_time 	    = 0;
    uint8_t eKey_2_press_flag 		= 0;
    uint8_t eKey_2_used_flag 		= 0;
    
    uint16_t eKey_3_press_time 	    = 0;
    uint8_t eKey_3_press_flag 		= 0;
    uint8_t eKey_3_used_flag 		= 0;
    
    
    
    static void zj_app_key_1_short(void)
    {
      //这里写1号按键的短按处理
    }
    
    static void zj_app_key_1_long(void)
    {
      //这里写1号按键的长按处理
    }
    
    
    
    static void zj_app_key_2_short(void)
    {
      //这里写2号按键的短按处理
    }
    
    static void zj_app_key_2_long(void)
    {
      //这里写2号按键的长按处理
    }
    
    
    
    static void zj_app_key_3_short(void)
    {
      //这里写3号按键的短按处理
    }
    
    static void zj_app_key_3_long(void)
    {
      //这里写3号按键的长按处理
    }
    
    
    static void zj_app_key_1_10ms_scan(void)
    {	
    	if(BSP_KEY_1_GET)
    	{
    		eKey_1_press_time++;
    		if(eKey_1_press_time * 10 >= KEY_1_SHORT_CHECK_MS)  //防抖50ms
    			eKey_1_press_flag 	= TRUE; //标记有按下
    	}
    	else
    	{
    		//松手处理
    		if(eKey_1_press_flag && eKey_1_used_flag == FALSE) //不足长按时间3S
    			zj_app_key_1_short(); //短按处理
    		//恢复按键
    		eKey_1_press_time 		= 0;
    		eKey_1_press_flag 		= FALSE;
    		eKey_1_used_flag 		= FALSE;
    	}
    	
    	if(eKey_1_press_time * 10 >= KEY_1_LONG_CHECK_MS  && eKey_1_used_flag == FALSE)//满足长按时间3S,只有效一次长按
    	{
    		zj_app_key_1_long();//长按处理
    		eKey_1_used_flag 		= TRUE;
    	}
    }
    
    
    static void zj_app_key_2_10ms_scan(void)
    {	
    	if(BSP_KEY_2_GET)
    	{
    		eKey_2_press_time++;
    		if(eKey_2_press_time * 10 >= KEY_2_SHORT_CHECK_MS)  //防抖50ms
    			eKey_2_press_flag 	= TRUE; //标记有按下
    	}
    	else
    	{
    		//松手处理
    		if(eKey_2_press_flag && eKey_2_used_flag == FALSE) //不足长按时间3S
    			zj_app_key_2_short(); //短按处理
    		//恢复按键
    		eKey_2_press_time 		= 0;
    		eKey_2_press_flag 		= FALSE;
    		eKey_2_used_flag 		= FALSE;
    	}
    	
    	if(eKey_2_press_time * 10 >= KEY_2_LONG_CHECK_MS  && eKey_2_used_flag == FALSE)//满足长按时间3S,只有效一次长按
    	{
    		zj_app_key_2_long();//长按处理
    		eKey_2_used_flag 		= TRUE;
    	}
    }
    
    
    static void zj_app_key_3_10ms_scan(void)
    {	
    	if(BSP_KEY_3_GET)
    	{
    		eKey_3_press_time++;
    		if(eKey_3_press_time * 10 >= KEY_3_SHORT_CHECK_MS)  //防抖50ms
    			eKey_3_press_flag 	= TRUE;	//标记有按下
    	}
    	else
    	{
    		//松手处理
    		if(eKey_3_press_flag && eKey_3_used_flag == FALSE) //不足长按时间3S
    			zj_app_key_3_short(); //短按处理
    		//恢复按键
    		eKey_3_press_time 		= 0;
    		eKey_3_press_flag 		= FALSE;
    		eKey_3_used_flag 		= FALSE;
    	}
    	
    	if(eKey_3_press_time * 10 >= KEY_3_LONG_CHECK_MS  && eKey_3_used_flag == FALSE)//满足长按时间3S,只有效一次长按
    	{
    		zj_app_key_3_long();//长按处理
    		eKey_3_used_flag 		= TRUE;
    	}
    }
    
    
    void zj_app_key_scan_10ms_process(void)
    {
    	zj_app_key_1_10ms_scan();
    	zj_app_key_2_10ms_scan();
    	zj_app_key_3_10ms_scan();
    }
    

            代码的移植只需要注意各个单片机的IO初始化,按键判断高低电平以及对应的库函数即可,将zj_app_key_scan_10ms_process(void)声明后放在10ms时基处理调用即可,按键的具体操作在各自的短按处理函数、长按处理函数设计即可。

    小弟感谢大家的关注!

          (利他之心,原创分享)

    物联沃分享整理
    物联沃-IOTWORD物联网 » 单片机按键处理:短按与长按区分方法详解(软件02)

    发表评论