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

QQ登錄

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

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

51單片機(jī)獨(dú)立按鍵程序 實(shí)現(xiàn)長(zhǎng)按、短按功能

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:743654 發(fā)表于 2021-9-30 11:26 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
獨(dú)立按鍵 通過(guò)定時(shí)器實(shí)現(xiàn)長(zhǎng)按、短按功能:

程序每條語(yǔ)句都附帶注釋,易理解,方便移植。

本人親測(cè)有效!

單片機(jī)源程序如下:
  1. /*************************************************************************************
  2. 實(shí)驗(yàn)現(xiàn)象:下載程序后按下K1按鍵可以對(duì)led_0/led_1小燈狀態(tài)取反
  3.            短按控制led_0;長(zhǎng)按控制led_1                                                  
  4. *************************************************************************************
  5. */

  6. #include "reg52.h"               //此文件中定義了單片機(jī)的一些特殊功能寄存器

  7. typedef unsigned int u16;          //對(duì)數(shù)據(jù)類(lèi)型進(jìn)行聲明定義
  8. typedef unsigned char u8;

  9. bit press_flag; //按鍵標(biāo)志位
  10. u16 count;      //計(jì)數(shù)器標(biāo)志位
  11. sbit k1=P3^1;         //定義P31口是k1
  12. sbit led_0=P2^0; //定義P20口是led_0
  13. sbit led_1=P2^1; //定義P20口是led_1

  14. void Timer0Init()
  15. {
  16.         TMOD|=0X01;//選擇為定時(shí)器0模式,工作方式1,僅用TR0打開(kāi)啟動(dòng)。

  17.         TH0=0XFC;        //給定時(shí)器賦初值,定時(shí)1ms
  18.         TL0=0X18;       
  19.         ET0=1;         //打開(kāi)定時(shí)器0中斷允許
  20.         EA=1;         //打開(kāi)總中斷
  21.         TR0=1;//打開(kāi)定時(shí)器                       
  22. }

  23. void Timer0() interrupt 1
  24. {
  25.         TH0=0XFC;        //給定時(shí)器賦初值,定時(shí)1ms
  26.         TL0=0X18;
  27.         count++;  //計(jì)數(shù)器累加
  28. }


  29. /*******************************************************************************
  30. * 函 數(shù) 名         : delay
  31. * 函數(shù)功能                   : 延時(shí)函數(shù),i=1時(shí),大約延時(shí)10us
  32. *******************************************************************************/
  33. void delay(u16 i)
  34. {
  35.         while(i--);       
  36. }

  37. /*******************************************************************************
  38. * 函 數(shù) 名         : keypros
  39. * 函數(shù)功能                   : 按鍵處理函數(shù),判斷按鍵K1是否按下
  40. *******************************************************************************/
  41. void keypros()
  42. {
  43.         if(k1==0)                     //檢測(cè)按鍵K1是否按下
  44.         {       
  45.                 delay(1000);   //消除抖動(dòng) 一般大約10ms
  46.                 if(k1==0)             //再次判斷按鍵是否按下
  47.                 {
  48.                   press_flag=1; //按鍵標(biāo)志位
  49.                   TR0=1;        //打開(kāi)中斷
  50.                   while(!k1);   //按鍵松手檢測(cè)
  51.                   TR0=0;        //關(guān)閉中斷
  52.                 }
  53.            if(press_flag)  //若有按鍵
  54.           {
  55.             if(count>=1500) //長(zhǎng)按>=1.5s
  56.             {
  57.               led_1=~led_1;        //led_1燈狀態(tài)取反 ,此處可以換成別的處理事件
  58.              }
  59.             else            //短按<1.5s
  60.             {
  61.               led_0=~led_0;         //led_0燈狀態(tài)取反 ,此處可以換成別的處理事件
  62.             }
  63.             count=0;               //計(jì)數(shù)器清零
  64.             press_flag=0;        //按鍵標(biāo)志位清零
  65.           }                
  66.         }
  67. }

  68. /*******************************************************************************
  69. * 函 數(shù) 名       : main
  70. * 函數(shù)功能                 : 主函數(shù)
  71. * 輸    入       : 無(wú)
  72. * 輸    出             : 無(wú)
  73. *******************************************************************************/
  74. void main()
  75. {       
  76.         Timer0Init();//定時(shí)器初始化
  77.         led_0=1;     //led_0熄滅
  78.         led_1=1;     //led_1熄滅
  79.         while(1)     //主循環(huán)
  80.         {       
  81.           keypros();  //按鍵處理函數(shù)       
  82.         }               
  83. }
