久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3802|回復: 26
打印 上一主題 下一主題
收起左側

單片機程序 長按關機時會觸發一次短按,如何解決?

  [復制鏈接]
跳轉到指定樓層
樓主
單片機源程序如下:
#define PD 0x22|(P1&0x51)|(P2<<1&0x80)|(P3<<2&0x0c)   /組合5個按鍵為1個字節數據

#define S0 0   //狀態0
#define S1 1   //狀態1
#define S2 2   //狀態2
#define S3 3   //狀態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

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

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

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


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏6 分享淘帖 頂1 踩
回復

使用道具 舉報

沙發
ID:161164 發表于 2022-11-29 09:58 | 只看該作者
要加長按功能,就需要在放開按鍵后才判斷鍵值
回復

使用道具 舉報

板凳
ID:686513 發表于 2022-11-29 11:03 | 只看該作者
lkc8210 發表于 2022-11-29 09:58
要加長按功能,就需要在放開按鍵后才判斷鍵值

佩服,太厲害了!
回復

使用道具 舉報

地板
ID:1001745 發表于 2022-11-29 13:15 | 只看該作者
lkc8210 發表于 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控制端狀態取反
        LED_R = ~LED_R;
   }
   else if(key_val==1)
   {
    HC = ~HC;     //HC控制端狀態取反
        LED_3 = ~LED_3;
   }
   else if(key_val==2)
   {
    FLK = ~FLK;    //閃光控制端口狀態取反
        LED_T = ~LED_T;
   }
    else if(key_val==3)
   {
    FAN = ~FAN;           //手動開啟散熱風扇,連續按3次狀態取反關閉風扇。
        LED_6 = ~LED_6;
   }
   key_val = 0;
  }
}
}
大師,我的這個按鍵程序也有這樣的問題,長按之后就會觸發短按的功能,這個該如何修改?謝謝!
回復

使用道具 舉報

5#
ID:161164 發表于 2022-11-29 13:42 | 只看該作者
mcuhui 發表于 2022-11-29 13:15
void key_pros()
{
if(flag_1ms==1)

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



回復

使用道具 舉報

6#
ID:1001745 發表于 2022-11-29 14:10 | 只看該作者
lkc8210 發表于 2022-11-29 13:42
很熟悉的代碼
長按成立后要把click_count清零
22行也有點問題

謝謝大師指導,小弟不才,這段代碼也是參考論壇上的程序進行修改移植的。
回復

使用道具 舉報

7#
ID:1034262 發表于 2022-11-29 14:37 | 只看該作者
短按釋放執行,按下不執行鍵碼。
回復

使用道具 舉報

8#
ID:686513 發表于 2022-11-30 14:16 | 只看該作者
lkc8210 發表于 2022-11-29 09:58
要加長按功能,就需要在放開按鍵后才判斷鍵值

大師,今天又測試了一下,之前長按松手后會觸發一次短按,按您的代碼修改后,顯示上是對的了,但實際好像還是觸發了一次短按。這個是關機后長按開機發現的,本來我是把上次的單位保存到了EEPROM中,開機后會跳到下個單位。
回復

使用道具 舉報

9#
ID:161164 發表于 2022-11-30 15:55 | 只看該作者
zhth1979 發表于 2022-11-30 14:16
大師,今天又測試了一下,之前長按松手后會觸發一次短按,按您的代碼修改后,顯示上是對的了,但實際好像 ...

試試這樣

回復

使用道具 舉報

10#
ID:686513 發表于 2022-11-30 16:42 | 只看該作者

剛剛試過了,還是不行!
回復

使用道具 舉報

11#
ID:1054812 發表于 2022-11-30 16:51 | 只看該作者
設定一個閾值,鍵按下開始計數,鍵釋放開始判斷:小于閾值為短按,大于閾值為長按
回復

使用道具 舉報

12#
ID:161164 發表于 2022-11-30 17:08 | 只看該作者
zhth1979 發表于 2022-11-30 16:42
剛剛試過了,還是不行!

這樣呢?


回復

使用道具 舉報

13#
ID:213173 發表于 2022-11-30 20:43 | 只看該作者
zhth1979 發表于 2022-11-30 16:42
剛剛試過了,還是不行!

給你一個驗證程序,看懂了就可以自由發揮了。
  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;     //計數變量
  12.         if(!key)   
  13.         {  
  14.                 count++;  
  15.                 if(count==key_L)    //長按
  16.                         LED2=~LED2;     //長按任務
  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;     //短按任務
  24.                 count=0;            //count清0
  25.         }   
  26. }

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

使用道具 舉報

14#
ID:686513 發表于 2022-12-1 08:23 | 只看該作者

仍然不行,我再描述一下:長按關機時不會出現一次短按,長按開機時會出現一次短按。
回復

使用道具 舉報

15#
ID:686513 發表于 2022-12-1 09:04 | 只看該作者
wulin 發表于 2022-11-30 20:43
給你一個驗證程序,看懂了就可以自由發揮了。

