虽然用普通的延时函数能够实现按键长按与短按的判别,但是在实际的工程应用和项目开发中并不好用也不灵活。更多得是借助定时器的间隔定时来计算按键从按下到松开的时间间隔,然后通过判断该时间值来区分按键长按与短按的状态。
在新大陆国赛设备的黑色Zigbee模块上,或者小蜜蜂制作的XMF09B和XMF09C中,按键SW1短按,切换D5灯的开关状态;按键SW1长按,切换D6灯的开关状态。
按键SW1----------P1_2
D5灯-------------P1_3(高电平点亮)
D6灯-------------P1_4(高电平点亮)
【实现思路】
《1》 定义一个变量K_Press,标志按键状态。按键在按下状态时,值为1;按键在松开状态时,值为0。
《2》 定义一个变量count_t,计算按键处在按下状态的时间,也就是K_Press为1时的时间。
《3》 在按键松开后,通过判断count_t的值来区分按键长按与短按状态。
《4》 每处理完一个按键状态,随即将count_t清0。
【实现代码】
#include “ioCC2530.h”
#define D3 P1_0
#define D4 P1_1
#define D5 P1_3
#define D6 P1_4
#define SW1 P1_2
unsigned char K_Press = 0;
unsigned char count_t = 0;
/*=======================简单的延时函数========================*/
void Delay(unsigned int t)
{
while(t--);
}
/*======================端口初始化函数========================*/
void Init_Port()
{
P1SEL &= ~0x1b; //P1_0、P1_1、P1_3和P1_4作为通用I/O端口
P1DIR |= 0x1b; //P1_0、P1_1、P1_3和P1_4端口输出
P1SEL &= ~0x04; //P1_2作为通用I/O端口
P1DIR &= ~0x04; //P1_2端口输入
P1INP &= ~0x04; //P1_2设置为上拉/下拉模式
P2INP &= ~0x40; //P1_2设置为上拉
D3 = 0;
D4 = 0;
D5 = 0;
D6 = 0;
}
/*=======================定时器1初始化========================*/
void Init_Timer1()
{
T1CC0L = 0xd4;
T1CC0H = 0x30; //16MHz时钟,128分频,定时0.1秒
T1CCTL0 |= 0x04; //开启通道0的输出比较模式
T1IE = 1;
EA = 1;
T1CTL = 0x0e; //分频系数是128,模模式
}
/*====================定时器1服务函数========================*/
#pragma vector = T1_VECTOR
__interrupt void TImer1_int()
{
T1STAT &= ~0x20; //清除定时器1的溢出中断标志位
if(K_Press != 0) //按键按下
{
count_t++; //计算按下按下的时间值
}
}
/*====================按键扫描处理函数========================*/
void Scan_Keys()
{
if(SW1 == 0)
{
Delay(100); //去抖动处理
if(SW1 == 0)
{
K_Press = 1; //标志按键正在按下
while(SW1 == 0); //等待按键松开
K_Press = 0; //标志按键已经松开
if(count_t 》 5) //按键长按
{
D6 = ~D6;
}
else //按键短按
{
D5 = ~D5;
}
count_t = 0; //按键计数值清零
}
}
}
/*=========================主函数=============================*/
void main()
{
Init_Port();
Init_TImer1();
while(1)
{
Scan_Keys();
}
}