復(fù)制代碼


評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏19 分享淘帖 頂3 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:1042234 發(fā)表于 2022-8-17 10:32 | 只看該作者
好像不太對(duì) 第一次短按會(huì)判斷為長(zhǎng)按
回復(fù)

使用道具 舉報(bào)

板凳
ID:1039671 發(fā)表于 2022-8-17 16:34 | 只看該作者
stcmcu2 發(fā)表于 2022-8-17 10:32
好像不太對(duì) 第一次短按會(huì)判斷為長(zhǎng)按

做了實(shí)驗(yàn),第一次開(kāi)機(jī)LED1會(huì)亮,仔細(xì)分析了下代碼,在定時(shí)器初始化里面把TR0=1改為T(mén)R0=0,就可以解決這個(gè)問(wèn)題。然后感覺(jué)有一點(diǎn)還是不完美,就是按鍵長(zhǎng)按不松開(kāi)LED1不會(huì)點(diǎn)亮,需要釋放按鍵才能點(diǎn)亮。
回復(fù)

使用道具 舉報(bào)

地板
ID:161164 發(fā)表于 2022-8-17 17:32 | 只看該作者
stcmcu2 發(fā)表于 2022-8-17 10:32
好像不太對(duì) 第一次短按會(huì)判斷為長(zhǎng)按

26行 改為 TR0 = 0;
但不建議用長(zhǎng)時(shí)間的阻塞式消抖/while(!K1)
回復(fù)

使用道具 舉報(bào)

5#
ID:814525 發(fā)表于 2022-8-17 20:17 | 只看該作者
一看到while(!k1)這句,就沒(méi)有研究的價(jià)值。
回復(fù)

使用道具 舉報(bào)

6#
ID:1042234 發(fā)表于 2022-8-18 08:42 | 只看該作者
lkc8210 發(fā)表于 2022-8-17 17:32
26行 改為 TR0 = 0;
但不建議用長(zhǎng)時(shí)間的阻塞式消抖/while(!K1)

雙擊的怎么樣去操作
回復(fù)

使用道具 舉報(bào)

7#
ID:161164 發(fā)表于 2022-8-18 10:00 | 只看該作者
  1. /*************************************************************************************
  2. 實(shí)驗(yàn)現(xiàn)象:下載程序后按下K1按鍵可以對(duì)led_0/led_1小燈狀態(tài)取反
  3.            短按控制led_0;長(zhǎng)按控制led_1
  4. *************************************************************************************
  5. */

  6. #include "reg52.h"               //此文件中定義了單片機(jī)的一些特殊功能寄存器

  7. typedef unsigned int u16;          //對(duì)數(shù)據(jù)類(lèi)型進(jìn)行聲明定義
  8. typedef unsigned char u8;

  9. u16 count = 0;      //計(jì)數(shù)器標(biāo)志位
  10. u8 KeyVal = 0;//按鍵標(biāo)志位
  11. sbit k1=P3^1;         //定義P31口是k1
  12. sbit led_0=P2^0; //定義P20口是led_0
  13. sbit led_1=P2^1; //定義P20口是led_1
  14. bit Flag_1ms = 0;//1ms標(biāo)志位
  15. void Timer0Init()
  16. {
  17.         TMOD|=0X01;//選擇為定時(shí)器0模式,工作方式1,僅用TR0打開(kāi)啟動(dòng)。

  18.         TH0=0XFC;        //給定時(shí)器賦初值,定時(shí)1ms
  19.         TL0=0X18;
  20.         ET0=1;         //打開(kāi)定時(shí)器0中斷允許
  21.         EA=1;         //打開(kāi)總中斷
  22.         TR0=1;//打開(kāi)定時(shí)器
  23. }

  24. void Timer0() interrupt 1
  25. {
  26.         TH0=0XFC;        //給定時(shí)器賦初值,定時(shí)1ms
  27.         TL0=0X18;
  28.         Flag_1ms = 1;
  29. }

  30. /*******************************************************************************
  31. * 函 數(shù) 名         : keypros
  32. * 函數(shù)功能                   : 按鍵處理函數(shù),判斷按鍵K1是否按下
  33. *******************************************************************************/
  34. void keypros()
  35. {
  36.         if(Flag_1ms==1)
  37.         {
  38.                 Flag_1ms = 0;
  39.                 if(k1==0)             //判斷按鍵是否按下
  40.                 {
  41.                         if(count<0xFFFF)count++;
  42.                         if(count==1500)
  43.                         {
  44.                                 KeyVal = 10;
  45.                         }
  46.                 }
  47.                 else
  48.                 {
  49.                         if((count>= 20) && (count<1500))
  50.                         {
  51.                                 KeyVal = 1;
  52.                         }
  53.                         count=0;
  54.                 }
  55.                 if(KeyVal > 0)  //若有按鍵
  56.                 {
  57.                         if(KeyVal==10) //長(zhǎng)按>=1.5s
  58.                         {
  59.                                 led_1=~led_1;        //led_1燈狀態(tài)取反 ,此處可以換成別的處理事件
  60.                         }
  61.                         else            //短按<1.5s
  62.                         {
  63.                                 led_0=~led_0;         //led_0燈狀態(tài)取反 ,此處可以換成別的處理事件
  64.                         }
  65.                         KeyVal=0;
  66.                 }
  67.         }
  68. }

  69. /*******************************************************************************
  70. * 函 數(shù) 名       : main
  71. * 函數(shù)功能                 : 主函數(shù)
  72. * 輸    入       : 無(wú)
  73. * 輸    出             : 無(wú)
  74. *******************************************************************************/
  75. void main()
  76. {
  77.         Timer0Init();//定時(shí)器初始化
  78.         led_0=1;     //led_0熄滅
  79.         led_1=1;     //led_1熄滅
  80.         while(1)     //主循環(huán)
  81.         {
  82.                 keypros();  //按鍵處理函數(shù)
  83.         }
  84. }
