轮子——04

作用:按键检测、示例在10ms任务中通过读取引脚电平进行单击、双击、长按检测。

Key.c

#include "key.h"

/* 10ms task */

T_KEY_STATE KEY_state;
void Key_Scan()
{
	//按下
   if(GPIO_Input_Pin_Data_Get(KEY_PORT,KEY_PIN) == RESET && KEY_state.isRelease != PRESS)  
		 //if(GPIO_ReadInputDataBit(GPIOB,GPIO_PIN_1) == RESET)  
	{
		KEY_state.relieving_shaking++; //消抖
		if(KEY_state.relieving_shaking >= RELIEVE_COUNT && GPIO_Input_Pin_Data_Get(KEY_PORT,KEY_PIN) == RESET)  //30ms
		{
			KEY_state.relieving_shaking = 0;
			KEY_state.idle_gap = 0;
			KEY_state.isRelease = PRESS;
		}
	}
    //释放	
	else if(GPIO_Input_Pin_Data_Get(KEY_PORT,KEY_PIN) == SET && KEY_state.isRelease != RELEASE)
		//else if(GPIO_ReadInputDataBit(GPIOB,GPIO_PIN_1) == SET)
	{
		KEY_state.relieving_shaking++; //消抖
		if(KEY_state.relieving_shaking >= RELIEVE_COUNT && GPIO_Input_Pin_Data_Get(KEY_PORT,KEY_PIN) == SET)    //30ms
		{
			KEY_state.relieving_shaking = 0;
			KEY_state.isRelease = RELEASE;
		}
	}
	
  switch(KEY_state.isRelease)
	{
		case PRESS:
			KEY_state.click_count++;
			if(KEY_state.click_count >= SINGLE_DOUBLE_INTERVAL)
			{
				//KEY_state.lock = UNLOCK;     //长按功能与长按不释放功能应该互斥
				KEY_state.key_action = KEY_LONG_PRESS_NO_RELEASE;
			}
		break;
		case RELEASE:
			
		    
		  if(KEY_state.click_count == 0)
			{
				KEY_state.idle_gap++;
				if(KEY_state.idle_gap >= IDLE_COUNT) //200ms
				{
					KEY_state.idle_gap = 0;
					KEY_state.key_action = KEY_IDLE;
				}
				
			}
			
			if(KEY_state.single_double_flag == 1)
			{
				KEY_state.single_double_interval++;
				if(KEY_state.single_double_interval >= DOUBLT_INTERVAL)  //500ms
				{
					KEY_state.single_double_interval = 0;
					KEY_state.single_double_flag = 0;
					KEY_state.key_action = KEY_SHORT_PRESS;
				  KEY_state.lock = UNLOCK;
				}
		  }
			
			
			if(KEY_state.click_count > 0 && KEY_state.click_count < SINGLE_DOUBLE_INTERVAL) //1s
			{
				KEY_state.click_count = 0;
				
				if(!KEY_state.single_double_flag)
				{
						KEY_state.single_double_flag = 1;       //记录
				}
				else
				{
					  KEY_state.single_double_flag = 0;
					  KEY_state.single_double_interval = 0;
						KEY_state.key_action = KEY_DOUBLE_CLICK;
				   	KEY_state.lock = UNLOCK;
				}
				
				
			}
			if(KEY_state.click_count >= SINGLE_DOUBLE_INTERVAL)
			{
				KEY_state.click_count = 0;
				KEY_state.lock = UNLOCK;
				KEY_state.key_action = KEY_LONG_PRESS;  //长按
			}
		break;
		default:break;
	}
	

	
	
	
}

Key.h

#ifndef __KEY_H__
#define __KEY_H__

#include "main.h"



#define KEY_PORT  GPIOA
#define KEY_PIN   GPIO_PIN_4
#define RELIEVE_COUNT  3            //消抖计数30ms
#define IDLE_COUNT    20            //空闲计数200ms
#define DOUBLT_INTERVAL 50          //双击间隔500ms
#define KEY_LOCK_INTERVAL 50        //按键锁定间隔500ms
#define SINGLE_DOUBLE_INTERVAL 100  //长按和短按的时间1s


enum E_KEY_action{
	KEY_IDLE = 0,                 //空闲
	KEY_SHORT_PRESS,              //短按
	KEY_LONG_PRESS,               //长按
	KEY_DOUBLE_CLICK,             //双击
	KEY_LONG_PRESS_NO_RELEASE,    //长按未抬起
};

enum E_PRESS{
	RELEASE = 0,
	PRESS,
};

enum E_LOCK{
	UNLOCK = 0,
	LOCK,
};

typedef struct{
	uint8_t click_count;
	uint8_t relieving_shaking;
	uint8_t single_double_interval;
	uint8_t single_double_flag;
	uint8_t isRelease;
	uint8_t idle_gap;
	uint8_t key_action;
	uint8_t lock;
	uint8_t key_lock;
	uint8_t key_lock_count;
}T_KEY_STATE;
extern T_KEY_STATE KEY_state;


void Key_Scan(void);

#endif

Task:

void task()
{
	 	//按键每次触发间隔500ms
	if(!KEY_state.key_lock)
	{
		Key_Scan();
	}
	else
	{
		KEY_state.key_lock_count++;
		if(KEY_state.key_lock_count > KEY_LOCK_INTERVAL)  //按键响应后,指定时间内不再响应
		{
			KEY_state.key_lock_count = 0;
			KEY_state.key_lock = UNLOCK; //解锁按键
		}
	}
	
	if(!KEY_state.lock)
	{
		
		switch(KEY_state.key_action)
		{
			case KEY_IDLE:
				break;
			case KEY_SHORT_PRESS:
				KEY_state.lock = LOCK;
			    KEY_state.key_lock = LOCK;     //触发按键上锁
				LOG("KEY_SHORT_PRESS\n");
				break;
			case KEY_LONG_PRESS:
				KEY_state.lock = LOCK;
			  KEY_state.key_lock = LOCK;     //触发按键上锁
				LOG("KEY_LONG_PRESS\n");
				break;
			case KEY_DOUBLE_CLICK:
				KEY_state.lock = LOCK;
			    KEY_state.key_lock = LOCK;     //触发按键上锁
				LOG("KEY_DOUBLE_CLICK\n");
				break;
			case KEY_LONG_PRESS_NO_RELEASE:
				KEY_state.lock = LOCK;
			    KEY_state.key_lock = LOCK;     //触发按键上锁
			    LOG("KEY_LONG_PRESS_NO_RELEASE\n");
				break;
			default:break;
		}
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值