打印

思路清晰的长短四按键非阻塞程序

[复制链接]
2309|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
雪山飞狐D|  楼主 | 2018-7-3 23:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 雪山飞狐D 于 2018-7-3 23:32 编辑

       用了按键缓存和定时器10ms时标,IO为上拉状态,检测0为按下。
       Get_Key( )直接在任何位置输出按键, Key_scan()放进定时器中断即可,当然为了减少按键状态,长按键状态计数会在某个很长的时间循环为0。
   
   void Key_scan(void);
   unsigned char Get_Key(void);

volatile unsigned char Key_State=0;   //1,2,3,4 代表短按键状态,11,12,13,14代表长按键状态

xdata unsigned char Key_Buf[3]={0,0,0};

//按键三级缓冲,IO电平为0为按键按下,写入101为K1按下,102为K2,103为K3,104为K4,写入0为按键松开

xdata unsigned long K1_couter=0;  //长按键计时
xdata unsigned long K2_couter=0;
xdata unsigned long K3_couter=0;
xdata unsigned long K4_couter=0;

sbit K1=P4^7;
sbit K2=P4^6;
sbit K3=P4^5;
sbit K4=P3^7;

unsigned char Get_Key(void)    //放入相关主函数获取按键状态
{
   unsigned char Key_temp=0;
        
         EA=0; //关中断防止重入
        
         Key_temp=Key_State;
        
         Key_State=0;  //读取按键后重置状态
         EA=1;
         
         return Key_temp;
        
}        

void Key_scan(void)          //放进定时10ms中断扫描
{

           K1=1;
           K2=1;
           K3=1;
           K4=1;   //IO口先置高//按键按下为IO电平0
                 
        
                 
        if(K1==0)
    {
         K1_couter++;    //按键计时
         Key_Buf[0]=Key_Buf[1];
         Key_Buf[1]=Key_Buf[2];
         Key_Buf[2]=101;        //压入按键缓冲
                                         
      }
         else if(K2==0)
     {
          K2_couter++;
          Key_Buf[0]=Key_Buf[1];
          Key_Buf[1]=Key_Buf[2];
          Key_Buf[2]=102;        //压入按键缓冲
                                         
       }        
           else if(K3==0)
       {
           K3_couter++;
           Key_Buf[0]=Key_Buf[1];
           Key_Buf[1]=Key_Buf[2];
           Key_Buf[2]=103;        //压入按键缓冲
                                         
          }         
           else if(K4==0)
         {
             K4_couter++;
             Key_Buf[0]=Key_Buf[1];
             Key_Buf[1]=Key_Buf[2];
             Key_Buf[2]=104;        //压入按键缓冲
                                         
         }        
           else
         {
             K1_couter=0;   //按键IO为1,重置计时
             K2_couter=0;
             K3_couter=0;   
             K4_couter=0;
             Key_Buf[0]=Key_Buf[1];
             Key_Buf[1]=Key_Buf[2];
             Key_Buf[2]=0;        //压入按键缓冲
                                         
            }         
                                            
            
     if((Key_Buf[0]==101)&&(Key_Buf[1]==101)&&(Key_Buf[2]==0)&&(K1_couter<200))   
//小于2S松手为短按键,检测上升沿为松手
        {
              Key_State=1;
                                          
                                
        }        
                                
   else if((Key_Buf[0]==102)&&(Key_Buf[1]==102)&&(Key_Buf[2]==0)&&(K2_couter<200))
    {
              Key_State=2;
                                    
    }        
                                
   else if((Key_Buf[0]==103)&&(Key_Buf[1]==103)&&(Key_Buf[2]==0)&&(K2_couter<200))
      {
              Key_State=3;
                                         
                                   
       }        
                                
    else if((Key_Buf[0]==104)&&(Key_Buf[1]==104)&&(Key_Buf[2]==0)&&(K2_couter<200))
       {
             Key_State=4;
                                 
      }        
                                
                                
                                       
                                
                                
    else  if((Key_Buf[0]==101)&&(Key_Buf[1]==101)&&(Key_Buf[2]==101)&&(K1_couter>=200))    //大于等于2S未松手为长按键,计数循环长度为unsigned long
     {
             Key_State=1+10;       //11代表K1长按
                                          
                                
       }        
                                
    else if((Key_Buf[0]==102)&&(Key_Buf[1]==102)&&(Key_Buf[2]==102)&&(K2_couter>=200))
      {
              Key_State=2+10;
                                    
       }        
                                
    else if((Key_Buf[0]==103)&&(Key_Buf[1]==103)&&(Key_Buf[2]==103)&&(K3_couter>=200))
     {
          Key_State=3+10;
                                          
                                   
      }        
                                
    else if((Key_Buf[0]==104)&&(Key_Buf[1]==104)&&(Key_Buf[2]==104)&&(K4_couter>=200))
     {
           Key_State=4+10;
                                    
      }        
                                



}



