找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 5002|回復(fù): 14
打印 上一主題 下一主題
收起左側(cè)

51單片機(jī)怎樣用按鍵控制長(zhǎng)短按切換界面,求程序思路

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:444712 發(fā)表于 2019-7-29 17:09 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
我要用兩個(gè)按鍵k1,k2。長(zhǎng)按K2,切換到設(shè)置界面,短按K2切換到常規(guī)界面。弄了好久沒(méi)有弄好,請(qǐng)高手幫忙指導(dǎo)一下,謝謝!
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:435708 發(fā)表于 2019-7-29 19:54 | 只看該作者
請(qǐng)工程化,定制化你的單片機(jī)代碼
http://www.torrancerestoration.com/bbs/dpj-162218-1.html
(出處: 單片機(jī)論壇)
回復(fù)

使用道具 舉報(bào)

板凳
ID:332444 發(fā)表于 2019-7-29 20:44 | 只看該作者
一般使用狀態(tài)進(jìn)行切換,你是怎么弄的不行?
回復(fù)

使用道具 舉報(bào)

地板
ID:213173 發(fā)表于 2019-7-29 21:18 | 只看該作者
如果K2只是用于切換界面不必采用長(zhǎng)短按方式,只要設(shè)置一個(gè)標(biāo)志隨操作取反即可。如果K2是多功能鍵才有必要分長(zhǎng)短按。給你一個(gè)簡(jiǎn)單實(shí)用的長(zhǎng)短按示例程序參考,希望對(duì)你有所幫助。
  1. #include <REG51.H>
  2. #define uint unsigned int
  3. #define uchar unsigned char
  4. #define key_S 20                                                //宏定義短按(20ms)
  5. #define key_L key_S*50                                //宏定義長(zhǎng)按(1s)

  6. sbit key1=P3^5;
  7. sbit key2=P3^6;
  8. sbit LED1=P1^0;
  9. sbit LED2=P1^2;
  10. sbit LED3=P1^4;
  11. sbit LED4=P1^6;
  12. uchar KeySec=0;

  13. void Timer0Init()//1毫秒@12.000MHz
  14. {
  15.         TMOD= 0x01;                //設(shè)置定時(shí)器模式
  16.         TL0 = 0x18;                //設(shè)置定時(shí)初值
  17.         TH0 = 0xFC;                //設(shè)置定時(shí)初值
  18.         TF0 = 0;                        //清除TF0標(biāo)志
  19.         TR0 = 1;                        //定時(shí)器0開(kāi)始計(jì)時(shí)
  20.         EA=1;                                //開(kāi)總中斷
  21.         ET0=1;                        //開(kāi)定時(shí)器0中斷
  22. }

  23. void keyscan()                                                        //按鍵掃描
  24. {
  25.         static uint count1=0;                        //計(jì)數(shù)變量
  26.         static uint count2=0;                        //計(jì)數(shù)變量
  27.         if(!key1)   
  28.         {  
  29.                 count1++;  
  30.                 if(count1==key_L)                                //長(zhǎng)按
  31.                         KeySec=2;                                        //輸出鍵值2
  32.                 if(count1>key_L)                                //防止count溢出
  33.                         count1=key_L+1;          
  34.         }  
  35.         else                                                                        //按鍵抬起
  36.         {  
  37.                 if(count1>key_S && count1<key_L)//短按
  38.                         KeySec=1;                                        //輸出鍵值1
  39.                         count1=0;                                        //count清0
  40.         }   
  41.         if(!key2)   
  42.         {  
  43.                 count2++;  
  44.                 if(count2==key_L)                                //長(zhǎng)按
  45.                         KeySec=4;                                        //輸出鍵值4
  46.                 if(count2>key_L)                                //防止count溢出
  47.                         count2=key_L+1;          
  48.         }  
  49.         else                                                                        //按鍵抬起
  50.         {  
  51.                 if(count2>key_S && count2<key_L)//短按
  52.                         KeySec=3;                                        //輸出鍵值3
  53.                         count2=0;                                        //count清0
  54.         }   
  55. }

  56. void key_service()                                        //按鍵服務(wù)程序
  57. {
  58.         switch(KeySec)                                                //按鍵服務(wù)狀態(tài)切換
  59.         {
  60.                 case 1:LED2=!LED2;KeySec=0;break;
  61.                 case 2:LED1=!LED1;KeySec=0;break;
  62.                 case 3:LED4=!LED4;KeySec=0;break;
  63.                 case 4:LED3=!LED3;KeySec=0;break;
  64.                 default: break;
  65.         }
  66. }

  67. void main()
  68. {
  69.         Timer0Init();                //初始化定時(shí)器
  70.         while(1)
  71.         {
  72.                 key_service();        //按鍵服務(wù)程序
  73.         }
  74. }
  75. void timer0() interrupt        1//1毫秒@12.000MHz
  76. {
  77.         TL0 = 0x18;                //設(shè)置定時(shí)重裝值
  78.         TH0 = 0xFC;                //設(shè)置定時(shí)重裝值
  79.         keyscan();                //按鍵掃描程序
  80. }
