【STC15】前后台方式实现按键的长按检测(面向对象)

数据结构(结构体定义借鉴了面向对象思想):

#ifndef __KEY_H_
#define __KEY_H_

//定义按键引脚
#define KEY1_State P32

//定义结构体类型
typedef struct 
{
    uint8_t volatile KEY_Flag;      //按键标志位
    uint8_t Click;                  //单击
    uint8_t Double_Click;           //双击
    uint8_t Press;                  //长按
    void (*KEY_Detect)();
}KEY_t;

/* extern variables-----------------------------------------------------------*/
extern KEY_t KEY1;
/* extern function prototypes-------------------------------------------------*/ 

#endif
/********************************************************
  End Of File
********************************************************/

 

后台:中断

/*
* @name   INT0_isr
* @brief  外部中断0中断处理函数
* @param  None
* @retval None   
*/
void INT0_isr() interrupt 0
{
    KEY1.KEY_Flag = TRUE;
    //Run_LED.Run_LED_Flip();
}

 

前台:轮询

/* Includes ------------------------------------------------------------------*/
#include <main.h>

/* Private define-------------------------------------------------------------*/

/* Private variables----------------------------------------------------------*/
static void KEY_Detect();
/* Public variables-----------------------------------------------------------*/
KEY_t KEY1 = {FALSE,FALSE,FALSE,FALSE,KEY_Detect};
/* Private function prototypes------------------------------------------------*/

/*
* @name   KEY_Detect
* @brief  按键检测
* @param  None
* @retval None   
*/
static void KEY_Detect()
{
    uint8_t i;

    //长按检测
    if(KEY1.KEY_FLAG == TRUE)
    {
        KEY1.Press = TRUE;               //如果有按键按下,默认会进行长按
        for(i = 0;i<200;i++)            //每次循环延时10ms,即延时2秒
        {
            Public.Delay_ms(10);
            if(KEY1_State == 1)          //如果这期间按键松开了,则达不到长按的条件
            {
                KEY1.Press = FALSE;      //长按标志位清0
                break;                  //提前结束延时
            }
        }
    }
}

/*
* @name   KEY_Act
* @brief  按键功能执行
* @param  None
* @retval None   
*/
static void KEY_Act()
{
    //按键功能
    //单击 -> 运行指示灯翻转
    //长按 -> 运行指示灯闪一下
    if(KEY1.Press == TRUE)
    {
        Run_LED.Run_LED_Flip();
        Public.Delay_ms(100);
        Run_LED.Run_LED_Flip();
    }
    else
    {
        if(KEY1.Click == TRUE)
        {
            Run_LED.Run_LED_Flip();
        }
    }
    KEY1.Click = FALSE;
    KEY1.Press = FALSE;
    EX0 = 1;                        //打开中断
}

 主函数:


/*
	* @name   main
	* @brief  主函数
	* @param  void	
	* @retval int      
*/
int main(void)
{	
	//系统初始化
	Hradware.Sys_Init();
	//系统主循环
	while(1)
    {
		KEY1.KEY_Detect();//按键检测
        KEY1.KEY_Act();//按键功能执行
	}
}

 

 

扩展:单前台轮询方式实现多按键检测:

if(KEY_IO != 0xFF)		//检测到有按键按下
{
	DelayNms (20);		//延时20毫秒(严重影响单片机的运行效率)
	if (KEY_IO !=0xFF)	//确认按键按下
    {
    	switch (KEY_IO)
    	{
    		case 0xFE: KeyValue=1 ; break;
    		case 0xFD: KeyValue=2 ; break;
    		default: KeyValue=0 ; break;
    	}
    }
}

参考文章:

原文链接:https://blog.csdn.net/weixin_46251230/article/details/126659466

posted @ 2024-09-03 15:22  FBshark  阅读(31)  评论(0编辑  收藏  举报