应广单片机来说的按键事件及开头和宏定义源码(图)

应广单片机来说的按键事件及开头和宏定义源码(图)

在开始按键扫描0.5s内没有按键操作的情况下,扫描按键会产生以下3种按键事件:

1.长按事件:任何发生一次的长按操作都是长按事件

2.点击事件:1次短按操作后游戏开发素材,2s内没有短按操作

3.双击事件:2次短按间隔

对于盈光单片机,首先是定时器和IO口的配置

void	IO_Init(void)
{
	//----------------------------
	PA		=	0b1111_1111;
	PAC		=	0b1111_1111;	//1:输出   0:输入
	PAPH	=	0b0000_0000;	//1:加上拉 0:不加上拉
	PAPL	=	0b0000_0000;	//1:加下拉 0:不加下拉
	PB		=	0b1111_1110;
	PBC		=	0b1111_1110;
	PBPH	=	0b0000_0001;
	PBPL	=	0b0000_0000;
	PADIER	=	0b0000_0000;	//CS脚及对应T_Key设置为模拟IO(设为0),用上位机时UART_IO设置为数字IO(设为1)
	PBDIER	=	0b0000_0001;
}

使用按钮进行状态控制,首先需要将定义好的引脚设置为单片机的输入。在本例中unity 按钮长按事件贴图笔刷,我使用 PB.0 引脚作为输入端口。

#define KeyOut_PIN PB.0//按键定义

小提示

定时器使用 10ms 延迟

word reload_T16;
void T16_Time(void){
	$ T16M SYSCLK,/4,bit12;  	//T16的时钟源选择,内部的时钟分频器,中断源选择(当选择位由低到高或者由高到低时,发生中断事件);
								//时钟源选择可以选择STOP, SYSCLK, PA4_F, IHRC, EOSC, ILRC, PA0_F;分频器可选择/1, /4, /16, /64
								//中断源可选择BIT8, BIT9, BIT10, BIT11, BIT12, BIT13, BIT14, BIT15
	reload_T16 = 4096 - 100;	//每次进中断为1ms;
			                	//计算公式为 [1/(时钟源/分频器)]*(中断源-reload_T16)=[1/(4M/4)]*(2^12-(4096-1000))=1000us=1ms
	stt16 reload_T16;			//设定计数器初始值reload_T16,当计数器累加超过设定中断源时产生中断;
	$ INTEN T16;				//中断允许寄存器,启用从T16的溢出中断;1:启用,0:停用。
	$ INTRQ T16;				//中断请求寄存器,此位是由硬件置位并由软件清零;1:请求,0:不请求。
								//注:INTEN,INTRQ没有初始值,所以要使用中断前,一定要根据需要设定数据。即使INTEN为0,INTRQ还是会被中断发生源触发。
	$ INTEGS BIT_R;				//T16中断边缘选择,上升缘请求中断为BIT_R,下降缘请求中断为BIT_F;默认为上升缘请求。
	//	设定INTEN、INTRQ的初始值
	INTEN.T16 = 1;				//开T16中断
//	INTEN.T16 = 0;				//关T16中断
	INTRQ.T16 = 0;				//清零INTRQ寄存器。
	ENGINT;						//打开全局中断
}

按钮函数的宏定义为

#define KeyOut_PIN PB.0//按键定义
#define key_no 0  //按键抬起
#define key_click 1//按键按下1次
#define key_double 2//双击按键
#define key_long 3//长按键
extern byte Key_detected;//按键抬起
void key_board(void);

源代码

/*按键函数以及红外触摸函数*/
#include"Keyboard.h"
word key_times=0;//按键时间初始化
byte Key_detected;//返回值,0:按键释放、1:按下按键、2:双击按键、3:长按按键
byte key_state=0;
void key_board(void)
{
	switch (key_state)
	{
	case 0:
		if(KeyOut_PIN==0)
		{
			key_state=1;//按键按下,开始消抖
		}
		break;
	case 1:
		if(KeyOut_PIN==0)
		 {	
			key_times++;
			if(key_times>=5)
			{
			key_times=0;//按键仍处于按下状态,消抖完成
			key_state=2;
			}
		}
		else
		{
			key_times=0;
			key_state=0;//按键在消抖时抬起,恢复初始状态
		}
		break;
	case 2:
		if(KeyOut_PIN==1)//按键抬起
		{
			key_times++;	//消抖
			if(key_times>=5)
			{
				key_times=0;
				key_state=3;
			}
		}
		else
		{
			key_times++;
			if(key_times>=500)//判断长按
			{
				key_times=0;
				key_detected=key_long;
				key_state=4;//返回到按键抬起
			}
		}
		break;
	case 3:
		key_times++;//判断双击
		if(key_times<200)
		{
			if(KeyOut_PIN==0)
			{
				key_detected=key_double;
				key_times=0;
				key_state=4;
			}
		}
		else
		{
			key_detected=key_click;
			key_times=0;
			key_state=4;
		}
		break;
	case 4:					//按键抬起
		if(KeyOut_PIN==1)
		{
			key_state=0;
		}
		break;
	}
}

此函数不会在开始和结束时将引用归零

它在循环调用结束时归零

如有必要

请在开关上执行key_detected=key_no;

因为实际中函数需要判断是单击还是双击,所以双击判断会有一个最小延时。如有需要unity 按钮长按事件,可自行修改!