找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 15165|回復(fù): 8
收起左側(cè)

51單片機(jī)消抖處理的按鍵程序源代碼

  [復(fù)制鏈接]
ID:318620 發(fā)表于 2018-5-24 18:07 | 顯示全部樓層 |閱讀模式
單片機(jī)源程序如下:
  1. //軟件消抖的獨(dú)立式鍵盤輸入實(shí)驗(yàn)
  2. #include<reg52.h>    //  包含51單片機(jī)寄存器定義的頭文件
  3. sbit S1=P1^4;        //將S1位定義為P1.4引腳
  4. sbit LED0=P0^0;       //將LED0位定義為P0.0引腳
  5. /*************************************************
  6. 函數(shù)功能:延時約30ms
  7. **************************************************/
  8. void delay(void)
  9. {
  10.    unsigned char i,j;
  11.         for(i=0;i<100;i++)
  12.           for(j=0;j<100;j++)
  13.             ;
  14. }
  15. /*************************************************
  16. 函數(shù)功能:主函數(shù)
  17. **************************************************/
  18. void main(void)  //主函數(shù)
  19. {
  20.    LED0=0;       //P0.0引腳輸出低電平
  21. while(1)
  22.    {
  23.             if(S1==0)   //P1.0引腳輸出低電平,按鍵S1被按下
  24.          {
  25.            delay(); //延時一段時間再次檢測
  26.             if(S1==0)   // 按鍵S1的確被按下
  27.               LED0=~LED0;  //P0.0引腳取反
  28.                 while(!S1);         
  29.           }      
  30.                   
  31.                         
  32.         }
  33. }
復(fù)制代碼
按K5按鍵 控制
以上代碼的Keil2工程文件下載:
消抖處理的按鍵程序.rar (8.11 KB, 下載次數(shù): 33)


回復(fù)

使用道具 舉報

ID:528469 發(fā)表于 2020-10-10 20:28 | 顯示全部樓層
謝謝了 兄弟 解決了
回復(fù)

使用道具 舉報

ID:820160 發(fā)表于 2020-11-18 18:31 | 顯示全部樓層
還用這樣的消抖方式誤導(dǎo)人啊
回復(fù)

使用道具 舉報

ID:515309 發(fā)表于 2022-9-22 15:33 | 顯示全部樓層
請問怎樣算出延時是30MS時間
回復(fù)

使用道具 舉報

ID:1045747 發(fā)表于 2022-9-24 14:54 | 顯示全部樓層
陸少 發(fā)表于 2022-9-22 15:33
請問怎樣算出延時是30MS時間

可能是用debug設(shè)置斷點(diǎn)看出來的
回復(fù)

使用道具 舉報

ID:1045747 發(fā)表于 2022-9-24 14:57 | 顯示全部樓層
確實(shí)這個消抖的方法不好,在運(yùn)行delay()這個部分的時候,單片機(jī)在這30ms的時間里什么也不能做
回復(fù)

使用道具 舉報

ID:1050150 發(fā)表于 2022-11-2 22:43 | 顯示全部樓層
單片機(jī)程序是跑著等,不應(yīng)該等著跑。
回復(fù)

使用道具 舉報

ID:496636 發(fā)表于 2022-11-5 19:12 | 顯示全部樓層
#include<reg52.h>
#define uch unsigned char
#define uint unsigned int
#define ulong unsigned long
sbit ADDR0=P1^0;
sbit ADDR1=P1^1;
sbit ADDR2=P1^2;
sbit ADDR3=P1^3;
sbit ENLED=P1^4;
sbit KEY_IN_1=P2^4;
sbit KEY_IN_2=P2^5;
sbit KEY_IN_3=P2^6;
sbit KEY_IN_4=P2^7;
sbit key_out_1=P2^3;
sbit key_out_2=P2^2;
sbit key_out_3=P2^1;
sbit key_out_4=P2^0;