復(fù)制代碼



回復(fù)

使用道具 舉報(bào)

5#
ID:136106 發(fā)表于 2019-7-29 22:34 | 只看該作者
這個(gè)可以用定時(shí)器來(lái)操作,假設(shè)K2按下的時(shí)間超過(guò)2S進(jìn)入設(shè)置界面。配置好定時(shí)器計(jì)時(shí)計(jì)數(shù),當(dāng)檢測(cè)到K2按下時(shí)開(kāi)啟計(jì)時(shí)。比如說(shuō)100ms來(lái)一次中斷,計(jì)數(shù)值temp++,當(dāng)來(lái)20次中斷后時(shí)間就為2S。判斷按鍵松開(kāi)時(shí)temp的值是否大于20?當(dāng)temp的值大于20就進(jìn)入你所說(shuō)的設(shè)置界面,小于20就進(jìn)入頁(yè)面切換。這樣的小程序用51來(lái)操作很容易,但是要注意定時(shí)器計(jì)數(shù)器的初值裝載的問(wèn)題,還有就是51單片機(jī)所用的晶振。12MHz的晶振和11.0592MHz的初值裝載是不一樣的。沒(méi)看懂的話就要回去看看51的定時(shí)器的知識(shí)了
回復(fù)

使用道具 舉報(bào)

6#
ID:388197 發(fā)表于 2019-7-29 23:59 | 只看該作者
隨手寫的,就寫了1個(gè)按鍵長(zhǎng)按短按不同功能,不保證沒(méi)BUG.注釋標(biāo)得也自認(rèn)為是清楚了,你對(duì)著你想要的修改調(diào)試下應(yīng)該就可以了.


#define Long_Push_Time    n        //長(zhǎng)按功能按鍵時(shí)長(zhǎng)(n乘以定時(shí)器中斷周期)
#define Short_Push_Time   m       //短按功能按鍵時(shí)間,需注意必須n 大于 m
sbit KEY = Px^x;                               //按鍵IO口定義
bit Flag_Short_Push_Funcation = 0;    //短按觸發(fā)標(biāo)志
bit Flag_Long_Push_Funcation = 0;    //長(zhǎng)按觸發(fā)標(biāo)志
bit Flag_KEY_Pushed               = 0;   //按鍵曾經(jīng)按下標(biāo)志

void Init_T0()                                 //定時(shí)器中斷設(shè)置
{
   .....
}

void Short_Push_Prog()
{
    ..........
}

void Long_Push_Prog()
{
     ............
}
void mian()
{
     Init_T0();
     while(1)
     {
        if(Flag_Short_Push_Funcation)                      //如果短按功能被置1
        {
              Short_Push_Prog();                              //執(zhí)行短按功能對(duì)應(yīng)的函數(shù)
              Flag_Short_Push_Funcation = 0;           //清短按功能標(biāo)志.
        }
        if(Flag_Long_Push_Funcation)                    //長(zhǎng)按功能,跟上面類同.
       {
               Long_Push_Prog();
               Flag_Long_Push_Funcation = 0;
       }
     }
}

