我把马老师的按键状态机改成一个函数,这样可否?
看了马老师那个一个按键,多个功能的帖子。然后自己改成一个函数来实现状态转换,不知道这样做是否合理。在硬件电路上已经测试过了,可以实现。但不知道合不合理???
unsigned char key_driver(void)
{
static unsigned char key_state = KEY_STATE_0;//初始状态
static unsigned char key_time_long = 0; //长按计时
static unsigned char key_time_double = 0; //双击计时
unsigned char key_press; //按下? 判断
unsigned char key_return = N_key;//返回值初始为无键
key_press = key_input; // 读按键I/O电平
switch (key_state)
{
case KEY_STATE_0: // 按键初始态
if (0 == key_press) //当前为低电平
{
key_state = KEY_STATE_1;// 键被按下,状态转换到按键消抖和确认状态
}
break;
case KEY_STATE_1: // 按键消抖与确认态
if (0 == key_press)
{
key_time_long = 0;
key_state = KEY_STATE_2;// 按键仍然处于按下,消抖完成,状态转换到按下键时间的计时状态,但返回的还是无键事件
}
else
{
key_state = KEY_STATE_0;// 按键已抬起,转换到按键初始态。此处完成和实现软件消抖,其实按键的按下和释放都在此消抖的。
}
break;
case KEY_STATE_2:
if(1 == key_press)
{
key_state = KEY_STATE_3; // 转换到下次判断是否双击
key_time_double = 0;
}
else if(++key_time_long >= 100)// 继续按下,计时加10ms(10ms为本函数循环执行间隔)
{
key_return = L_key; // 按下时间>1000ms,此按键为长按操作,返回长键事件
key_state = KEY_STATE_4; // 转换到等待释放状态
}
break;
case KEY_STATE_3:// 此状态判断单击或者双击
if (0 == key_press) // 又一次单击(间隔肯定<500ms)
{
key_return = D_key; // 返回双击键事件,回初始状态
key_state = KEY_STATE_4; //等待按键释放
}
else // 这里500ms内肯定读到的都是无键事件,因为长键>1000ms,在1s前低层返回的都是无键
{
if(++key_time_double >= 50)
{
key_return = S_key; // 500ms内没有再次出现单键事件,返回上一次的单键事件
key_state = KEY_STATE_0; // 返回初始状态
}
}
break;
case KEY_STATE_4: // 等待按键释放状态,此状态只返回无按键事件
if (1 == key_press)
{
key_state = KEY_STATE_0; //按键已释放,转换到按键初始态
}
break;
}
return key_return;
}
沙发,
鼓励 + 有空验证下。 letyoufly 发表于 2014-3-25 13:36
沙发,
鼓励 + 有空验证下。
{:lol:} O(∩_∩)O谢谢 {:mad:}顶一下,来看看这样合理不 感觉挺好的。 当然可以了,扔到定时器中断里面 tragedy 发表于 2014-3-25 23:34
感觉挺好的。
这是我第一次用状态机,所以来看看有没有错误 68336016 发表于 2014-3-25 23:39
当然可以了,扔到定时器中断里面
我定时器一毫秒的,然后在大循环,判断是否10毫秒就检查一次 本帖最后由 68336016 于 2014-3-26 14:32 编辑
jufr12315 发表于 2014-3-26 14:13
我定时器一毫秒的,然后在大循环,判断是否10毫秒就检查一次
只说我个人观点,如果将按键读取放在大循环里面,你觉得方便么?
比如 最简单的几行代码,肯定希望一调用ReadKey()返回就是按键值。如果你还在主循环里面不断设置中断标志来判断ReadKey()的值,那程序结构就很混乱了。
if(ReadKey() == KEY_1)
{
Led_1_ON();
}
if(ReadKey() == KEY_2)
{
Led_2_ON();
}
68336016 发表于 2014-3-26 14:31
只说我个人观点,如果将按键读取放在大循环里面,你觉得方便么?
比如 最简单的几行代码,肯定希望一调用 ...
if (time_10ms_ok) //每10ms执行一次,
{
time_10ms_ok =0;
key = key_read(); //《====== 10ms一次调用按键中间层函数,根据返回键值,点亮不同的LED灯,全面测试按键操作是否正常
if (key == L_key)
........//点亮A_LED,关闭B_LED和C_LED
else if(key == D_key)
........//点亮B_LED,关闭A_LED和C_LED
else if(key == S_key)
........//点亮C_LED,关闭A_LED和B_LED
}
我在大循环这样不行么?参考马老师的帖子的 根据我的经验,不推荐放在定时中断中,至于原因么大家可以讨论一下。任何方法都有优点和不足,要采用最可靠和适合实际需求的。 machao 发表于 2014-3-27 16:30
根据我的经验,不推荐放在定时中断中,至于原因么大家可以讨论一下。任何方法都有优点和不足,要采用最可靠 ...
谢谢马老师的指点。 谢谢分享。。。学习学习
页:
[1]