找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7144|回复: 12
打印 上一主题 下一主题
收起左侧

求指导:按键处理方法,长按3秒进入菜单,长按1秒退出,单击实现其它功能

  [复制链接]
跳转到指定楼层
楼主
想实现如图的功能,具体按键处理方法为:长按3秒进入菜单,长按1秒退出,单击实现其它功能。其中“长按3秒进入菜单,长按1秒退出”一点思路也没有,想了好多办法都没法实现,请各位指导!


按键操作方式.jpg (37.93 KB, 下载次数: 46)

红框内为按键处理方式

红框内为按键处理方式
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:401564 发表于 2020-7-1 17:13 | 只看该作者
如果我没有记错的话,哥们你搞这个“按键”已经快两年了,我记得我说过“两年时间,学一门编程语言都可以了”,更何况只是一个功能而已呢
1:设定一个标志位,用于标志当前是在菜单中,还是已经退出菜单了
2:当按下按键之后,去抖动,一边检测按键有没有松开,一边计时
3:按键松开之后,通过计时时间的长短来判定功能:
A不到1秒,无效,
B如果是已经进入菜单,大于1秒,小于3秒,退出。大于3秒,无效
C如果是没有进入菜单,小于3秒的都无效

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

板凳
ID:91521 发表于 2020-7-1 17:47 | 只看该作者
可是仪表要求的是,按键1秒以上退出“初始设定菜单”,即使按键超过3秒也不会再次触发出现“初始设定菜单”,这是个难点,我曾经在手电筒上见识过类似的设置,一直没能实现,所以反复的发帖,想找到一个编程的方法
回复

使用道具 举报

地板
ID:781892 发表于 2020-7-1 17:58 来自手机 | 只看该作者
Y_G_G 发表于 2020-7-1 17:13
如果我没有记错的话,哥们你搞这个“按键”已经快两年了,我记得我说过“两年时间,学一门编程语言都可以了 ...

按键1秒以上退出“初始设定菜单”,即使按键超过3秒也不会再次触发出现“初始设定菜单”,这是个难点,我曾经在手电筒上见识过类似的设置,一直没能实现,所以反复的发帖,想找到一个编程的方法
回复

使用道具 举报

5#
ID:91521 发表于 2020-7-1 18:44 | 只看该作者
根本不能在按键松开时判断,因为这样无法实现达到三秒立即进入“初始设定菜单”,
回复

使用道具 举报

6#
ID:7209 发表于 2020-7-1 18:59 | 只看该作者
按键按下去开始计时
松开按键返回时间
(这里 需要用到电平反转 中断
  启用定时器
  实际上就是 一键多功能 的实现
你可以查查  ,
)

tiime  = duqu_k1_time(); //读取定时中断中按键按下去的时间
switch(time)
   {
   case 1:  //处理1s 的功能代码  
   baeak;
   case 2:  //处理2s 的功能代码
   break;
   case 3: //处理3s 的功能代码
   break;
  default:  //处理不再按键保持时间功能
  break;

   }
//伪代码
回复

使用道具 举报

7#
ID:401564 发表于 2020-7-1 19:08 | 只看该作者
gl960530484 发表于 2020-7-1 17:58
按键1秒以上退出“初始设定菜单”,即使按键超过3秒也不会再次触发出现“初始设定菜单”,这是个难点,我 ...

按下按键超过3秒就认为是已经达到开机或者其它功能的条件了,然后就调用处理程序,处理玩之后再回来判断按键有没有松开,没有松开就一直等到它松开再进行下一次的检测,这样就不会出现一直按下按键就一直有功能的现象了,我会上传一个LED灯的程序,你试着看一下,我用的是汇编,你要是不会汇编,那就没有办法了
回复

使用道具 举报

8#
ID:401564 发表于 2020-7-1 19:10 | 只看该作者
这是一个已经验证过的汇编程序,双击和长按是开关机,短按是功能切换,你参考一下,如果不会汇编,那就没有办法了 LED V8.0.rar (11.1 KB, 下载次数: 21)
回复

使用道具 举报

9#
ID:213173 发表于 2020-7-1 20:50 | 只看该作者
给你写一个短、中、长按键示例,具体任务自行完善。有详细注释,不难理解。
  1. #include<reg52.h>
  2. sbit LED1=P1^0;
  3. sbit LED2=P1^1;
  4. sbit LED3=P1^2;
  5. sbit key=P1^7;

  6. void Timer0Init()        //10毫秒@12.000MHz
  7. {
  8.         TMOD= 0x01;                //设置定时器模式
  9.         TL0 = 0xF0;                //设置定时初值
  10.         TH0 = 0xD8;                //设置定时初值
  11.         TR0 = 1;                        //定时器0开始计时
  12.         EA  = 1;       //开总中断
  13.         ET0 = 1;       //开T0中断
  14. }

  15. //按键扫描
  16. void keyscan()
  17. {
  18.         static unsigned int time=0;//计数变量
  19.         static bit key_sign=0;                //按键状态标志
  20.         if(!key)//按键按下
  21.         {
  22.                 time++;
  23.                 if(time>300)
  24.                         time=301;//防止溢出
  25.                 if(time>1 && key_sign==0)//10ms消抖
  26.                         key_sign=1;//确认按键按下
  27.                 if(time==300)//判断按下3s有效
  28.                         LED3=~LED3;//任务3
  29.         }
  30.         else //没有按或按下后松手
  31.         {
  32.                 if(key_sign==1)//判断是按键按下后松手
  33.                 {
  34.                         key_sign=0;
  35.                         if(time<100)//小于1s判断短按
  36.                                 LED1=~LED1;//任务1
  37.                         if(time>=100 && time<300)//大于1s有效
  38.                                 LED2=~LED2;//任务2
  39.                 }
  40.                 time=0;
  41.         }
  42. }
  43. //主函数
  44. void main()
  45. {
  46.         Timer0Init();//定时器初始化函数
  47.         while(1)
  48.         {
  49.                 //其它任务
  50.         }
  51. }
  52. //T0中断服务函数
  53. void Timer0Interrupt() interrupt 1
  54. {
  55.         TL0 = 0xF0;                //设置定时初值
  56.         TH0 = 0xD8;                //设置定时初值
  57.         keyscan();                //按键扫描
  58. }
复制代码
回复

使用道具 举报

10#
ID:633559 发表于 2020-7-1 22:41 | 只看该作者
该我出场的时候了,如果人人都献出一份爱~~~,咳咳,我的截图工具今晚不给力啊,只能分两张了

评分

参与人数 1黑币 +40 收起 理由
admin + 40 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

11#
ID:592807 发表于 2020-7-2 11:43 | 只看该作者
daiya 发表于 2020-7-1 18:44
根本不能在按键松开时判断,因为这样无法实现达到三秒立即进入“初始设定菜单”,

3秒和1秒,这么精准的吗?
我按两秒会怎么样?按4秒怎么样?
就不能多弄按键复用吗?按键扫描和处理都要时间,人手按键时间也不精准啊,谁也保证不了。


if(按下按键)
{
   延时500毫秒;
  if(按键松开)//单击  {
      功能1;
  }
else//长按
{
     延时500毫秒;
     if(按键松开)
     {
        功能2;
     }
    延时1500毫秒;
    else
      {
          功能3;
      }
}
}

回复

使用道具 举报

12#
ID:548551 发表于 2020-7-2 17:18 | 只看该作者
我不知道你是学生还是已经在工作了,  如果是学生的话还可以理解.如果是出来工作了不应该一个按键的长短按还弄不清楚啊. 我给你一个程序,上面的注释很清楚 ,如果你还不理解的话就不要做单片机了.这个是我所有项目都那样写的. 有三个点要注意:1  你要用到的那个IO口,也就是按键IO口必须是输入设置,并且打开上拉,2 我的程序是4MS 一个定时. 3 不要用延时程序, 你用了延时程序以后这个就程序读取的电平就不准了, 时间也不准了.
void KEY_SCAN(void)                                        //扫描按键
{
    if(!f_key_press)                                        //判断是按下还是弹起状态 1 按下状态 0 弹起状态
    {
        if(P_KEY){key_cnt=0;}                        // 读取IO口的电平 因为开了上拉,没有按按键的时候读取到的为高 所以只要是高就清零计数
        key_cnt++;                                        // ++
        if(key_cnt>=10)                                        // 连续读取IO口电平10次证明按下按键了, 并且稳定了这也可以理解为消抖
        {
            key_cnt=0;                                        // 清零按键计数 记得你一定要清零
            f_key_press=1;                                //置按下按键标志位 并且置长按按键标志位
            f_key_ctrl=1;                                        // 长按标志位置起来后面要用到
        }
    }
    else                                                        //判断按键是按下还是弹起状态 按下状态 0 弹起状态
    {
        if(!P_KEY){key_cnt=0;}                        //读取IO口电平 ,开上拉的缘故 置要读取到为低就证明还在按下状态中 所以要清零按键计数
        key_cnt++;                                        //++
        if(key_cnt>=10)                                        // 连续读取到10次高电平就证明已经弹起按键了.
        {
            key_cnt=0;                                        // 清零弹起计数
            f_key_press=0;                                //清按下标志位
            // 敲重点  这里仔细看
            if(f_key_ctrl)                                        //去读取这个标志位还在不在, 如果这个标志位不在就说明已经按下有3S了.直接跳过这里.执行下一条命令;
                                                                    //如果这标志位还在就说明按下不到3S ,只能是短按,或者按下1S-3s之间.所以我们要来判断ctrl_cnt的个数                                         
            {
                if(ctrl_cnt>=250)                        //判断之前的计数是多少 如果大于250*4MS =1000MS 就是长按1S的动作,那么执行长按1s的程序就可以了
                {
                        ctrl_cnt=0;                        // 记得判断后要立即清零
                        f_key_1s=1;                        //和f_key_3s一样, 后面去读取这个标志位 有就执行相应动作,没有就不执行
                }
                else                                                //不大于1S就短按  我们执行短按的程序
                {
                        ctrl_cnt=0;
                        f_key_short=1;
                }
             }
             //敲重点因为前面判断了f_key_ctrl标志位还在不在,所以判断完以后一定要清零 ,并且清理的位置不能错
             f_key_ctrl=0;                                // 清零长按标志位               
        }       
    }
    //
    if(f_key_ctrl)                                                // 这个长按只管3S的长按 1 S 的在弹起里面处理
    {
        ctrl_cnt++;                                        // 只要一读取到f_key_ctrl为1 就开始++计数
        if(ctrl_cnt>=750)                                //计数到750*4ms=3000ms 就清零 说明长按3S时间到了
        {
                ctrl_cnt=0;                                // 清零计数
                f_key_ctrl=0;                                // 清零标志位
                f_key_3s=1;                                // 这个标志位是长按3s的标志位,你自己另外写一个函数,然后来读取这个标志位 为1就执行长按3S的动作
                                                                //否则就不执行
        }
     }
     else
     {
        ctrl_cnt=0;
     }
}
void WORK_APP(void)
{
        if(f_key_3s)                        //读取上面按键的标志位 3S
        {
                // 自己添加相应的功能
        }
        else if(f_key_1s)                        // 读取上面按键的标志位1s
        {
                // 自己添加功能
        }
        else if(f_key_short)                // 读取上面短按标志位
        {       
                // 自己添加功能
        }
}
回复

使用道具 举报

13#
ID:91521 发表于 2022-2-4 18:45 | 只看该作者
没有各位想的那么复杂,一个While循环搞定
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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