標(biāo)題: 單片機(jī)程序 長按關(guān)機(jī)時(shí)會(huì)觸發(fā)一次短按,如何解決? [打印本頁]

作者: zhth1979    時(shí)間: 2022-11-29 09:10
標(biāo)題: 單片機(jī)程序 長按關(guān)機(jī)時(shí)會(huì)觸發(fā)一次短按,如何解決?
單片機(jī)源程序如下:
#define PD 0x22|(P1&0x51)|(P2<<1&0x80)|(P3<<2&0x0c)   /組合5個(gè)按鍵為1個(gè)字節(jié)數(shù)據(jù)

#define S0 0   //狀態(tài)0
#define S1 1   //狀態(tài)1
#define S2 2   //狀態(tài)2
#define S3 3   //狀態(tài)3

sbit up   = P2^6;   //0111 1111  7f
sbit unit = P1^0;   //1111 1110  fe
sbit down = P3^0;   //1111 1011  fb
sbit md   = P1^6;   //1011 1111  bf
sbit k5   = P3^1;   //1111 0111  f7
sbit k6   = P1^4;   //1110 1111  ef

/*******************************************************************************
* 文件名:按鍵函數(shù)
* 描  述:
* 功  能:
* 參  數(shù):無
*******************************************************************************/        
void key_scan()
{
      bit kflag;
     static u8 state=S0,key_time;
     u8 key;
     key=PD&0xFF;                                
     switch(state)   //檢測(cè)狀態(tài)                              
         {
         case S0:                                                    //狀態(tài)0
                 if(key!= 0xFF) state = S1; break;        
               
        case S1:                                                     //狀態(tài)1
                if(key==0xFF) state = S0;                  //判斷輸入是否為1,為1返回狀態(tài)0
                else                                                 //否則,轉(zhuǎn)入狀態(tài)2,執(zhí)行按鍵程序
                  {
                    state=S2;                                   //按鍵按下執(zhí)行短按操作
                    switch(key)
                         {
                         case 0x7F:      加鍵     break;
                                                                                                        
                        case 0xfe:       單位切換    break;        
                                       
                         case 0xFB:      減鍵     break;
                                                        
                         case 0xBF:     執(zhí)行任務(wù)      break;
                                                
                         case 0xF7:   執(zhí)行任務(wù)     break;
                                 
                         case 0xEF:    執(zhí)行任務(wù)      break;        
                         default:break;               
                         }
                }
              break;

  case S2:                                                            //狀態(tài)2
     if(key==0xFF) state = S0;                              //判斷輸入是否為1,為1返回狀態(tài)0
     else if(++key_time==200)                          //按下時(shí)間等于200時(shí)為長按,轉(zhuǎn)入狀態(tài)3
          {
              key_time=0;state=S3;                                                                       
          }      
                 break;

  case S3:                                                  //狀態(tài)3
     if(key==0xFF)    state=S0;                               //判斷輸入是否為1,為1返回狀態(tài)0                                         
     else if(++key_time==5)                                 //否則開始計(jì)時(shí),計(jì)時(shí)結(jié)束按鍵連擊
       {
         key_time=0;
        switch(key)
          {
             case 0x7F:        執(zhí)行任務(wù)                  break;                                                         
             case 0xfe:        單位切換+長按開關(guān)機(jī)   break;      //短按切換單位,長按開關(guān)機(jī)。長按開機(jī)或關(guān)機(jī)后都會(huì)跟隨一次短按,如關(guān)機(jī)前是P單位,再次開機(jī)后不會(huì)在P單位,而是P下一個(gè)單位K.(此鍵放在這個(gè)位置是不對(duì)的,這里是連按識(shí)別,應(yīng)該放在長按識(shí)別里的。)
             case 0xFB:       執(zhí)行任務(wù)                    break;                                                                                                                                                                                                                                                                                
          }
      }
      break;
  }
紅色標(biāo)注部分如何解決?在網(wǎng)上查了下,是不是要加個(gè)自鎖標(biāo)志?



作者: lkc8210    時(shí)間: 2022-11-29 09:58
要加長按功能,就需要在放開按鍵后才判斷鍵值

作者: zhth1979    時(shí)間: 2022-11-29 11:03
lkc8210 發(fā)表于 2022-11-29 09:58
要加長按功能,就需要在放開按鍵后才判斷鍵值

佩服,太厲害了!
作者: mcuhui    時(shí)間: 2022-11-29 13:15
lkc8210 發(fā)表于 2022-11-29 09:58
要加長按功能,就需要在放開按鍵后才判斷鍵值

void key_pros()
{
if(flag_1ms==1)
{
  flag_1ms = 0;
  if(key1==0)           //判斷模式按鍵是否按下
  {
   if(press_delay<0xffff)press_delay++;
   if(press_delay==20)                 //20ms消抖處理
   {
    click_count++;
   }
   if(press_delay==3000)
   {
    key_val = 10;
   }
   release_delay = 0;
  }
  else
  {
   if(press_delay<0xff)release_delay++;
   if(release_delay==200)
   if(press_delay<3000)
   {
    key_val = click_count;
        click_count = 0;
   }
   press_delay = 0;
  }
  if(key_val > 0)         //若有按鍵按下
  {
   if(key_val==10)         //長按1.5s
   {
    EN = ~EN;      //HG控制端狀態(tài)取反
        LED_R = ~LED_R;
   }
   else if(key_val==1)
   {
    HC = ~HC;     //HC控制端狀態(tài)取反
        LED_3 = ~LED_3;
   }
   else if(key_val==2)
   {
    FLK = ~FLK;    //閃光控制端口狀態(tài)取反
        LED_T = ~LED_T;
   }
    else if(key_val==3)
   {
    FAN = ~FAN;           //手動(dòng)開啟散熱風(fēng)扇,連續(xù)按3次狀態(tài)取反關(guān)閉風(fēng)扇。
        LED_6 = ~LED_6;
   }
   key_val = 0;
  }
}
}
大師,我的這個(gè)按鍵程序也有這樣的問題,長按之后就會(huì)觸發(fā)短按的功能,這個(gè)該如何修改?謝謝!
作者: lkc8210    時(shí)間: 2022-11-29 13:42
mcuhui 發(fā)表于 2022-11-29 13:15
void key_pros()
{
if(flag_1ms==1)

很熟悉的代碼
長按成立后要把click_count清零
22行也有點(diǎn)問題




作者: mcuhui    時(shí)間: 2022-11-29 14:10
lkc8210 發(fā)表于 2022-11-29 13:42
很熟悉的代碼
長按成立后要把click_count清零
22行也有點(diǎn)問題

謝謝大師指導(dǎo),小弟不才,這段代碼也是參考論壇上的程序進(jìn)行修改移植的。
作者: coody_sz    時(shí)間: 2022-11-29 14:37
短按釋放執(zhí)行,按下不執(zhí)行鍵碼。
作者: zhth1979    時(shí)間: 2022-11-30 14:16
lkc8210 發(fā)表于 2022-11-29 09:58
要加長按功能,就需要在放開按鍵后才判斷鍵值

大師,今天又測(cè)試了一下,之前長按松手后會(huì)觸發(fā)一次短按,按您的代碼修改后,顯示上是對(duì)的了,但實(shí)際好像還是觸發(fā)了一次短按。這個(gè)是關(guān)機(jī)后長按開機(jī)發(fā)現(xiàn)的,本來我是把上次的單位保存到了EEPROM中,開機(jī)后會(huì)跳到下個(gè)單位。
作者: lkc8210    時(shí)間: 2022-11-30 15:55
zhth1979 發(fā)表于 2022-11-30 14:16
大師,今天又測(cè)試了一下,之前長按松手后會(huì)觸發(fā)一次短按,按您的代碼修改后,顯示上是對(duì)的了,但實(shí)際好像 ...

試試這樣


作者: zhth1979    時(shí)間: 2022-11-30 16:42
lkc8210 發(fā)表于 2022-11-30 15:55
試試這樣

剛剛試過了,還是不行!
作者: wycdd    時(shí)間: 2022-11-30 16:51
設(shè)定一個(gè)閾值,鍵按下開始計(jì)數(shù),鍵釋放開始判斷:小于閾值為短按,大于閾值為長按
作者: lkc8210    時(shí)間: 2022-11-30 17:08
zhth1979 發(fā)表于 2022-11-30 16:42
剛剛試過了,還是不行!

這樣呢?



作者: wulin    時(shí)間: 2022-11-30 20:43
zhth1979 發(fā)表于 2022-11-30 16:42
剛剛試過了,還是不行!

給你一個(gè)驗(yàn)證程序,看懂了就可以自由發(fā)揮了。
  1. #include <REG51.H>
  2. #define uint unsigned int
  3. #define uchar unsigned char
  4. #define key_S 1100           //宏定義短按(約20ms)
  5. #define key_L key_S*50       //宏定義長按(約1s)

  6. sbit key=P3^6;
  7. sbit LED1=P1^0;
  8. sbit LED2=P1^4;

  9. void keyscan()               //按鍵掃描
  10. {
  11.         static uint count=0;     //計(jì)數(shù)變量
  12.         if(!key)   
  13.         {  
  14.                 count++;  
  15.                 if(count==key_L)    //長按
  16.                         LED2=~LED2;     //長按任務(wù)
  17.                 if(count>key_L)     //防止count溢出
  18.                         count=key_L+1;         
  19.         }  
  20.         else                    //按鍵抬起
  21.         {  
  22.                 if(count>key_S && count<key_L)//短按
  23.                         LED1=~LED1;     //短按任務(wù)
  24.                 count=0;            //count清0
  25.         }   
  26. }

  27. void main()
  28. {
  29.         while(1)
  30.         {
  31.                 keyscan();
  32.         }
  33. }
復(fù)制代碼

作者: zhth1979    時(shí)間: 2022-12-1 08:23
lkc8210 發(fā)表于 2022-11-30 17:08
這樣呢?

仍然不行,我再描述一下:長按關(guān)機(jī)時(shí)不會(huì)出現(xiàn)一次短按,長按開機(jī)時(shí)會(huì)出現(xiàn)一次短按。
作者: zhth1979    時(shí)間: 2022-12-1 09:04
wulin 發(fā)表于 2022-11-30 20:43
給你一個(gè)驗(yàn)證程序,看懂了就可以自由發(fā)揮了。

這個(gè)程序只能識(shí)別長按和短按,我還要有連按功能就沒辦法識(shí)別了吧?
作者: zhth1979    時(shí)間: 2022-12-1 09:17
此按鍵掃描功能:短按  長按加連按三種功能!
作者: lkc8210    時(shí)間: 2022-12-1 09:26
zhth1979 發(fā)表于 2022-12-1 08:23
仍然不行,我再描述一下:長按關(guān)機(jī)時(shí)不會(huì)出現(xiàn)一次短按,長按開機(jī)時(shí)會(huì)出現(xiàn)一次短按。

長按開機(jī)代碼?
作者: zhth1979    時(shí)間: 2022-12-1 10:15
本帖最后由 zhth1979 于 2022-12-1 10:18 編輯
lkc8210 發(fā)表于 2022-12-1 09:26
長按開機(jī)代碼?

可能我描述的不清楚,case 0xfe  這個(gè)鍵短按是單位切換長按是開關(guān)機(jī),放在S3這個(gè)狀態(tài)里是不對(duì)的,這里是連按識(shí)別,應(yīng)該放在長按識(shí)別里的(else if(++key_time==200) 這個(gè)地方的,但這個(gè)地方我沒法判斷長按抬起,所以后面直接放到了連按里了,問題應(yīng)該出在這  )。開機(jī)代碼就是在休眠前開個(gè)外部中斷,這個(gè)鍵我連到外部中斷1上了,按下會(huì)進(jìn)中斷,中斷里退出休眠,關(guān)機(jī)是這個(gè)鍵長按直接給Low_Power賦值,這個(gè)值是大于77,所以就直接休眠了。
//休眠 ---------------------------------------------------------------------------------------------                                                
  if(XmCnt==1)
                {
                 if(T1Cnt == 0)                        
                          {
                                 Low_Power ++;        
                                }        
      else
                          {                        
                                 Low_Power = 0;
                          }        
                }                                
                 if(Low_Power > 77)
                      {        
           IT1=1;
           EX1=1;
                                                
                                         ET0=0;
                                         ET1=0;
                                         EIE &= 0xfb;        //關(guān)閉SG ADC 中斷
                                                                        
                        //確保關(guān)閉24位-ADC
                                PD_CON    = 0x02;                                //解鎖P2 解鎖sgadcon,sgadcon2; 并確保關(guān)閉LDO;        
                                SGADCON &= 0x3f;                                //關(guān)閉24ADC
                                
                        //配置低漏電模式:
                                PCON2  &= 0xfe;                                //解鎖PD_CON2\PD_CON3
                                PCON2  = 0x00;                                //確保PD_CON2為默認(rèn)值
                        //通過PCON3來配置STOP2的休眠模式
                                WD_TA = 0x05;
                                WD_TA = 0x0a;
                                PCON3  = 0xf3;                                //0xf3 1111 0011 STOP2: por_high_en同步關(guān)閉; 允許關(guān)閉PDM2; 不關(guān)閉PDM1; 關(guān)閉看門狗; 數(shù)字LDO切換到低功耗;
                                                
                                        P0 = 0xff;P1 = 0xff;P2 = 0xff;
                                        P3 = 0xff;P4 = 0xff;         
                                        md1=0;                 
                                                
                                 _nop_();
                                        PCON |= 0x00;                        //進(jìn)入休眠模式
                                 _nop_();
          Power_Down_F = 0;                                         
                      //-- 關(guān)機(jī) : 等待外部中斷喚醒 ---         
                while(1)
                          {
                                  if(Power_Down_F)        
                                //        PCON |= 0x40;
                      PCON        = 0x0C;        
                          }
                   }        
   }
}

