用状态机写的一个按键程序,死活调不出,大伙帮我看下,问题在哪
就三个按键,设置,加,减每个都要实现长按短按功能。单独调一个的时候是可以的,三个一起就乱了,中断程序里10ms扫一次
/按键
sbit KEY_SET = P1^3;
sbit KEY_UP = P1^2;
sbit KEY_DOWN = P1^0;
//状态机四种状态 按下,松手,确认,松手
#define key_state_0 0 //按下
#define key_state_1 1 //确认
#define key_state_2 2 //计时1 判断长短按
#define key_state_3 3 //松手检测计时
#define set_shot_press 1 //短按
#define set_long_press 2 //长按
#define up_shot_press 3
#define up_long_press 4
#define down_shot_press 5
#define down_long_press 6
uchar keyscan(void)
{
static uchar key_state = 0, key_time = 0;
uchar key_set_press,key_up_press,key_down_press;
uchar key_return = 0;
key_set_press = KEY_SET; // 读按键I/O电平
key_up_press=KEY_UP;
key_down_press=KEY_DOWN;
switch (key_state)
{
case key_state_0: // 按键初始态
if ((!key_set_press) || !(key_up_press)||!(key_down_press))//如果三个键有任何一个按下
key_state = key_state_1; // 状态转换到键确认态
break;
case key_state_1: // 按键确认态,确认哪一个按下
if (!key_set_press)
{
set_down=true; //确认是set 键,标志位
key_state = key_state_2; // 按键仍按下,状态转换到计时1
key_time = 0; // 清另按键时间计数器
}
else if (!key_up_press)
{
up_down=true;
key_state = key_state_2;
key_time = 0;
}
else if(!key_down_press)
{
down_down=true;
key_state = key_state_2;
key_time = 0;
}
elsekey_state = key_state_0; // 按键已抬起,转换到按键初始态
break;
case key_state_2://检测是否松开
if (key_set_press&&set_down)//set按下过,现在已抬起
{
key_state = key_state_0; // 换到按键初始态
key_return = set_shot_press; //判断为短按 1
}
else if (++key_time >= 200&&set_down) //按下时间>2s
{
key_state = key_state_0;
key_time = 0; // 清按键计数器
key_return = set_long_press;// 判断为长按 2
}
//-------------------------------------------
if (key_up_press&&up_down)
{
key_state = key_state_0;
key_return = up_shot_press;
}
else if (++key_time >= 200)
{
key_state = key_state_0;
key_time = 0;
key_return = up_long_press;
}
//----------------------------------------------------
if (key_set_press&&down_down)
{
key_state = key_state_0;
key_return = down_shot_press;
}
else if (++key_time >= 200)
{
key_state = key_state_0;
key_time = 0;
key_return = down_long_press;
}
break;
}
return key_return;
} 单独一个按键的程序
uchar keyscan(void)
{
static uchar key_state = 0, key_time = 0;
uchar key_set_press,key_up_press,key_down_press;
uchar key_return = 0;
key_set_press = KEY_SET; // 读按键I/O电平
key_up_press=KEY_UP;
key_down_press=KEY_DOWN;
switch (key_state)
{
case key_state_0: // 按键初始态
if (!key_set_press)如果三个键有任何一个按下
key_state = key_state_1; // 状态转换到键确认态
break;
case key_state_1: // 按键确认态,确认哪一个按下
if (!key_set_press)
{
key_state = key_state_2; // 按键仍按下,状态转换到计时1
key_time = 0; // 清另按键时间计数器
}
elsekey_state = key_state_0; // 按键已抬起,转换到按键初始态
break;
case key_state_2://检测是否松开
if (key_set_press)//现在已抬起
{
key_state = key_state_0; // 换到按键初始态
key_return = set_shot_press; //判断为短按 1
}
else if (++key_time >= 200) //按下时间>2s
{
key_state = key_state_0;
key_time = 0; // 清按键计数器
key_return = set_long_press;// 判断为长按 2
}
break;
}
return key_return;
}
这是单个按键的程序,很正常,三个一起做我就不会了,请大家指点下吧 回复【1楼】zhuyi2576
-----------------------------------------------------------------------
楼主,不知道你的问题解决了吗?我在使用状态机的时候和你也出现同样的问题。一个按键的时候好用,当做三个按键的时候,就出现问题,无法返回值。我在keil下写的,debug的时候正常。。写进去就不对。你是怎么解决的呢? 以下蓝色文字由版主:Gorgon Meducer 于:2010-05-31,13:49:25 加入。<font color=black>请发贴人注意:本贴放在这分区不合适,即将移走
原来分区:AVR32技术论坛
即将移去的分区:AVR (原ourAVR.com) 技术论坛
移动执行时间:自本贴发表0小时后
任何的疑问或咨询,请可随时联系站长。谢谢你的支持!</font> 少见,傻孩子发帖居然也被移走了。 回复【4楼】ningsane
少见,傻孩子发帖居然也被移走了。
-----------------------------------------------------------------------
是傻孩子移帖,不是被移 下载了,谢谢楼主的分享!!!!!!!!! tangly2017 发表于 2018-1-6 15:09
下载了,谢谢楼主的分享!!!!!!!!!
是我瞎了吗,哪有下载链接,这水灌的。。。 tangly2017 发表于 2018-1-6 15:09
下载了,谢谢楼主的分享!!!!!!!!!
三个按键的状态机对按键判断怎么弄这个我也不会,可以提一下思路吗? bingshuihuo888 发表于 2019-4-24 08:00
三个按键的状态机对按键判断怎么弄这个我也不会,可以提一下思路吗? ...
楼主的程序有三个变量(set_down,up_down,down_down)没交代,看起来应该是全局bool变量,也可以做为静态变量加入子程序中。问题也就出在这几个变量置位之后没清零,应该在设置短按或长按返回值后清零。另外就是长按计时不能在按键松开之前清零,状态机也要在按键松开之后才能重置。
zmh169 发表于 2019-4-24 14:14
楼主的程序有三个变量(set_down,up_down,down_down)没交代,看起来应该是全局bool变量,也可以做为静 ...
有三个按键的程序可以指导一下吗?
对于三个按键的我不指导状态机应该怎么写,怎么去判读他们状态 一个按键的 看起来写没有问题多个按键就不指导怎么弄了 本帖最后由 zmh169 于 2019-4-24 15:33 编辑
bingshuihuo888 发表于 2019-4-24 15:14
有三个按键的程序可以指导一下吗?
对于三个按键的我不指导状态机应该怎么写,怎么去判读他们状态 ...
我把楼主程序修改了一下,理论上应该没问题,没调试验证过,供参考。按键按下端口拉低,没考虑多键同时按下的情况。
//按键
sbit KEY_SET = P1^3;
sbit KEY_UP = P1^2;
sbit KEY_DOWN = P1^0;
//状态机3种状态:按下,确认,松手
#define key_state_0 0 //按下
#define key_state_1 1 //确认
#define key_state_2 2 //计时 判断长短按
#define set_short_press 1 //短按
#define set_long_press 2 //长按
#define up_short_press 3
#define up_long_press 4
#define down_short_press 5
#define down_long_press 6
uchar keyscan(void)
{
static uchar key_state = 0, key_time = 0;
static bool set_down = false, up_down = false, down_down = false;
uchar key_set_press,key_up_press,key_down_press;
uchar key_return = 0;
key_set_press = KEY_SET; // 读按键I/O电平
key_up_press = KEY_UP;
key_down_press = KEY_DOWN;
switch (key_state)
{
case key_state_0: // 按键初始态
set_down = false;
up_down = false;
down_down = false;
key_time = 0; // 清零按键时间计数器
if ((!key_set_press) || (!key_up_press)|| (!key_down_press))//如果三个键有任何一个按下
{
key_state = key_state_1; // 状态转换到键确认态
if (!key_set_press)
{
set_down=true; //确认是set 键,标志位
}
else if (!key_up_press)
{
up_down=true;
}
else if(!key_down_press)
{
down_down=true;
}
}
break;
case key_state_1: // 按键确认态
if ( (!key_set_press && set_down) ||
(!key_up_press && up_down) ||
(!key_down_press && down_down) )
{
key_state = key_state_2;
}
else
{
key_state = key_state_0; // 按键已抬起,转换到按键初始态
}
break;
case key_state_2: //检测是否长按
if( (!key_set_press&&set_down) ||
(!key_up_press&&up_down) ||
(!key_down_press&&down_down) )
{
if (key_time < 255) //避免计时器溢出
{
key_time ++;
}
if(key_time >= 200) //按下时间>=2s,判断为长按
{
if (!key_set_press&&set_down)
{
key_return = set_long_press;
}
//-------------------------------------------
else if (!key_up_press&&up_down)
{
key_return = up_long_press;
}
//----------------------------------------------------
else if (!key_down_press&&down_down)
{
key_return = down_long_press;
}
}
}
else
{
if(key_time < 200)//按下过,现在已抬起, 判断为短按
{
if (key_set_press&&set_down)
{
key_return = set_short_press;
}
//-------------------------------------------
else if (key_up_press&&up_down)
{
key_return = up_short_press;
}
//----------------------------------------------------
else if (key_down_press&&down_down)
{
key_return = down_short_press;
}
}
else //长按结束,判定为无按键按下
{
key_return = 0;
}
key_state = key_state_0; // 换到按键初始态
}
break;
}
return key_return;
} 感谢你啊 我在细细研究一下,感谢指导
页:
[1]