前言:
在一些例程上的按键扫描函数基本为单按或长按(容易误触)。能不能实现像一些遥控器一样,短按可被识别并输出一次键值,当按键被持续按下超过一定时间后判断为长按,一直输出键值,二者不冲突且不会误触。 本代码只使用了简单的计数实现,无需使用定时器等功能。
/*按键扫描,带单按和长按功能*/
uint16_t read_key(void)
{
static uint8_t key_up=1;
static uint8_t key_value=0; //键值
static uint16_t long_cnt=0; //长按时间判断
if(key_up==1 &&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))
{
vTaskDelay(pdMS_TO_TICKS(10)); //延时10ms
key_up=2; //进入长按判断
if(KEY0==0) {key_value=1; return 1; } //返回一次键值并记录下键值
else if(KEY1==0) {key_value=2; return 2; }
else if(KEY2==0) {key_value=3; return 3; }
else if(WK_UP==1) {key_value=4; return 4; }
else return 0;
}
if((KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)) //只要有按键松开,复位到单按模式
{
key_up=1; //值复位
long_cnt=0;
key_value=0;
}
if(key_up==2 && long_cnt<=10) long_cnt++; //若按下时间过长,判断为长按,返回当前按下键值
if(long_cnt>10) return key_value;
return 0;
}
代码解释:
if(key_up==1 &&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))
{
vTaskDelay(pdMS_TO_TICKS(10)); //延时10ms
key_up=2; //进入长按判断
if(KEY0==0) {key_value=1; return 1; } //返回一次键值并记录下键值
else if(KEY1==0) {key_value=2; return 2; }
else if(KEY2==0) {key_value=3; return 3; }
else if(WK_UP==1) {key_value=4; return 4; }
else return 0;
}
1.当按键第一次被按下时返回一次键值,并且记录下当前的键值key_value,key_up相当于状态,key_up=2即进入到长按判断。
if((KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)) //只要有按键松开,复位到单按模式
{
key_up=1; //值复位
long_cnt=0;
key_value=0;
}
2.当按键松开时,复位所有参数。
if(key_up==2 && long_cnt<=10) long_cnt++; //若按下时间过长,判断为长按,返回当前按下键值
if(long_cnt>10) return key_value;
3.我们使用long_cnt变量进行长按的计数,当这个按键一直被按下时,long_cnt++。当long_cnt超过我们设定的值时,判断为长按,并且函数一直返回按下的键值。
注意
我的代码中long_cnt超过10即判断为长按,这个值主要是根据整个程序的运行速率决定,如果这个值太小,就会出现按一下按键,键值被多次返回的情况,可以适当增大该值,具体需要根据实际需求进行调整。