OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2620|回复: 5

4个按键长短按双击检测多种任务判断

[复制链接]

12

主题

44

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2655
金钱
2655
注册时间
2016-4-4
在线时间
226 小时
发表于 2020-2-21 19:40:10 | 显示全部楼层 |阅读模式
30金钱
我现在有4个独立的按键(非矩阵键盘)要求根据按键按下或双击的情况执行不同任务。
如按键234一直按下时:按键1短按执行任务1,按键1双击执行任务2,按键1长按执行任务3;
按键234没按下时:按键1短按执行任务4,按键1双击执行任务5,按键1长按执行任务6;

按键23一起被短按执行任务7;
由于硬件资源不容许最好不用按键中断或者定时器计算延时时间,谢谢

最佳答案

查看完整内容[请看2#楼]

好久没逛开源网,解决楼主的问题需要两步: 1,如何在一个循环体里实现按键状态检测 2,根据当前/上个时刻键值(状态翻转)辨别任务、执行任务。 我手写实现了第一步(无调试过,仅参考)。希望能够帮到你。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

2

帖子

0

精华

初级会员

Rank: 2

积分
50
金钱
50
注册时间
2020-2-22
在线时间
6 小时
发表于 2020-2-21 19:40:11 | 显示全部楼层
好久没逛开源网,解决楼主的问题需要两步:
1,如何在一个循环体里实现按键状态检测
2,根据当前/上个时刻键值(状态翻转)辨别任务、执行任务。
我手写实现了第一步(无调试过,仅参考)。希望能够帮到你。

  1. //键值处理位图
  2. typedef struct demo_pins
  3. {
  4.   int downCtP[6]; //数组每一位代表该键(pin)按下持续时间
  5.   int upCtP[6];   //数组每一位代表该键(pin)弹起持续时间
  6. };
  7. gpioPin pins[6]; //对应每个gpio状态
  8. #define down 1
  9. #define up 0

  10. int fir_works(demo_pins *ps)
  11. {
  12.   int pin_status[6]; //每个键值状态:1长按/2短按/3短弹起/4长弹起
  13.   for (int i = 0; i < 6; ++i)
  14.   {
  15.     if (pins[i] == down)
  16.     {
  17.       if (ps->upCtP[i] != 0)
  18.         --ps->upCtP[i];
  19.       ++ps->downCtP[i];
  20.     }
  21.     else if (pins[i] == up)
  22.     {
  23.       if (ps->downCtP[i] != 0)
  24.         --ps->downCtP[i];
  25.       ++ps->upCtP[i];
  26.     }

  27.     if (ps->downCtP[i] >= 1 && ps->downCtP[i] <= 5 && ps->upCtP[i] >= 1)
  28.     {
  29.       printf("pin:[%d] short down\n", i);
  30.       pin_status[i] = 2;
  31.     }
  32.     if (ps->downCtP[i] >= 5 && ps->upCtP[i] >= 1)
  33.     {
  34.       printf("pin:[%d] long down\n", i);
  35.       pin_status[i] = 1;
  36.     }

  37.     if (ps->upCtP[i] >= 1 && ps->upCtP[i] <= 5 && ps->downCtP[i] >= 1)
  38.     {
  39.       printf("pin:[%d] short up\n", i);
  40.       pin_status[i] = 3;
  41.     }
  42.     if (ps->upCtP[i] >= 5 && ps->downCtP[i] >= 1)
  43.     {
  44.       printf("pin:[%d] long up\n", i);
  45.       pin_status[i] = 4;
  46.     }
  47.   }

  48.   return 0;
  49. }

  50. int main(int argc, char const *argv[])
  51. {
  52.   demo_pins m_ps;
  53.   int re = 0;
  54.   while (1)
  55.   {
  56.     re = fir_works(&m_ps);
  57.     if (re != 0)
  58.     {
  59.       do_works(re);
  60.     }
  61.     else //如执行任务则不进行延时来筛选键值变化
  62.     {
  63.       msleep(50);
  64.     }
  65.   }

  66.   return 0;
  67. }
复制代码
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165475
金钱
165475
注册时间
2010-12-1
在线时间
2115 小时
发表于 2020-2-21 23:21:10 | 显示全部楼层
自己尝试下先
回复

使用道具 举报

12

主题

44

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2655
金钱
2655
注册时间
2016-4-4
在线时间
226 小时
 楼主| 发表于 2020-2-22 20:33:46 | 显示全部楼层
huangjinfa 发表于 2020-2-21 19:40
好久没逛开源网,解决楼主的问题需要两步:
1,如何在一个循环体里实现按键状态检测
2,根据当前/上个时 ...

分先给你吧,不过这是大量c++语法我只擅长c的看着不太明白,而且我想要一份Arduino和stm32通用的程序,太多c++语法不知道能不能塞到Arduino里,能给个c语言版本的吗?
回复

使用道具 举报

0

主题

2

帖子

0

精华

初级会员

Rank: 2

积分
50
金钱
50
注册时间
2020-2-22
在线时间
6 小时
发表于 2020-2-23 15:50:07 | 显示全部楼层
项琦骑象下象棋 发表于 2020-2-22 20:33
分先给你吧,不过这是大量c++语法我只擅长c的看着不太明白,而且我想要一份Arduino和stm32通用的程序,太 ...

这都是c代码把,只不过代码有点多而已,剩下的功能相信你能完成的
回复

使用道具 举报

12

主题

44

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2655
金钱
2655
注册时间
2016-4-4
在线时间
226 小时
 楼主| 发表于 2020-2-24 20:40:57 | 显示全部楼层
huangjinfa 发表于 2020-2-23 15:50
这都是c代码把,只不过代码有点多而已,剩下的功能相信你能完成的

采用你的思想,1.一次性采集3个按键(1不按、0按下)状态,延时。共采集4轮。
2.keystate第5排设置为上一次状态:0不按/1短按/2长按
3.根据每列(每个按键的5个值)的switch码表更新状态值
4.按键0状态值*100+按键1状态值*10+按键2状态值*1输出结果
5.主函数根据结果的switch码表执行不同任务
基本实现多个按键短按长按功能,就是长按的开始容易输出短按信号,怎么改进好难
,另外由于初始变量都是数字变量所以输出结果也是数值只能输出100,10等不能输出010,020前面都是0的否则switch识别不了
无法实现双击功能,加入双击整个判断都混乱了
代码在探索板上已验证,需要联系我
u8 KEYnew_Scan()//按键扫描函数
{         
        static int keystate[5][3]={{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}};
        for (int i = 0; i < 4; i++)
        {       
                keystate[0]=KEY0;
                keystate[1]=KEY1;
                keystate[2]=KEY2;
                delay_ms(200);
        }
        for (int p = 0; p < 3; p++)
        {       
                switch(keystate[4][p]*10000+keystate[0][p]*1000+keystate[1][p]*100+keystate[2][p]*10+keystate[3][p]*1)
                {//每个键值状态:0不按1短按/2长按
                case 0:keystate[4][p]=2;break;
                case 1000:keystate[4][p]=2;break;
                case 100:keystate[4][p]=1;break;
                case 10:keystate[4][p]=1;break;
                case 1:keystate[4][p]=2;break;
                case 1100:keystate[4][p]=1;break;
                case 11:keystate[4][p]=1;break;
                case 110:keystate[4][p]=1;break;
                case 1001:keystate[4][p]=1;break;
                case 1010:keystate[4][p]=1;break;
                case 101:keystate[4][p]=1;break;
                case 1111:keystate[4][p]=0;break;
                case 111:keystate[4][p]=1;break;
                case 1011:keystate[4][p]=1;break;
                case 1101:keystate[4][p]=1;break;
                case 1110:keystate[4][p]=1;break;
               
                case 10000:keystate[4][p]=2;break;
                case 11000:keystate[4][p]=2;break;
                case 10100:keystate[4][p]=1;break;
                case 10010:keystate[4][p]=1;break;
                case 10001:keystate[4][p]=2;break;
                case 11100:keystate[4][p]=1;break;
                case 10011:keystate[4][p]=1;break;
                case 10110:keystate[4][p]=1;break;
                case 11001:keystate[4][p]=1;break;
                case 11010:keystate[4][p]=1;break;
                case 10101:keystate[4][p]=1;break;
                case 11111:keystate[4][p]=0;break;
                case 10111:keystate[4][p]=1;break;
                case 11011:keystate[4][p]=1;break;
                case 11101:keystate[4][p]=1;break;
                case 11110:keystate[4][p]=1;break;
               
                case 20000:keystate[4][p]=2;break;
                case 21000:keystate[4][p]=2;break;
                case 20100:keystate[4][p]=1;break;
                case 20010:keystate[4][p]=1;break;
                case 20001:keystate[4][p]=2;break;
                case 21100:keystate[4][p]=1;break;
                case 20011:keystate[4][p]=2;break;
                case 20110:keystate[4][p]=1;break;
                case 21001:keystate[4][p]=1;break;
                case 21010:keystate[4][p]=1;break;
                case 20101:keystate[4][p]=1;break;
                case 21111:keystate[4][p]=0;break;
                case 20111:keystate[4][p]=2;break;
                case 21011:keystate[4][p]=1;break;
                case 21101:keystate[4][p]=1;break;
                case 21110:keystate[4][p]=1;break;
               
                default :{keystate[4][p]=0;break;}

                }
       
        }

        return keystate[4][0]*100+keystate[4][1]*10+keystate[4][2]*1;
}       


main()//主函数
{
        solve=KEYnew_Scan();
        if(solve!=0)
        {
                switch(solve)     
                {//每个键值状态:0不按1短按/2长按
         case 100:{printf("100");printf("\r\n\r\n");USART_RX_STA=0;break;}
                 case 10:{printf("010");printf("\r\n\r\n");USART_RX_STA=0;break;}
                 case 1:{printf("001");printf("\r\n\r\n");USART_RX_STA=0;break;}
                 case 11:{printf("011");printf("\r\n\r\n");USART_RX_STA=0;break;}
                 case 111:{printf("111");printf("\r\n\r\n");USART_RX_STA=0;break;}
                 case 200:{printf("200");printf("\r\n\r\n");mp3_play(4);printf("\r\n\r\n");USART_RX_STA=0;break;}
                 case 210:{printf("210");printf("\r\n\r\n");USART_RX_STA=0;break;}
                 case 220:{printf("220");printf("\r\n\r\n");USART_RX_STA=0;break;}
               
                 default :{}
                 }                       
        }
                        delay_ms(200);
}


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-7 20:23

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表