uch code ledchar[]={                                //從數(shù)字0到F的顯示碼。
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e
};
uch keysta[4][4]={
{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1},
};
void main()
{

   uch i,j;//循環(huán)變量i和j
   uch backup[4][4]={
   {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1},
   };//按鍵值備份。
   EA=1;//使能總中斷
   ENLED=0;//選擇數(shù)碼管DS1進(jìn)行顯示。
   ADDR3=1;
   ADDR2=0;
   ADDR1=0;
   ADDR0=0;
   TMOD=0x01;//定時器0工作在模式1
   TH0=0xfc;
   TL0=0x67;//定時中斷間隔1毫秒
   ET0=1;//開定時器0中斷。
   TR0=1;//啟動定時器0
   P0=ledchar[0]; //LED顯示0
   while(1)
   {
                for (i=0;i<4;i++)//外層循環(huán),執(zhí)行四次;
                {
                         for (j=0;j<4;j++)//內(nèi)層循環(huán),執(zhí)行四次
                         {
                                 if (backup[i]!=keysta[i][j])
                                 {
                                         if (backup[i][j]!=0)//如果上次保存的狀態(tài)是非0,就是1,表明上次按鈕按下,現(xiàn)在狀態(tài)不同上次保存狀態(tài),那意思就是按下后已彈起
                                         {
                                           P0=ledchar[i*4+j];//將編號顯示出來。i是行號,從0行開始,j是行中的第幾個元素,那么變成一維數(shù)據(jù)就是行號*列寬+列號
                                         } //判斷按下彈起大括號
                                        backup[i][j]=keysta[i][j];
                                 }//判斷鍵值變化大括號
                         } //內(nèi)層循環(huán)大括呈

                }//外層循環(huán)大括號
   } //while大括號

} //main函數(shù)大括號

void InterruptTimer0() interrupt 1
{
        uch i;
        static uch keyout=0;
        static uch keybuf[4][4]={
         {0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff}
         };
        TH0=0xfc;//重新加載初值
         TL0=0x67;

         keybuf[keyout][0]=(keybuf[keyout][0]<<1)|KEY_IN_1;
         keybuf[keyout][1]=(keybuf[keyout][0]<<1)|KEY_IN_2;
         keybuf[keyout][2]=(keybuf[keyout][0]<<1)|KEY_IN_3;
         keybuf[keyout][3]=(keybuf[keyout][0]<<1)|KEY_IN_4;
         
         //消抖后更新按鍵狀態(tài)
         for (i=0;i<4;i++)//每行4個按鍵,所以循環(huán)4次
         {
                  if ((keybuf[keyout][i]&0x0f)==0x00)
                  {           //連續(xù)4次掃描值為0,即4*4ms內(nèi)都是按下狀態(tài)時,可認(rèn)為按鍵已穩(wěn)定的彈起
                     keysta[keyout][i]=1;
                  }

         }//外層循環(huán)大括號
         //執(zhí)行下一次的掃描輸出
         keyout++;
         keyout=keyout&0x03;//索引值加到4即歸零
         switch(keyout)
         {
           case 0:key_out_4=1;key_out_1=0;break;  //key_out_1低電平的時候,開始探測第一行按鍵。順便把上次低電平的拉高。
           case 1:key_out_1=1;key_out_2=0;break;  //
           case 2:key_out_2=1;key_out_3=0;break;
           case 3:key_out_3=1;key_out_4=0;break;
           default:break;
         }//switch后大括號

}//中斷大括號

評分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎勵!

查看全部評分

回復(fù)

使用道具 舉報

ID:284226 發(fā)表于 2023-3-30 22:02 | 顯示全部樓層
你好。請問if ((keybuf[keyout][i]&0x0f)==0x00)。這一段為什么一定先要按位與了。才能進(jìn)行進(jìn)行比較呢。就不能這樣直接比較嗎?if ((keybuf[keyout][i])==0x00)
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

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

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