一种单片机按键检测方式

一种单片机按键检测方式

这个是目前自己在使用的按键功能模块,该功能使用定时器定时检测按键状态,避免了使用延时函数方式时会导致的程序卡顿问题。

  • 具有基础的按键检测功能
  • 具有检测按键持续按下和持续松开功能
  • 支持组合键功能

程序内会使用的功能部分

  • 记录按键状态
  • 按键持续时间
  • 持续时间的复位
//.h文件
#ifndef __KEY_SCANF_H__
#define __KEY_SCANF_H__
#include "STC.h"	//单片机头文件

#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
#ifndef ulong
#define ulong unsigned long
#endif


extern uint keep_key1;
extern uint keep_key2;
extern uint keep_key3;
extern uint keep_key4;
//定义操作名,方便调用
#define K1_PRESS 		( old_key1 && !now_key1)	//利用当前按键状态和上一个按键状态来判断按键操作	
#define K1_LEASE 		(!old_key1 &&  now_key1)
#define K1_KEEP_PRESS 	(!now_key1 && keep_key1>10)	//当按键持续存在一段时间时认定为持续
#define K1_KEEP_LEASE 	( now_key1 && keep_key1>10)
#define K1_HAVE_PRESS	(!now_KEY1)
#define K1_HAVE_LEASE	( now_KEY1)

#define K2_PRESS 		( old_key2 && !now_key2)
#define K2_LEASE 		(!old_key2 &&  now_key2)
#define K2_KEEP_PRESS 	(!now_key2 && keep_key2>10)
#define K2_KEEP_LEASE 	( now_key2 && keep_key2>10)
#define K2_HAVE_PRESS	(!now_KEY2)
#define K2_HAVE_LEASE	( now_KEY2)

#define K3_PRESS 		( old_key3 && !now_key3)
#define K3_LEASE 		(!old_key3 &&  now_key3)
#define K3_KEEP_PRESS 	(!now_key3 && keep_key3>10)
#define K3_KEEP_LEASE 	( now_key3 && keep_key3>10)
#define K3_HAVE_PRESS	(!now_KEY3)
#define K3_HAVE_LEASE	( now_KEY3)

#define K4_PRESS 		( old_key4 && !now_key4)
#define K4_LEASE 		(!old_key4 &&  now_key4)
#define K4_KEEP_PRESS 	(!now_key4 && keep_key4>10)
#define K4_KEEP_LEASE 	( now_key4 && keep_key4>10)
#define K4_HAVE_PRESS	(!now_KEY4)
#define K4_HAVE_LEASE	( now_KEY4)

//定义按键io口
sbit K1	=	P1^0
sbit K2	=	P1^1
sbit K3	=	P1^2
sbit K4	=	P1^3

#endif
//.c
#include "key_scanf.h"
//记录按键状态
uchar now_key1,old_key1;
uchar now_key2,old_key2;
uchar now_key3,old_key3;
uchar now_key4,old_key4;
//状态保持时间
uint keep_key1;
uint keep_key2;
uint keep_key3;
uint keep_key4;
void read_key(){
	//读取按键状态
	old_key1=now_key1;now_key1=K1;
	old_key2=now_key2;now_key2=K2;
	old_key3=now_key3;now_key3=K3;
	old_key4=now_key4;now_key4=K4;
	//按键状态改变时,保持时间复位
	if(IN1_PRESS || IN1_LEASE)keep_key1=0;
	if(IN2_PRESS || IN2_LEASE)keep_key2=0;
	if(IN3_PRESS || IN3_LEASE)keep_key3=0;
	if(IN4_PRESS || IN4_LEASE)keep_key4=0;
	//记录保持时间
	if(keep_key1<65535)keep_key1++;
	if(keep_key2<65535)keep_key2++;
	if(keep_key3<65535)keep_key3++;
	if(keep_key4<65535)keep_key4++;
}
void TIM_ISR(void) interrupt 1
{
	read_key();
}
  • 读取字符型按键
    在逻辑上是一样的,所以这里只用一个按键来展示原理
//.h文件
#define K1_CHAR 0x01	//假设是0x01
#define K1_PRESS 		(old_key1!=K1_CHAR && now_key1==K1_CHAR)
#define K1_LEASE 		(old_key1==K1_CHAR && now_key1!=K1_CHAR)
#define K1_KEEP_PRESS 	(now_key1==K1_CHAR && keep_key1>10)
#define K1_KEEP_LEASE 	(now_key1!=K1_CHAR && keep_key1>10)
#define K1_HAVE_PRESS	(now_key1==K1_CHAR)
#define K1_HAVE_LEASE	(now_key1!=K1_CHAR)
extern uint keep_key1;

//.c文件
uchar now_key1,old_key1;
uint keep_key1;
void read_key(){
	old_key1=now_key1;now_key1=read_char();
	
	if(IN1_PRESS || IN1_LEASE)keep_key1=0;
	
	if(keep_key1<65535)keep_key1++;
}
void TIM_ISR(void) interrupt 1
{
	read_key();
}
  • 调用示例
#include "STC.h"
#include "key_scanf.h"
sbit LED1	=	P2^0;
#define ON	0
#define OFF	1
void main(){
	TIM_INIT();//定时器初始化,固定时间刷新按键状态
	while(1){
	//基础功能
		if(IN1_PRESS)LED1=!LED1;	//按键按下
		if(IN1_LEASE)LED1=!LED1;	//按键松开
		if(IN1_KEEP_PRESS)LED1=ON;else LED1=OFF;
		if(IN1_KEEP_LEASE)LED1=OFF;else LED1=ON;
	
	//长按一定的时间
	//判断的数值大小视功能调用时间而定,可以判断一个时间范围允许误差
		if(IN1_HAVE_PRESS && keep_key1==100){LED1=!LED1;}
	//组合键
	/*这个目前实现起来就有点蛋疼了*/
	//按键1和按键2同时按下改变led的状态
		if(IN1_HAVE_PRESS && IN2_HAVE_PRESS && (IN1_PRESS || IN2_PRESS))LED1=!LED1;
		/*3个*/
		if(IN1_HAVE_PRESS && IN2_HAVE_PRESS && IN3_KEEP_PRESS && (IN1_PRESS || IN2_PRESS || IN3_PRESS))LED1=!LED1;
	//先按下按键1再按下按键2(这个仅支持两个有序按下)
		if(IN1_HAVE_PRESS && !IN1_PRESS/*不包括同时按下*/ && IN2_PRESS)LED1=!LED1;

	}
}

叮 +1

#define KEEPLEASE 	0
#define PRESS		1
#define LEASE 		2
#define KEEPPRESS	3

sbit K1=P0^0;
sbit K2=P0^1;
sbit K3=P0^2;

uchar KEY[3];

void KeyScan(){
	KEY[0]=KEY[0]<<1|K1;
	KEY[1]=KEY[1]<<1|K2;
	KEY[2]=KEY[2]<<1|K3;
}

uchar ReadKey(uchar Key){
	return KEY[key-1];
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值