标题:
51单片机实现按键短按双击长按程序
[打印本页]
作者:
幸福来陪伴
时间:
2023-9-13 14:32
标题:
51单片机实现按键短按双击长按程序
这个程序使用状态机实现长按,双击,短按识别程序,很好的用,欢迎大家参考和指导
/*-----------------------------------------------
名称:按键
------------------------------------------------*/
#include"key.h"
extern unsigned char keyvalue;
unsigned char keyscan()
{
unsigned char keynumber;
if(!KEY1) keynumber = 1; //!!!修改此处,可以增加/减少按键数量
else if(!KEY2) keynumber = 2; //!!!修改此处,可以增加/减少按键数量
else if(!KEY3) keynumber = 3; //!!!修改此处,可以增加/减少按键数量
else if(!KEY4) keynumber = 4; //!!!修改此处,可以增加/减少按键数量
else keynumber = 0;
return keynumber;
}
unsigned char key_multi(void)
{
static uchar key_state; //按键状态变量
static uint key_time; //按键计时变量
static uchar key_press_nums; //按键次数变量
static uint key_time_double; //按键双击时间
static uchar keynum; //键值
static uchar new_keynum; //新的键值
uchar key_press, key_return; //键值和返回值
key_return = None_click; //清除返回按键值
switch(keyscan())
{
case 1:key_press = KEY1;new_keynum = 1;break; //!!!修改此处,可以增加/减少按键数量
case 2:key_press = KEY2;new_keynum = 2;break; //!!!修改此处,可以增加/减少按键数量
case 3:key_press = KEY3;new_keynum = 3;break; //!!!修改此处,可以增加/减少按键数量
case 4:key_press = KEY4;new_keynum = 4;break; //!!!修改此处,可以增加/减少按键数量
default:key_press = 1;break;
}
if(key_press_nums > 0) //按键次数大于0,说明有按键
{
key_time_double++; //是否开始双击计
if(key_time_double >= DOUBLE_KEY_TIME && key_time_double < LONG_KEY_TIME) key_state = KEY_STATE_2;//如果时间到了在双击和长按之间,切换到状态2
}
switch (key_state)
{
case KEY_STATE_0: //按键状态0:判断有无按键按下
{
if (!key_press) //是否有按键按下,没有按下就退出
{
key_time = 0; //清零时间间隔计数
key_state = KEY_STATE_1; //然后进入 按键状态1
}
}break;
case KEY_STATE_1: //按键状态1:软件消抖(确定按键是否有效,而不是误触)。按键有效的定义:按键持续按下超过设定的消抖时间。
{
if (!key_press)
{
key_time++; //一次10ms
if(key_time>=SINGLE_KEY_TIME) //消抖时间为:SINGLE_KEY_TIME*10ms = 10ms;
{
key_state = KEY_STATE_2; //如果按键时间超过 消抖时间,即判定为按下的按键有效。进入按键状态2,继续判定到底是单击、双击还是长按
key_press_nums++; //按键次数+1
}
}
else key_state = KEY_STATE_0; //如果按键时间没有超过,判定为误触,按键无效,返回 按键状态0,继续等待按键
}break;
case KEY_STATE_2: //按键状态2:判定按键有效的种类:是单击,双击,还是长按
{
if(key_press) //如果按键在 设定的双击时间内释放,则判定为单击/双击
{
if(key_time_double < DOUBLE_KEY_TIME ) key_state = KEY_STATE_0; //双击时间达到前,再次扫描按键,看还有没有按键按下
if(key_time_double >= DOUBLE_KEY_TIME && key_time_double < LONG_KEY_TIME) //达到双击设定时间后,如果时间超过双击的时间则判断按键按下的次数
{
if(key_press_nums == 1) key_return = Single_click + new_keynum*10; //判断只按了1次,返回有效按键值:单击,通过不同的值判断是哪个按键按下的单击
else if(key_press_nums ==2 && new_keynum == keynum) key_return = Double_click + new_keynum*10; //判断按了2次和两次按键按的一样,返回有效按键值:双击,通过不同的值判断是哪个按键按下的双击
key_state = KEY_STATE_0; //返回 按键状态0,继续等待按键
key_press_nums = 0; //清空按键次数
key_time_double = 0; //清空双击计时
}
if(key_time_double >LONG_KEY_TIME ) key_state = KEY_STATE_3; //如果长按之后才松开的,则切换到状态3清0
}
else
{
key_time++; //按键一直按着的话,长按计时
if(key_time >= LONG_KEY_TIME) //如果按键时间超过 设定的长按时间(LONG_KEY_TIME*10ms=80*10ms=800ms), 则判定为 长按
{
key_return = Long_click + new_keynum*10; //返回有效键值值:长按,通过不同的值判断是哪个按键按下的长按了
//key_state = KEY_STATE_3; //去状态3,等待按键释放
}
}
}break;
case KEY_STATE_3: //等待按键释放
{
if (key_press)
{
key_state = KEY_STATE_0; //按键释放后,进入 按键状态0 ,进行下一次按键的判定
key_press_nums = 0; //清空按键次数
key_time_double = 0; //清空双击计时
}
}break;
default:key_state = KEY_STATE_0;break; //特殊情况:key_state是其他值得情况,清零key_state。这种情况一般出现在 没有初始化key_state,第一次执行这个函数的时候
}
keynum = new_keynum; //将新获取的键值赋值给键值
return key_return; //返回 按键值
}
复制代码
作者:
yzwzfyz
时间:
2023-9-15 15:29
要点:做一个计数器CJ来判定长按与短按,CJ的规则如下:
1、CJ计数只发生于定时器的中断服务程序中,每次中断+1,计满不再计,即不回0。
2、CJ计数只发生于键按下的时候,未按下不计。
3、做一个键状态判定触发标记:B_OK,如果键未按下,但CJ<>0,则置B_OK=1,表示是判断键状态的时候了。
4、当B_OK=1,判断键状态的界定法则是:CJ<某个值为短按,CJ>某个值为长按,某个值是多少由你决定。建议事先将长短两个界定值放置在某个寄存器中,这样可以随意变更界定值。
5、状态界定完成后将:B_OK清0、CJ清0以备下次再界定。
双击:只是规定的时间内,发生了两个短按,这不在此叙述了。三击、多击如法炮制。
作者:
tyrl800
时间:
2023-9-17 20:37
这个程序太复杂了
作者:
lids
时间:
2024-7-1 10:56
按键程序这样写太复杂了,你有时间去学学吴坚鸿的程序写法,比你学这些强多了
作者:
swy1232
时间:
2024-7-1 12:13
有没有简单的 程序或者更加详细的说明
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1