這個程序只能識別長按和短按,我還要有連按功能就沒辦法識別了吧?
回復

使用道具 舉報

16#
ID:686513 發表于 2022-12-1 09:17 | 只看該作者
此按鍵掃描功能:短按  長按加連按三種功能!
回復

使用道具 舉報

17#
ID:161164 發表于 2022-12-1 09:26 | 只看該作者
zhth1979 發表于 2022-12-1 08:23
仍然不行,我再描述一下:長按關機時不會出現一次短按,長按開機時會出現一次短按。

長按開機代碼?
回復

使用道具 舉報

18#
ID:686513 發表于 2022-12-1 10:15 | 只看該作者
本帖最后由 zhth1979 于 2022-12-1 10:18 編輯
lkc8210 發表于 2022-12-1 09:26
長按開機代碼?

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

void EX_Int1 (void) interrupt 2       //INT1
{         
Power_Down_F = 1 ;
        
}
回復

使用道具 舉報

19#
ID:686513 發表于 2022-12-3 16:25 | 只看該作者
coody_sz 發表于 2022-11-29 14:37
短按釋放執行,按下不執行鍵碼。

是的,在哪步判斷呢?
回復

使用道具 舉報

20#
ID:1040651 發表于 2024-2-16 21:22 | 只看該作者
遇到了這個問題,找答案的同時自己想到了辦法,在按鍵時檢測長按,松鍵檢測短按,長按條件滿足時 設置一個按鍵保護時間,在松鍵判斷之前判斷一下保護時間,保護時間為0再執行短按判斷,因為一般長按后不會馬上操作
回復

使用道具 舉報

21#
ID:1109793 發表于 2024-2-17 07:59 | 只看該作者
fww223 發表于 2024-2-16 21:22
遇到了這個問題,找答案的同時自己想到了辦法,在按鍵時檢測長按,松鍵檢測短按,長按條件滿足時 設置一個 ...

馬上操作也需要斷開一次的,在識別為長按之后設定一個標志,在斷開時看下沒有標志就是短按,有舊忽略并且清除掉這個標志
回復

使用道具 舉報

22#
ID:1109793 發表于 2024-6-28 18:13 | 只看該作者
按照輸入點處理,下降沿,上升沿,低電平保持,高電平保持,保持中連續觸發
回復

使用道具 舉報

23#
ID:420836 發表于 2024-6-30 01:21 | 只看該作者
判斷鍵盤按下是長按還是短按,必須插入一個按鍵釋放狀態來判斷按鍵是否完成。
回復

使用道具 舉報

24#
ID:329625 發表于 2024-7-1 21:38 | 只看該作者
加上松手檢測與定時器判斷就可以解決了
回復

使用道具 舉報

25#
ID:1127816 發表于 2024-7-2 00:40 來自手機 | 只看該作者
在軟件設計上,可以在長按邏輯執行完畢后,添加一個忽略短按的緩沖時間,在這個時間內不響應任何短按事件。
回復

使用道具 舉報

26#
ID:521990 發表于 2024-7-3 16:34 | 只看該作者
收藏學習
回復

使用道具 舉報

27#
ID:1104510 發表于 2024-7-5 13:47 | 只看該作者
wulin 發表于 2022-11-30 20:43
給你一個驗證程序,看懂了就可以自由發揮了。

大佬  你這個程序很好  效果很贊  我想問下  你那個#define key_S 1100  #define key_L key_S*50   這兩個按鍵按下去的時間時怎么得來的呢?我想要賦值其他的時間數值進去  求告知
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 一区二区高清不卡 | 久久久久久久久久久国产 | 免费高清av | 精品视频免费 | 奇米在线| 中文字幕日韩一区二区 | 国产1区2区在线观看 | 久久久久久网站 | 久久国产成人精品国产成人亚洲 | 男女搞网站| 亚洲五码在线 | 欧美在线视频a | 亚洲精品一区二区三区丝袜 | av大片 | 亚洲三级免费看 | 久久综合久色欧美综合狠狠 | 在线免费av电影 | 4hu最新网址 | 国产成人在线一区二区 | 日韩一二区 | 午夜精品久久久久久久99黑人 | 亚洲精品久久久久久国产精华液 | 国产精品亚洲欧美日韩一区在线 | 欧美成人精品激情在线观看 | 欧美 日韩 国产 成人 在线 | 日本午夜网 | 欧美中文字幕一区二区三区亚洲 | 日韩精品一区二区三区 | 欧美日韩一区二区在线观看 | 国产精品1区2区 | 日韩在线欧美 | 荷兰欧美一级毛片 | 国产97色| 精品在线一区二区 | 国产一级在线观看 | 婷婷久久网| 欧美日韩毛片 | 国产精品亚洲一区 | 毛片久久久 | www.亚洲一区 | 一区二区高清 |