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) { // 二次確認
// 處理按鍵
}
}
機械按鍵彈跳:按下/釋放瞬間,金屬觸點會發生微秒~毫秒級的多次開合抖動。若無消抖,單次掃描可能讀到抖動邊緣,誤判為多次按鍵或錯誤鍵值。
temp != 0xF0)。delayms(10) 等待抖動穩定(典型 5~20ms)。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) | 未等抖動結束,仍誤判 |
| 未等待釋放 | 長按視為連續多次點擊 |
| 行列接線反接/無上拉電阻 | 掃描邏輯全錯,讀不到按鍵 |