找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2354|回复: 10
收起左侧

单片机C语言单位切换键加长按开关机功能,如何实现?

  [复制链接]
ID:686513 发表于 2023-1-4 13:47 | 显示全部楼层 |阅读模式
333.png
想实现的功能: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;
  }
}

回复

使用道具 举报

ID:686513 发表于 2023-1-4 14:11 | 显示全部楼层
之前也有几位大神指点过,但自己太愚笨,没能实现!
回复

使用道具 举报

ID:863657 发表于 2023-1-4 17:01 | 显示全部楼层
整几个按键状态,LASTKEY 、NOWKEY,用定时器判断,只有超过500ms才可以给按键状态赋值,这样长按和短按可以分开来
回复

使用道具 举报

ID:1060328 发表于 2023-1-4 18:53 | 显示全部楼层
每次判断按键按下就触发定时器TRx=1,并赋初值,再加一个flag计数,再判断按键弹起,若定时溢出就开关机,若没有进入定时中断就功能切换
回复

使用道具 举报

ID:686513 发表于 2023-1-5 09:33 | 显示全部楼层
hjc5035 发表于 2023-1-4 18:53
每次判断按键按下就触发定时器TRx=1,并赋初值,再加一个flag计数,再判断按键弹起,若定时溢出就开关机, ...

这个方法可行,有没有例程,发我一下参考,多谢!
回复

使用道具 举报

ID:686513 发表于 2023-1-5 09:37 | 显示全部楼层
zhaomin253 发表于 2023-1-4 17:01
整几个按键状态,LASTKEY 、NOWKEY,用定时器判断,只有超过500ms才可以给按键状态赋值,这样长按和短按可 ...

长按,短按或短按,连按倒都还好区分,但短按,长按,连按三个放在一起都不太好区分吧?(连按大多是在长按的基础上触发连按)
回复

使用道具 举报

ID:301191 发表于 2023-1-10 14:57 | 显示全部楼层
顶一下
回复

使用道具 举报

ID:1056056 发表于 2023-1-10 15:08 | 显示全部楼层
弄一个变量判断开关机状态即可
回复

使用道具 举报

ID:401564 发表于 2023-1-10 19:59 | 显示全部楼层
这是当初我学单片机的时候写的,长按和双击,定时器开启中断
通过在主程序判断标志位来检测是长按还是双击,并调用函数,在调用的函数中清除对应的标志位
大概是这样的
void one_pre_disp()                                                //单击按键处理
{       
        ONE_PRE=0;

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

使用道具 举报

ID:67199 发表于 2023-1-10 20:31 | 显示全部楼层
单一执行,设置一个状态变量,根据当前状态结合按键状态,进行下一步操作。个人喜欢按下则开启定时器计数,松开停止,超过多少时间为判定长按判断。
回复

使用道具 举报

ID:213173 发表于 2023-1-11 07:36 | 显示全部楼层
zhth1979 发表于 2023-1-5 09:37
长按,短按或短按,连按倒都还好区分,但短按,长按,连按三个放在一起都不太好区分吧?(连按大多是在长 ...

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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