復(fù)制代碼


回復(fù)

使用道具 舉報(bào)

8#
ID:161164 發(fā)表于 2022-8-18 10:22 | 只看該作者
stcmcu2 發(fā)表于 2022-8-18 08:42
雙擊的怎么樣去操作
  1. /*************************************************************************************
  2. 實(shí)驗(yàn)現(xiàn)象:下載程序后按下K1按鍵可以對(duì)led_0/led_1小燈狀態(tài)取反
  3.            短按控制led_0;長(zhǎng)按控制led_1
  4. *************************************************************************************
  5. */

  6. #include "reg52.h"               //此文件中定義了單片機(jī)的一些特殊功能寄存器

  7. typedef unsigned int u16;          //對(duì)數(shù)據(jù)類(lèi)型進(jìn)行聲明定義
  8. typedef unsigned char u8;

  9. u16 PressDelay = 0;     //按下計(jì)數(shù)器標(biāo)志位
  10. u16 ReleaseDelay = 0;   //放開(kāi)計(jì)數(shù)器標(biāo)志位
  11. u8 KeyVal = 0;                        //按鍵標(biāo)志位
  12. u8 ClickCount = 0;                //按鍵次數(shù)
  13. sbit k1=P3^2;                 //定義P32口是k1
  14. sbit led_0=P2^0;                 //定義P20口是led_0
  15. sbit led_1=P2^1;                 //定義P20口是led_1
  16. bit Flag_1ms = 0;                //1ms標(biāo)志位
  17. void Timer0Init()
  18. {
  19.         TMOD|=0X01;//選擇為定時(shí)器0模式,工作方式1,僅用TR0打開(kāi)啟動(dòng)。

  20.         TH0=0XFC;       //給定時(shí)器賦初值,定時(shí)1ms
  21.         TL0=0X18;
  22.         ET0=1;                 //打開(kāi)定時(shí)器0中斷允許
  23.         EA=1;                 //打開(kāi)總中斷
  24.         TR0=1;                        //打開(kāi)定時(shí)器
  25. }

  26. void Timer0() interrupt 1
  27. {
  28.         TH0=0XFC;        //給定時(shí)器賦初值,定時(shí)1ms
  29.         TL0=0X18;
  30.         Flag_1ms = 1;         //1ms標(biāo)志位
  31. }

  32. /*******************************************************************************
  33. * 函 數(shù) 名         : keypros
  34. * 函數(shù)功能                   : 按鍵處理函數(shù),判斷按鍵K1是否按下
  35. *******************************************************************************/
  36. void keypros()
  37. {
  38.         if(Flag_1ms==1)
  39.         {
  40.                 Flag_1ms = 0;
  41.                 if(k1==0)             //判斷按鍵是否按下
  42.                 {
  43.                         if(PressDelay<0xFFFF)PressDelay++;
  44.                         if(PressDelay==20)//20ms消抖
  45.                         {
  46.                                 ClickCount++;
  47.                         }
  48.                         if(PressDelay==1500)
  49.                         {
  50.                                 KeyVal = 10;
  51.                         }
  52.                         ReleaseDelay = 0;
  53.                 }
  54.                 else
  55.                 {
  56.                         if(ReleaseDelay<0xFF)ReleaseDelay++;
  57.                         if(ReleaseDelay==200)
  58.                         if(PressDelay<1500)
  59.                         {
  60.                                 KeyVal = ClickCount;
  61.                                 ClickCount = 0;
  62.                         }
  63.                         PressDelay=0;
  64.                 }
  65.                 if(KeyVal > 0)  //若有按鍵
  66.                 {
  67.                         if(KeyVal==10) //長(zhǎng)按>=1.5s
  68.                         {
  69.                                 led_1=~led_1;        //led_1燈狀態(tài)取反 ,此處可以換成別的處理事件
  70.                         }
  71.                         else if(KeyVal==1)
  72.                         {
  73.                                 led_0=0;
  74.                         }
  75.                         else if(KeyVal==2)
  76.                         {
  77.                                 led_0=1;
  78.                         }
  79.                         KeyVal=0;
  80.                 }
  81.         }
  82. }

  83. /*******************************************************************************
  84. * 函 數(shù) 名       : main
  85. * 函數(shù)功能                 : 主函數(shù)
  86. * 輸    入       : 無(wú)
  87. * 輸    出             : 無(wú)
  88. *******************************************************************************/
  89. void main()
  90. {
  91.         Timer0Init();//定時(shí)器初始化
  92.         led_0=1;     //led_0熄滅
  93.         led_1=1;     //led_1熄滅
  94.         while(1)     //主循環(huán)
  95.         {
  96.                 keypros();  //按鍵處理函數(shù)
  97.         }
  98. }