void T0_ISR() interrupt 1
{
    TH0 = XXXX;
    TL0 = XXXX;
     if(!KEY)                                             //按鍵按下
     {
        KEY_CNT++;                                 //開(kāi)始計(jì)時(shí)
        Flag_KEY_Pushed= 1;                    //按鍵已經(jīng)按過(guò)的標(biāo)志置1
        Flag_Short_Push_Funcation = 0;                   //短按無(wú)效
        Flag_Long_Push_Funcation  = 0;                   //長(zhǎng)按無(wú)效
     }
     if(KEY && Flag_KEY_Pushed == 1 && KEY_CNT < Short_Push_Time)
     /*如果按鍵沒(méi)有按下但按鍵曾經(jīng)按下,可是按下時(shí)間很短,不足以觸發(fā)短按的設(shè)定時(shí)間,則認(rèn)為是干擾*/
    {
         Flag_KEY_Pushed= 0;                                  //清按鍵曾經(jīng)按下標(biāo)志
         KEY_CNT = 0;                                            //清按鍵按下計(jì)時(shí)變量
         Flag_Short_Push_Funcation = 0;                   //短按無(wú)效
         Flag_Long_Push_Funcation  = 0;                   //長(zhǎng)按無(wú)效
         return;                                          //如判斷為干擾,則下面的代碼無(wú)須執(zhí)行,直接跳出.  
    }
     if(KEY && Flag_KEY_Pushed == 1 && KEY_CNT>=Short_Push_Time &&
       KEY_CNT < Long_Push_Time)
      /*如果按鍵沒(méi)有按下, 但按鍵已經(jīng)按過(guò)(用來(lái)判斷按過(guò)后彈起),
            并且曾經(jīng)按下時(shí)間超過(guò) 設(shè)定短按時(shí)間且不超過(guò)長(zhǎng)按時(shí)間*/
     {
           Flag_Short_Push_Funcation = 1;         //短按功能有效
           Flag_Long_Push_Funcation = 0;         //長(zhǎng)按功能無(wú)效
           KEY_CNT             = 0;                      //清按鍵計(jì)時(shí)變量
           Flag_KEY_Pushed=  0;                      //清按鍵曾經(jīng)按下標(biāo)志
           return;                       //判斷完成,直接跳出
     }
}

      if(KEY && Flag_KEY_Pushed == 1 && KEY_CNT>=Long_Push_Time )
      /*如果按鍵沒(méi)有按下, 但按鍵已經(jīng)按過(guò)(用來(lái)判斷按過(guò)后彈起),
            且曾經(jīng)按下時(shí)間超過(guò) 長(zhǎng)按時(shí)間*/
       {
           Flag_Short_Push_Funcation = 0;         //短按功能無(wú)效
           Flag_Long_Push_Funcation = 1;         //長(zhǎng)按功能有效
           KEY_CNT             = 0;                      //清按鍵計(jì)時(shí)變量
           Flag_KEY_Pushed=  0;                      //清按鍵曾經(jīng)按下標(biāo)志
       }
}
回復(fù)

使用道具 舉報(bào)

7#
ID:511461 發(fā)表于 2019-7-30 08:27 | 只看該作者
cjm82 發(fā)表于 2019-7-29 23:59
隨手寫的,就寫了1個(gè)按鍵長(zhǎng)按短按不同功能,不保證沒(méi)BUG.注釋標(biāo)得也自認(rèn)為是清楚了,你對(duì)著你想要的修改調(diào)試下 ...

謝謝分享
回復(fù)

使用道具 舉報(bào)

8#
ID:123289 發(fā)表于 2019-7-30 08:31 | 只看該作者
要點(diǎn):做一個(gè)計(jì)數(shù)器CJ來(lái)判定長(zhǎng)按與短按,CJ的規(guī)則如下:
1、CJ計(jì)數(shù)只發(fā)生于定時(shí)器的中斷服務(wù)程序中,每次中斷+1,計(jì)滿不再計(jì),即不回0。
2、CJ計(jì)數(shù)只發(fā)生于鍵按下的時(shí)候,未按下不計(jì)。
3、做一個(gè)鍵狀態(tài)判定觸發(fā)標(biāo)記:B_OK,如果鍵未按下,但CJ<>0,則置B_OK=1,表示是判斷鍵狀態(tài)的時(shí)候了。
4、當(dāng)B_OK=1,判斷鍵狀態(tài)的界定法則是:CJ<某個(gè)值為短按,CJ>某個(gè)值為長(zhǎng)按,某個(gè)值是多少由你決定。建議事先將長(zhǎng)短兩個(gè)界定值放置在某個(gè)寄存器中,這樣可以隨意變更界定值。
5、狀態(tài)界定完成后將:B_OK清0、CJ清0以備下次再界定。
回復(fù)

使用道具 舉報(bào)

