蓝桥杯电子类单片机组模块——独立按键(长按与短按)

蓝桥杯单片机组对按键模块的考察不仅仅会涉及到普通的按键扫描,还有可能设计到一些按键的高级用法:按下与松开、长短按等。

现在,我们介绍一下按键“长短按”功能的实现方法。

1、要使用独立按键,那么开发板上的J5跳帽必须接到BTN(独立按键)。

2、第二步,大家可以先参考一下标准程序模板(独立按键)的代码块:
http://blog.csdn.net/qq_44629819/article/details/107937826
在本次实验中,我们需要将原先的代码做轻微的变动:

static u8 KEY_STATE=KEY_STATE0; 

将上述代码段中“KEY_STATE”作为外部变量,也就是将代码移植出去

Q:这样做有何目的?
A:有益于我们在主函数里读取到按键状态。

3、我们假设有一个这样的赛题片段:

  • 当S5按下时间长达1s时,视为长按,否则视为短按。
  • S5长按时,led3亮起;S5短按时,led2亮起。
  • 要求其他按键按下时对led模块无任何影响。

如果大家对led模块不是很熟悉,可以先参考一下led模块显示的代码块:
https://blog.csdn.net/qq_44629819/article/details/104498166

4、如下,以标准例程为模板编写独立按键长短按代码块。

#include <STC15F2K60S2.H>
#include "intrins.h"

#define u8 unsigned char
#define u16 unsigned int

#define NO_KEY 0xF0
#define KEY_STATE0 0
#define KEY_STATE1 1
#define KEY_STATE2 2

#define LED0 0x00
#define LED1 0x01
#define LED2 0x01<<1
#define LED3 0x01<<2
#define LED4 0x01<<3
#define LED5 0x01<<4
#define LED6 0x01<<5
#define LED7 0x01<<6
#define LED8 0x01<<7

#define NO_THING 0x00
#define BUZZER 0x40
#define RELAY 0x10
#define BU_RE 0x50

/***************************************本地常量声明**********************************/
u8 code smg_du[]={//标准字库
//   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
    0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e};
u8 code smg_point[]={0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};//0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
u8 code smg_wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//位码
u8 code led_du[]={LED0,LED1,LED2,LED3,LED4,LED5,LED6,LED7,LED8};
u8 code bure_du[]={NO_THING,RELAY,BUZZER,BU_RE};

void Timer0Init(void)		//1毫秒中断@12.0MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x20;		//设置定时初值
	TH0 = 0xD1;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0=1;
	EA=1;
}

/********code_added********/
static u8 key_state=KEY_STATE0;//设置按键状态为全局变量,方便函数外读取。
/********code_added********/
unsigned char key_scan()
{

	u8 key1,key_temp,key_val;
	P30=1;P31=1;P32=1;P33=1;P44=0;
	if(P30==0) key1=0x10;
	if(P31==0) key1=0x20;
	if(P32==0) key1=0x30;
	if(P33==0) key1=0x40;
	if((P30==1)&&(P31==1)&&(P32==1)&&(P33==1)) key1=0xf0;
	key_temp=key1;
	
	switch(key_state)
	{
		case KEY_STATE0:
			if(key_temp!=NO_KEY)
			{	
				key_state=KEY_STATE1;
			}
		break;
		
		case KEY_STATE1:
			if(key_temp==NO_KEY)
			{	
				key_state=KEY_STATE0;
			}
			else
			{
				key_state=KEY_STATE2;
				switch(key_temp)
				{
					case 0x10:key_val=7;break;
					case 0x20:key_val=6;break;
					case 0x30:key_val=5;break;
					case 0x40:key_val=4;break;
				}
			}
		break;
		case KEY_STATE2:
			if(key_temp==NO_KEY)
			{	
				key_state=KEY_STATE0;
			}
		break;
	}
	
	return key_val;
}


bit key_flag=0;//按键读取标志位
u8 key_value;//按键键值
u8 led_choose=0;//LED1灯选择
u8 bure_choose=0;//ULN2003选择
/********code_added********/
bit long_press_bit=0;//长按按键检测标志位
/********code_added********/
void main()
{
	Timer0Init();
	while(1)
	{

		if(key_flag)
		{
			key_flag=0;
			key_value=key_scan();
			switch(key_value)
			{
				case 4:
				led_choose=1;
				bure_choose=0;
					break;

				case 5:
				/********code_added********/
					long_press_bit=1;//打开长按按键检测标志位
				/********code_added********/
					break;
				
				case 6:
				led_choose=3;
				  bure_choose=2;	
				break;
				
				case 7:
				led_choose=4;	
				  bure_choose=3;	
				break;
			}
		}
	}
}

void timer0() interrupt 1 using 1
{
	static u16 key_count=0,display_count=0,i=0;
/********code_added********/
	static u16 long_press_count=0;//长按按键计数变量,从按下开始进行计数
/********code_added********/
	
/***************************************按键定时器中断**********************************/
	key_count++;
	if(key_count==10)
	{
		key_count=0;
		key_flag=1;
	}
/***************************************显示定时器中断**********************************/
	display_count++;
	if(display_count==1)
	{
		P0=~led_du[led_choose];P2=0x80;P2=0x00;
	}
	if(display_count==2)
	{
		P0=bure_du[bure_choose];P2=0xA0;P2=0x00;
	}
	if(display_count==3)
	{
		display_count=0;
		P2=0XE0;P0=~0X00;P2=0X00;
		P2=0XC0;P0=smg_wei[i];P2=0X00;
		P2=0XE0;P0=~smg_du[i];P2=0X00; 
		i++;
		if(i==8) i=0;
	}
		

/********code_added********/
	if((long_press_bit)&&(key_state==KEY_STATE2))//判断长按标志位是否打开并且满足按键未松开   
	{
			long_press_count++;//长按标志位打开,正常计数。
	}	
	else
	{
		long_press_bit=0;//关闭长按标志位(即判定结果为长按)
		if(long_press_count>=1000)//判断长按状态是否满足[1000,无穷)
		{
			led_choose=2;//长按服务函数
			long_press_count=0;//长按键计数赋值为0
		}
		else if((long_press_count>0)&&(long_press_count<1000))//判断长按按下时间是否满足(0,1000)
		{
			led_choose=3;//短按服务函数
			long_press_count=0;//长按键计数赋值为0
		}
	}
/********code_added********/	
			
}

5、附上按键按下与松开的相关链接
http://blog.csdn.net/qq_44629819/article/details/104505443

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Elec Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值