void EX_Int1 (void) interrupt 2       //INT1
{         
Power_Down_F = 1 ;
        
}
作者: zhth1979    時(shí)間: 2022-12-3 16:25
coody_sz 發(fā)表于 2022-11-29 14:37
短按釋放執(zhí)行,按下不執(zhí)行鍵碼。

是的,在哪步判斷呢?
作者: fww223    時(shí)間: 2024-2-16 21:22
遇到了這個(gè)問題,找答案的同時(shí)自己想到了辦法,在按鍵時(shí)檢測(cè)長按,松鍵檢測(cè)短按,長按條件滿足時(shí) 設(shè)置一個(gè)按鍵保護(hù)時(shí)間,在松鍵判斷之前判斷一下保護(hù)時(shí)間,保護(hù)時(shí)間為0再執(zhí)行短按判斷,因?yàn)橐话汩L按后不會(huì)馬上操作
作者: xiaobendan001    時(shí)間: 2024-2-17 07:59
fww223 發(fā)表于 2024-2-16 21:22
遇到了這個(gè)問題,找答案的同時(shí)自己想到了辦法,在按鍵時(shí)檢測(cè)長按,松鍵檢測(cè)短按,長按條件滿足時(shí) 設(shè)置一個(gè) ...

馬上操作也需要斷開一次的,在識(shí)別為長按之后設(shè)定一個(gè)標(biāo)志,在斷開時(shí)看下沒有標(biāo)志就是短按,有舊忽略并且清除掉這個(gè)標(biāo)志
作者: xiaobendan001    時(shí)間: 2024-6-28 18:13
按照輸入點(diǎn)處理,下降沿,上升沿,低電平保持,高電平保持,保持中連續(xù)觸發(fā)
作者: TTQ001    時(shí)間: 2024-6-30 01:21
判斷鍵盤按下是長按還是短按,必須插入一個(gè)按鍵釋放狀態(tài)來判斷按鍵是否完成。
作者: 17337161031    時(shí)間: 2024-7-1 21:38
加上松手檢測(cè)與定時(shí)器判斷就可以解決了
作者: 3205563085    時(shí)間: 2024-7-2 00:40
在軟件設(shè)計(jì)上,可以在長按邏輯執(zhí)行完畢后,添加一個(gè)忽略短按的緩沖時(shí)間,在這個(gè)時(shí)間內(nèi)不響應(yīng)任何短按事件。
作者: ljfljfljf321    時(shí)間: 2024-7-3 16:34
收藏學(xué)習(xí)
作者: 鄭效桂    時(shí)間: 2024-7-5 13:47
wulin 發(fā)表于 2022-11-30 20:43
給你一個(gè)驗(yàn)證程序,看懂了就可以自由發(fā)揮了。

大佬  你這個(gè)程序很好  效果很贊  我想問下  你那個(gè)#define key_S 1100  #define key_L key_S*50   這兩個(gè)按鍵按下去的時(shí)間時(shí)怎么得來的呢?我想要賦值其他的時(shí)間數(shù)值進(jìn)去  求告知




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1