9#
ID:123289 發(fā)表于 2019-7-30 08:40 | 只看該作者
設(shè)置界面、常規(guī)界面各做一個(gè)標(biāo)記如:B_SET、B_NOR。在哪個(gè)界面哪個(gè)置1。再多的界面也這樣做。如果只有兩個(gè)界面可以只用一個(gè)標(biāo)記。界面分層疊進(jìn)疊退時(shí)還需要增加次序(層面記憶),這里不說(shuō)了。
長(zhǎng)按以后的動(dòng)作是:B_SET=1、其它B_NOR=0。
短按以后的動(dòng)作是:B_NOR=1、其它B_SET=0。
回復(fù)

使用道具 舉報(bào)

10#
ID:123289 發(fā)表于 2019-7-30 08:41 | 只看該作者
界面的切換,發(fā)生于B_SET、B_NOR有變化的時(shí)候。
回復(fù)

使用道具 舉報(bào)

11#
ID:307020 發(fā)表于 2019-7-30 10:47 | 只看該作者
參考文章“請(qǐng)工程化,定制化你的單片機(jī)代碼”,用中斷服務(wù)對(duì)按下鍵進(jìn)行計(jì)數(shù),根據(jù)計(jì)數(shù)的多少便可換算時(shí)間長(zhǎng)短、便可根據(jù)不同時(shí)間長(zhǎng)短執(zhí)行不同的程序了。
回復(fù)

使用道具 舉報(bào)

12#
ID:592379 發(fā)表于 2019-7-30 15:31 | 只看該作者
用定時(shí)器做,按下按鈕開(kāi)始計(jì)數(shù),放開(kāi)按鈕結(jié)束計(jì)數(shù),按鈕函數(shù)里面要加個(gè)防抖延時(shí)
回復(fù)

使用道具 舉報(bào)

13#
ID:444712 發(fā)表于 2019-8-1 16:47 | 只看該作者
謝謝!
回復(fù)

使用道具 舉報(bào)

14#
ID:444712 發(fā)表于 2019-8-2 16:45 | 只看該作者
cjm82 發(fā)表于 2019-7-29 23:59
隨手寫的,就寫了1個(gè)按鍵長(zhǎng)按短按不同功能,不保證沒(méi)BUG.注釋標(biāo)得也自認(rèn)為是清楚了,你對(duì)著你想要的修改調(diào)試下 ...

Init_T0,void Short_Push_Prog(),void Long_Push_Prog().里邊的內(nèi)容能否幫忙提供一下.謝謝!
回復(fù)

使用道具 舉報(bào)

15#
ID:415527 發(fā)表于 2019-8-4 10:47 | 只看該作者
當(dāng)按鍵按下時(shí),開(kāi)啟定時(shí)器,并且在定時(shí)器中斷里面用一個(gè)變量來(lái)計(jì)數(shù),當(dāng)按鍵松開(kāi)時(shí)再來(lái)判斷計(jì)數(shù)時(shí)間,如果小于0.5s,則判斷為短按,標(biāo)志位給0,如果大于0.5s,標(biāo)志位給1,然后根據(jù)標(biāo)志位進(jìn)行界面切換。定時(shí)器的計(jì)數(shù)時(shí)間要設(shè)置一個(gè)上限,否則如果時(shí)間太長(zhǎng)可能會(huì)溢出,判斷按鍵按下或松開(kāi),可以用經(jīng)典的三行代碼,其中有兩個(gè)變量,一個(gè)變量是用來(lái)判斷按鍵的“下降沿”(其實(shí)準(zhǔn)確來(lái)說(shuō)并不能定義為下降沿,只是按鍵按下時(shí),第一遍執(zhí)行程序時(shí),對(duì)應(yīng)的位會(huì)發(fā)生改變,當(dāng)執(zhí)行第二遍時(shí)就又變?yōu)?,有點(diǎn)類似于static的作用),另一個(gè)變量是用來(lái)檢測(cè)按鍵是否為按下?tīng)顟B(tài),可以用這兩個(gè)變量來(lái)判斷按鍵按下和松開(kāi),從而開(kāi)啟或改變定時(shí)器,讀取計(jì)數(shù)值,讀取完計(jì)數(shù)值后需要將計(jì)數(shù)值清零,否則,第二次按下按鍵時(shí)則判斷不了短按。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表