标题: 单片机C语言单位切换键加长按开关机功能,如何实现? [打印本页]

作者: zhth1979    时间: 2023-1-4 13:47
标题: 单片机C语言单位切换键加长按开关机功能,如何实现?

想实现的功能:unit按键短按单位切换,长按3S开关机。
方法1:此键连到外部中断IO口,开机时短按单位切换,长按时可以关机,关机时短按下降沿触发外部中断也可以开机,基本可以实现想要的功能。但在短按触发外部中断开机时,单位切换也会触发一次,即关机前是单位1,短按开机后会到单位2。


方法2:就是如上图连接,硬件触发开机,unit键不连到外部中断,普通按键接法,只负责短按单位切换,长按关机。关机短按UNIT可以开机,但也会出现单位触发一次,现像与方法1一样.  


以上两种方法都是因为按下unit开机的同时,单位短按也执行了,这样情况如何解决,各路大神快来帮帮小弟吧,这个问题困扰小弟好久了!


下面是单片机按键扫描程序:
void key_scan()
{
        static u8 state=S0,key_time,lastkey;
        u8 key;
       key=PD&0xFF;
         
  switch(state)   //检测状态                              
   {
    case S0:                                    
             if(key!= 0xFF) state = S1;  break;      
               
   case S1:                                   
           if(key==0xFF)        state = S0;               
          else                                 
             {
                 lastkey=key;
                 state=S2;
            }
          break;

   case S2:
    if(key==0xFF)
        {                        
           state = S0;                //判断输入是否为1,为1返回状态0        
           switch(lastkey)
               {
                 case 0x7F:     执行短按任务         break;
                                                                                                        
                case 0xfe:      执行短按任务         break;         //unit短按单位切换
                                                                                    
               case 0xFB:       执行短按任务         break;
                                                                                                
               case 0xBF:       执行短按任务         break;

               case 0xF7:              执行短按任务         break;                        
                                                         
               case 0xEF:             执行短按任务         break;                        
                                         
              default:break;               
               }
       }                        
     else if(++key_time==200)
         {
            key_time=0;
            switch(key)
             {
               case 0xfe:    执行长按任务 break;         // unit不仅连到单片机普通IO,还连到外部中断IO口,开机时长按关机,关机时短按下降沿触发开机。
             }
            state=S3;                                                                                                        
         }      
        break;

  case S3:                                                  
            if(key==0xFF)   state=S0;                                 
      else if(++key_time==5)                                 //否则开始计时,计时结束按键连击
             {
               key_time=0;
               switch(key)
                {
                   case 0x7F:      执行连击任务         break;        
                                                                                                               
                  case 0xFB:      执行连击任务         break;                                                                                                                                                                                                                                                                                                                                                 }
              }
      break;
  }
}


作者: zhth1979    时间: 2023-1-4 14:11
之前也有几位大神指点过,但自己太愚笨,没能实现!
作者: zhaomin253    时间: 2023-1-4 17:01
整几个按键状态,LASTKEY 、NOWKEY,用定时器判断,只有超过500ms才可以给按键状态赋值,这样长按和短按可以分开来
作者: hjc5035    时间: 2023-1-4 18:53
每次判断按键按下就触发定时器TRx=1,并赋初值,再加一个flag计数,再判断按键弹起,若定时溢出就开关机,若没有进入定时中断就功能切换
作者: zhth1979    时间: 2023-1-5 09:33
hjc5035 发表于 2023-1-4 18:53
每次判断按键按下就触发定时器TRx=1,并赋初值,再加一个flag计数,再判断按键弹起,若定时溢出就开关机, ...

这个方法可行,有没有例程,发我一下参考,多谢!
作者: zhth1979    时间: 2023-1-5 09:37
zhaomin253 发表于 2023-1-4 17:01
整几个按键状态,LASTKEY 、NOWKEY,用定时器判断,只有超过500ms才可以给按键状态赋值,这样长按和短按可 ...

长按,短按或短按,连按倒都还好区分,但短按,长按,连按三个放在一起都不太好区分吧?(连按大多是在长按的基础上触发连按)
作者: 人工置顶员    时间: 2023-1-10 14:57
顶一下
作者: ma5ter    时间: 2023-1-10 15:08
弄一个变量判断开关机状态即可
作者: Y_G_G    时间: 2023-1-10 19:59
这是当初我学单片机的时候写的,长按和双击,定时器开启中断
通过在主程序判断标志位来检测是长按还是双击,并调用函数,在调用的函数中清除对应的标志位
大概是这样的
void one_pre_disp()                                                //单击按键处理
{       
        ONE_PRE=0;

...............
}
Timer0_Key.rar (1.33 KB, 下载次数: 10)




作者: lyxing    时间: 2023-1-10 20:31
单一执行,设置一个状态变量,根据当前状态结合按键状态,进行下一步操作。个人喜欢按下则开启定时器计数,松开停止,超过多少时间为判定长按判断。
作者: wulin    时间: 2023-1-11 07:36
zhth1979 发表于 2023-1-5 09:37
长按,短按或短按,连按倒都还好区分,但短按,长按,连按三个放在一起都不太好区分吧?(连按大多是在长 ...

其实一键开关机不需要这么复杂的硬件电路。利用单片机休眠功能即可解决。初次上电自动开机,P3.2作为普通按键使用,短按切换菜单,长按执行菜单下不同任务。只要再加一项菜单,长按打开外部中断,执行睡眠即可关机。在睡眠状态由外部触发唤醒,关闭外部中断,恢复P3.2作为普通按键使用。最多只要在P3.2外接一个1K电阻和1个104电容硬件消抖。




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1