復(fù)制代碼


回復(fù)

使用道具 舉報(bào)

9#
ID:119977 發(fā)表于 2022-8-18 10:31 | 只看該作者
delay(1000);   //消除抖動(dòng) 一般大約10ms   //一般我看到用延時(shí)消抖我都覺(jué)得水平一般   
回復(fù)

使用道具 舉報(bào)

10#
ID:1042234 發(fā)表于 2022-8-18 15:01 | 只看該作者

1.按鈕長(zhǎng)按松開(kāi)的時(shí)候會(huì)誤判為短按
2.雙擊的時(shí)候第二下如果時(shí)間長(zhǎng)一點(diǎn)的話會(huì)誤判為長(zhǎng)按
回復(fù)

使用道具 舉報(bào)

11#
ID:1042234 發(fā)表于 2022-8-18 15:11 | 只看該作者

你好  實(shí)際在測(cè)試的時(shí)候發(fā)現(xiàn) 1.按鈕長(zhǎng)按抬起的時(shí)候會(huì)誤判為短按
2.雙擊的時(shí)候第二下長(zhǎng)按的時(shí)候會(huì)誤判為長(zhǎng)按  
回復(fù)

使用道具 舉報(bào)

12#
ID:161164 發(fā)表于 2022-8-18 17:26 | 只看該作者
stcmcu2 發(fā)表于 2022-8-18 15:01
1.按鈕長(zhǎng)按松開(kāi)的時(shí)候會(huì)誤判為短按
2.雙擊的時(shí)候第二下如果時(shí)間長(zhǎng)一點(diǎn)的話會(huì)誤判為長(zhǎng)按
  1. void keypros()
  2. {
  3.         if(Flag_1ms==1)
  4.         {
  5.                 Flag_1ms = 0;
  6.                 if(k1==0)             //判斷按鍵是否按下
  7.                 {
  8.                         if(PressDelay<0xFFFF)PressDelay++;
  9.                         if(PressDelay==20)//20ms消抖
  10.                         {
  11.                                 ClickCount++;
  12.                         }
  13.                                                 if(ClickCount<2)//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  14.                                                         if(PressDelay==1500)
  15.                                                         {
  16.                                                                         KeyVal = 10;
  17.                                                                         ClickCount = 0;//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  18.                                                         }
  19.                         ReleaseDelay = 0;
  20.                 }
  21.                 else
  22.                 {
  23.                         if(ReleaseDelay<0xFF)ReleaseDelay++;
  24.                         if(ReleaseDelay==200)
  25.                                                         if(ClickCount)//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  26.                                                         {
  27.                                                                         KeyVal = ClickCount;
  28.                                                                         ClickCount = 0;
  29.                                                         }
  30.                         PressDelay=0;
  31.                 }
  32.                 if(KeyVal > 0)  //若有按鍵
  33.                 {
  34.                         if(KeyVal==10) //長(zhǎng)按>=1.5s
  35.                         {
  36.                                 led_1=~led_1;        //led_1燈狀態(tài)取反 ,此處可以換成別的處理事件
  37.                         }
  38.                         else if(KeyVal==1)
  39.                         {
  40.                                 led_0=0;
  41.                         }
  42.                         else if(KeyVal==2)
  43.                         {
  44.                                 led_0=1;
  45.                         }
  46.                         KeyVal=0;
  47.                 }
  48.         }
  49. }
