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

QQ登錄

只需一步,快速開始

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

單片機(jī)按鍵消抖經(jīng)典算法,親測(cè)很好用,不信自己試試,分享就是快樂!

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:114701 發(fā)表于 2020-7-12 23:52 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
/*功能:實(shí)現(xiàn)按鍵計(jì)數(shù),4位數(shù)碼管上顯示計(jì)數(shù)值,   實(shí)驗(yàn)?zāi)康模喊存I穩(wěn)定消抖,按鍵按下一次只執(zhí)行一次操作,*/

單片機(jī)源程序如下:
  1. #include<reg52.h>
  2. #include<intrins.h>
  3. typedef unsigned char uint8;
  4. #include<reg52.h>
  5. #include<intrins.h>
  6. typedef unsigned char uint8;                          
  7. typedef unsigned int uint16;                           
  8. typedef unsigned long uint32;

  9. sbit KEYGND=P3^4; //矩陣按鍵的一條列線,此程序?qū)EYGND=0,模擬出3個(gè)獨(dú)立按鍵的到地
  10. sbit K1 = P3^5;
  11. sbit K2 = P3^6;
  12. sbit K3 = P3^7;
  13. sbit LED = P1^7;
  14. uint8 code seg[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //0-9段碼
  15. uint8 dis[4]={0,0,0,0};//位顯緩存
  16. uint16 count=0,ms;

  17. void KeyScan(void)  //這里的松手檢測(cè)很好用,值得記住,在定時(shí)中斷函數(shù)中每20ms調(diào)用一次KeyScan(),非常完美,基本不會(huì)不影響其程序運(yùn)行,
  18. {                   //按下只產(chǎn)生一次操作
  19.      static bit KeyOnOff = 0;  //這里一定要定義為靜態(tài)變量或者全局變量
  20.      if(K1==0||K2==0||K3==0)             //  判斷是否有按鍵按下
  21.       {
  22.         if(KeyOnOff == 0)         //  自鎖變量
  23.          {
  24.              KeyOnOff = 1;   // 屏蔽這句話,將沒有松手檢測(cè),數(shù)字加的快
  25.              if(K1==0) //按K1加數(shù)
  26.              {
  27.                 count++;
  28.              }
  29.              if(K2==0)  //按K2減數(shù)
  30.              {
  31.                 count--;
  32.              }
  33.              if(K3==0)  //按K3歸零
  34.              {
  35.                 count=0;
  36.              }
  37.           }
  38.       }
  39.      else
  40.       {
  41.         KeyOnOff = 0;    //  當(dāng)沒有按鍵按下時(shí)  解鎖
  42.       }
  43. }
  44. /*********************毫秒延時(shí)函數(shù)************************************/
  45. void delay1ms(unsigned char n)   
  46. {
  47.     unsigned char a,b,c;
  48.                 for(c=n;c>0;c--)
  49.     for(b=102;b>0;b--)
  50.         for(a=3;a>0;a--);
  51. }

  52. /**************************數(shù)據(jù)處理和刷新顯示函數(shù)*********************/
  53. void disp_count()  //數(shù)碼管顯示函數(shù)
  54. {
  55.         uint8 i=0;        
  56.         dis[0]=count%10;       //計(jì)數(shù)器顯示用刷新函數(shù)
  57.         dis[1]=count/10%10;    //計(jì)數(shù)器顯示用刷新函數(shù)
  58.         dis[2]=count/100%10;    //計(jì)數(shù)器顯示用刷新函數(shù)
  59.         dis[3]=count/1000%10;   //計(jì)數(shù)器顯示用刷新函數(shù)
  60.         
  61.         if(dis[3]==0)
  62.         {
  63.                  dis[3]=0x0a;  //高位為零不顯示,
  64.                  if(dis[2]==0)
  65.                  {
  66.             dis[2]=0x0a;  //高位為零不顯示,
  67.             if(dis[1]==0)
  68.             {
  69.                 dis[1]=0x0a;  //高位為零不顯示,
  70.             }
  71.                  }
  72.         }

  73.         for (i=0;i<4;i++)
  74.         {
  75.                         switch(i)           
  76.             {
  77.                 case 0: P0=0Xff; P2=0xfe;break;  //這里的P0=0XFF的目的是消除鬼影
  78.                 case 1: P0=0Xff; P2=0xfd;break;         //這里的P0=0XFF的目的是消除鬼影
  79.                 case 2: P0=0Xff; P2=0xfb;break;  //這里的P0=0XFF的目的是消除鬼影
  80.                 case 3: P0=0Xff; P2=0xf7;break;  //這里的P0=0XFF的目的是消除鬼影
  81.             }
  82.                         P0=seg[dis[i]];
  83.                         delay1ms(1);
  84.         }
  85. }

  86. /*************定時(shí)器初始化函數(shù)*************/
  87. void InitTimer0(void)
  88. {
  89.     TMOD = 0x01;
  90.     TH0 = 0xfc;  //TH0=0xfc,TL0=0x66組合是1毫秒的初值
  91.     TL0 = 0x66;  //
  92.     EA = 1;
  93.     ET0 = 1;
  94.     TR0 = 1;
  95. }   

  96. /*****************************************主函數(shù)*******************************/
  97. void main()
  98. {
  99.     P0=0xff;  //4位數(shù)碼管段碼
  100.     P2=0xff;  //4位數(shù)碼管位碼
  101.     KEYGND=0;
  102.     InitTimer0(); //定時(shí)器初始化函數(shù)
  103.     while(1)
  104.     {

  105.         disp_count();  //數(shù)碼管顯示函數(shù)
  106.         delay1ms(1);   
  107.     }
  108. }

  109. /************************************INT0定時(shí)中斷函數(shù)****************************/
  110. void Timer0Interrupt(void) interrupt 1
  111. {
  112.     TH0 = 0xfc;
  113.     TL0 = 0x66;
  114.                 ms++;      
  115.         if(ms%20==0) //每20ms執(zhí)行一次按鍵檢測(cè)
  116.         {
  117.            KeyScan();
  118.         }
  119.                
  120. }  
復(fù)制代碼

評(píng)分

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

查看全部評(píng)分

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

使用道具 舉報(bào)

沙發(fā)
ID:328014 發(fā)表于 2020-7-13 15:29 | 只看該作者
很好的思路,值得學(xué)習(xí)
回復(fù)

使用道具 舉報(bào)

板凳
ID:17647 發(fā)表于 2020-7-13 15:38 | 只看該作者
經(jīng)典!收藏了。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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