相关帖子

沙发
eydj2008| | 2018-7-4 07:58 | 只看该作者
开始我也是像你这样写 后来
else if(K2[i]==0)
     {
          K2_couter[i]++;
          ...                              
       }  
数组多大 就表示多少个键了,  像你这样如果100个键 代码会很难改的.
相互学习,共同进步

使用特权

评论回复
板凳
chongdongchen| | 2018-7-4 11:22 | 只看该作者
思路清晰的时候,应该把代码也清晰化

使用特权

评论回复
地板
雪山飞狐D|  楼主 | 2018-7-4 17:19 | 只看该作者
eydj2008 发表于 2018-7-4 07:58
开始我也是像你这样写 后来
else if(K2==0)
     {

   呵呵,是的,couter 用数组 更好一点,

使用特权

评论回复
5
iDiy| | 2018-7-4 21:00 | 只看该作者
画个状态机,让思路更清晰。

使用特权

评论回复
6
elelevi| | 2018-7-5 14:39 | 只看该作者
    对啊,光有程序没有说思路啊

使用特权

评论回复
7
雪山飞狐D|  楼主 | 2018-7-5 15:08 | 只看该作者
elelevi 发表于 2018-7-5 14:39
对啊,光有程序没有说思路啊

     别看if分支那么多,其实只有两部分,第一部分每按一次,就把按键存到数组缓存里面,同时计数+1,要检测到松手了没按,就把按键值0写进缓存,同时清零计数器。
    第二部分 if 对当前缓存里面的按键值做判断,两次按下了,然后最后一次是没按,说明进行了松手,计数器小于200(2秒)就认为是短按键松手了,给按键状态赋值
    要是数组里面的三个成员是一样的,表明一直是按下的同一个按键,然后判断计数器大于200(2秒),没有松手(最后一个数组成员不是0),就给按键状态赋值为长按键状态。
    Get_Key( ) 就是读取按键状态函数,函数返回值作为状态输出,把按键状态给提取出来,同时把按键状态变量Key_State 给清0,不清0会有其它逻辑冲突。
    Key_san( ) 就不用解释了把。。。。

使用特权

评论回复
8
elelevi| | 2018-7-8 08:06 | 只看该作者
雪山飞狐D 发表于 2018-7-5 15:08
别看if分支那么多,其实只有两部分,第一部分每按一次,就把按键存到数组缓存里面,同时计数+1,要 ...

   学习一下,试问,这个代码在片子上用过么?不过网上貌似有代码更精简的程序。

使用特权

评论回复
9
雪山飞狐D|  楼主 | 2018-7-8 14:56 | 只看该作者
elelevi 发表于 2018-7-8 08:06
学习一下,试问,这个代码在片子上用过么?不过网上貌似有代码更精简的程序。 ...

在STC15上写的

使用特权

评论回复
10
cedtek| | 2021-1-7 19:53 | 只看该作者
感谢分享,MARK一下

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

24

主题

3812

帖子

24

粉丝