復(fù)制代碼


回復(fù)

使用道具 舉報(bào)

13#
ID:1042234 發(fā)表于 2022-8-19 09:36 | 只看該作者

有時(shí)間我試一試 效果
回復(fù)

使用道具 舉報(bào)

14#
ID:1039671 發(fā)表于 2022-8-19 10:03 | 只看該作者

這個(gè)好,長(zhǎng)按不需要松手就可以完成動(dòng)作,收藏了
回復(fù)

使用道具 舉報(bào)

15#
ID:1042234 發(fā)表于 2022-8-19 11:30 | 只看該作者

短按 抬起  ok
雙擊 抬起ok
長(zhǎng)按 ok
回復(fù)

使用道具 舉報(bào)

16#
ID:699774 發(fā)表于 2022-8-19 12:38 | 只看該作者
hewayking 發(fā)表于 2022-8-18 10:31
delay(1000);   //消除抖動(dòng) 一般大約10ms   //一般我看到用延時(shí)消抖我都覺(jué)得水平一般

確實(shí)真正寫(xiě)程序誰(shuí)會(huì)用delay讓mcu死在這里循環(huán)等待呢
回復(fù)

使用道具 舉報(bào)

17#
ID:1093578 發(fā)表于 2023-9-14 20:21 | 只看該作者

試了一下,確實(shí)OK
回復(fù)

使用道具 舉報(bào)

18#
ID:320250 發(fā)表于 2023-9-15 12:58 | 只看該作者
用定時(shí)器來(lái)檢測(cè),有點(diǎn)浪費(fèi)
回復(fù)

使用道具 舉報(bào)

19#
ID:1093578 發(fā)表于 2023-9-16 10:11 | 只看該作者
瘋城浪子 發(fā)表于 2023-9-15 12:58
用定時(shí)器來(lái)檢測(cè),有點(diǎn)浪費(fèi)

我很疑惑,他這個(gè)功能實(shí)現(xiàn)是OK的,但是TR0=1 打開(kāi)后,再也沒(méi)關(guān)閉。定時(shí)器一直在跑,有什么弊端?
回復(fù)

使用道具 舉報(bào)

20#
ID:1093740 發(fā)表于 2023-9-16 17:21 | 只看該作者

這個(gè)COUNT延時(shí),是不是還得算上程序運(yùn)行時(shí)間了。額。應(yīng)該沒(méi)啥影響吧。
回復(fù)

使用道具 舉報(bào)

21#
ID:1093740 發(fā)表于 2023-9-16 17:22 | 只看該作者
Tony5658 發(fā)表于 2023-9-16 10:11
我很疑惑,他這個(gè)功能實(shí)現(xiàn)是OK的,但是TR0=1 打開(kāi)后,再也沒(méi)關(guān)閉。定時(shí)器一直在跑,有什么弊端?

這定時(shí)器一直跑,沒(méi)啥影響啊
回復(fù)

使用道具 舉報(bào)

22#
ID:1119741 發(fā)表于 2024-6-17 17:12 | 只看該作者
有處理兩個(gè)按鍵的嘛
回復(fù)

使用道具 舉報(bào)

23#
ID:161164 發(fā)表于 2024-6-18 11:54 | 只看該作者
mxf153163 發(fā)表于 2024-6-17 17:12
有處理兩個(gè)按鍵的嘛

有,加一些判斷和標(biāo)志位
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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