按鍵為什么要消抖?


原理圖分析

按鍵原理圖

根據原理圖,當按鍵沒有按下的時候,單片機引腳BTN1通過10K的電阻接VCC,為高電平;當按鍵按下的時候,BTN1通過10K的電阻接地,為低電平,此時這個10K的電阻起限流作用,一般程序限流電阻。那么理想情況下,按鍵沒有按下的時候為高電平1,按下為低電平0,但是實際情況下,由於機械的抖動,實際情況產生的波形如下圖所示:

按下時的波形

信號由於機械的抖動,導致在10之間多次跳變,一般抖動時間為5-10ms。單片機的處理速度很快,如果不做處理,那么會導致程序多次執行按鍵后的操作,從而導致邏輯錯誤。例如,要實現按下燈亮,再次按下燈滅,如果不消抖,就可能導致一次按下,多次處理,燈的開關狀態就有可能沒有變化。

實現按鍵消抖

一個簡單的消抖辦法是檢測到按鍵按下,則等待10ms之后,再次檢測是否在按下狀態,如果是按下的狀態,那么才確定是在按下狀態。偽代碼如下:

if (key == 0) {			//檢測到按鍵按下
	DelayMs(10);		//等待10個毫秒
	if (key == 0) {		//按鍵仍然保持在按下的狀態
		led = !led;		//切換LED的開關狀態
		while (key == 0);	//等待松手
	}
}

編寫程序並測試

#include <ioCC2530.h> 

#define LED1   P1_0     //定義LED1所在引腳
#define KEY1   P0_1     //定義BTN1所在引腳

void DelayMs(int ms)
{
    while (ms--) {
        volatile int x = 500;//注意:這個數字是估計的,不准確
        while (x--);
    }
}

void main(void)
{
    //配置P0_1引腳的按鍵1 
    P0SEL &= ~0x02; //普通GPIO模式<0為IO模式,1為外設模式>
    P0DIR &= ~0x02; //輸入功能<0為輸入,1為輸出>
    P0INP &= ~0x02; //上拉或下拉模式<0為上拉或下拉模式,1為三態模式>

    //配置P1_0引腳的LED1
    P1SEL &= ~0x01; //普通GPIO模式<0為IO模式,1為外設模式>
    P1DIR |= 0x01;  //輸出功能<0為輸入,1為輸出>
    P1INP &= ~0x01; //上拉或下拉模式<0為上拉或下拉模式,1為三態模式>
    
    P2INP |= 0xe0;  //P0,P1,P2都設置為上拉模式
    
    while (1)
    {
        if (0 == KEY1) {
            DelayMs(10);
            if (0 == KEY1) {
                LED1 = !LED1;
                while (0 == KEY1);
            }
        } 
    }
}

注意事項

上面這個方法比較常用,但是存在如下問題:

  • 如果用戶一直按着,會導致程序停在等待松手的位置。
  • 在等待10ms期間,程序什么也不能做,浪費了處理器的性能。

下一篇介紹一個比較靠譜的按鍵檢測方法。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM