首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

51 單片機 4x4 矩陣鍵盤掃描:為何需雙重檢測(消抖)?可否省略?

     編輯:程式設計綜合問答

程式碼片段

uchar temp, key;
P3 = 0xFE;        // 1111 1110  掃描第 1 行
temp = P3;
temp = temp & 0xF0; // 取高 4 位 (列)
if (temp != 0xF0) {   // 有按鍵按下
    delayms(10);      // 延時 10ms
    temp = P3;
    temp = temp & 0xF0;
    if (temp != 0xF0) { // 二次確認
        // 處理按鍵
    }
}

為何要「重複兩遍」?

機械按鍵彈跳:按下/釋放瞬間,金屬觸點會發生微秒~毫秒級的多次開合抖動。若無消抖,單次掃描可能讀到抖動邊緣,誤判為多次按鍵或錯誤鍵值。

雙重檢測原理

  1. 第一次偵測到按鍵(temp != 0xF0)。
  2. delayms(10) 等待抖動穩定(典型 5~20ms)。
  3. 第二次掃描確認狀態仍為按下,才認定為有效按鍵。

可不可以刪去一遍?

  • 極不建議:直接刪除會導致按鍵誤觸發、重複輸入、功能錯亂。
  • 若 MCU 主頻極高(如 STM32 72MHz+),可縮短延時至 1~5ms,但雙重檢測邏輯必須保留。
  • 替代方案:硬體消抖(RC 電路、專用消晶片)、軟體狀態機(連續 N 次掃描相同才確認)、定時器中斷掃描(每 1ms 掃描一次,連續 10 次相同才有效)。

完整 4x4 掃描流程(含消抖、鍵值對應)

const uchar keyMap[4][4] = {
    {'1','2','3','A'},
    {'4','5','6','B'},
    {'7','8','9','C'},
    {'*','0','#','D'}
};

uchar KeyScan(void) {
    uchar row, col, temp;
    for (row = 0; row < 4; row++) {
        P3 = ~(0x01 << row); // 逐行拉低 (假設 P3.0-P3.3 接行, P3.4-P3.7 接列, 上拉)
        temp = P3 & 0xF0;
        if (temp != 0xF0) {
            delayms(10);
            temp = P3 & 0xF0;
            if (temp != 0xF0) {
                // 判斷列
                switch (temp) {
                    case 0xE0: col = 0; break; // 1110
                    case 0xD0: col = 1; break; // 1101
                    case 0xB0: col = 2; break; // 1011
                    case 0x70: col = 3; break; // 0111
                    default:   col = 0xFF;
                }
                // 等待釋放 (可選)
                while ((P3 & 0xF0) != 0xF0) delayms(5);
                return keyMap[row][col];
            }
        }
    }
    return 0; // 無按鍵
}

常見錯誤

錯誤後果
刪除二次確認抖動導致單次按下觸發多次事件
延時過短 (< 5ms)未等抖動結束,仍誤判
未等待釋放長按視為連續多次點擊
行列接線反接/無上拉電阻掃描邏輯全錯,讀不到按鍵
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved