云主機(jī) 做網(wǎng)站鏈接交換公司
🎬 秋野醬:《個(gè)人主頁》
🔥 個(gè)人專欄:《Java專欄》《Python專欄》
??心若有所向往,何懼道阻且長
文章目錄
- 矩陣按鍵
- 原理圖
- 按鍵狀態(tài)檢測
- 單行按鍵狀態(tài)檢測
- 多行按鍵狀態(tài)檢測
- 狀態(tài)記錄
- 狀態(tài)優(yōu)化
- 循環(huán)優(yōu)化
矩陣按鍵
矩陣鍵盤是一種常見的數(shù)字輸入設(shè)備,由多行多列的按鍵組成。每個(gè)按鍵都有一個(gè)唯一的行列坐標(biāo),通過行列坐標(biāo)可以確定按鍵的編號,從而實(shí)現(xiàn)對數(shù)字或字母的輸入。
原理圖
矩陣鍵盤的基本結(jié)構(gòu)包括按鍵、行引腳和列引腳。按鍵一般是機(jī)械按鍵或觸摸按鍵,行引腳和列引腳分別與矩陣鍵盤的行和列相連,用于檢測按鍵的輸入狀態(tài)。
按鍵狀態(tài)檢測
單個(gè)按鍵狀態(tài)檢測
● 輸出端的電平
● 輸入端的狀態(tài)
● 按鍵抬起
通過按鍵抬起時(shí)的狀態(tài),我們分析輸入端的電平信號,來確定抬起時(shí)輸入端的默認(rèn)電平狀態(tài)。
通過按鍵按下時(shí)的狀態(tài),我們分析輸入端的電平信號,來確定按下時(shí)輸入端的默認(rèn)電平狀態(tài)。
通過分析確認(rèn),默認(rèn)輸出端和輸入端都是高電平;
● 當(dāng)輸出端輸出低電平時(shí),輸入端為高電平,則開關(guān)為抬起狀態(tài);
● 當(dāng)輸出端輸出低電平時(shí),輸入端為低電平,則開關(guān)為按下狀態(tài);
單行按鍵狀態(tài)檢測
通過逐一檢測輸入端的狀態(tài),來判斷按鍵是否按下。
多行按鍵狀態(tài)檢測
首先,將第一行輸出低電平,其余行設(shè)置為高電平。目的是為了只測試第一行的按鍵狀態(tài)。
然后,將第二行輸出低電平,其余行設(shè)置為高電平。目的是為了只測試第二行的按鍵狀態(tài)。
接著,將第三行輸出低電平,其余行設(shè)置為高電平。目的是為了只測試第三行的按鍵狀態(tài)。
最后,將第四行輸出低電平,其余行設(shè)置為高電平。目的是為了只測試第四行的按鍵狀態(tài)。
狀態(tài)記錄
通過自定義狀態(tài)來記錄按鍵狀態(tài)
// 記錄16個(gè)按鍵狀態(tài),0為按下,1為抬起
u16 key_state = 0xFFFF;......void scan() {
// 初始都是 高電平ROW_COL_RESET();NOP1();// ROW1// 給 row1 低電平,讀取COL1的值ROW1 = 0;NOP1();// 當(dāng)前是UP,當(dāng)之前是DOWN,則為UP// 當(dāng)前是DOWN,當(dāng)之前是UP,則為DOWN if(COL1 != (key_state & 0x01) >> 0) {if(COL1) {// 修改當(dāng)前狀態(tài)為UPkey_state |= 0x01;printf("K1 Up\r\n");} else {// 修改當(dāng)前狀態(tài)為DOWNkey_state &= ~0x01;printf("K1 Down\r\n");}}......
}
狀態(tài)優(yōu)化
通過define優(yōu)化一些數(shù)值的操作,方便在后續(xù)看代碼時(shí)方便理解,提高代碼的閱讀性。
// 記錄16個(gè)按鍵狀態(tài),0為按下,1為抬起
u16 key_state = 0xFFFF;#define KEY_UP 1
#define KEY_DOWN 0
// 第n個(gè)按鍵的狀態(tài)
#define KEY_STATE(n) ((key_state & (1 << n)) >> n)
#define SET_KEY_UP(n) (key_state |= (1 << n))
#define SET_KEY_DOWN(n) (key_state &= ~(1 << n))#define ROW_COL_RESET() {ROW1=1,ROW2=1,ROW3=1,ROW4=1;COL1=1,COL2=1,COL3=1,COL4=1;}......void scan() {// 初始都是 高電平ROW_COL_RESET();NOP1();// ROW1// 給 row1 低電平,讀取COL1的值ROW1 = 0;NOP1();// 當(dāng)前是UP,當(dāng)之前是DOWN,則為UP// 當(dāng)前是DOWN,當(dāng)之前是UP,則為DOWNif(COL1 != KEY_STATE(0)) {if(COL1) {// 修改當(dāng)前狀態(tài)為UPSET_KEY_UP(0);printf("K1 Up\r\n");} else {// 修改當(dāng)前狀態(tài)為DOWNSET_KEY_DOWN(0);printf("K1 Down\r\n");}}......
}
循環(huán)優(yōu)化
操作的按鍵眾多,通過循環(huán)的方式來操控每一個(gè)按鍵,減少代碼量,方便維護(hù)。
#define ROW 4
#define COL 4// 記錄16個(gè)按鍵狀態(tài),0為按下,1為抬起
u16 key_state = 0xFFFF;#define KEY_UP 1
#define KEY_DOWN 0
// 第n個(gè)按鍵的狀態(tài)
#define KEY_STATE(r, c) ((key_state & (1 << (r * ROW + c))) >> (r * ROW + c))
#define SET_KEY_UP(r, c) (key_state |= (1 << (r * ROW + c)))
#define SET_KEY_DOWN(r, c) (key_state &= ~(1 << (r * ROW + c)))#define ROW_COL_RESET() {ROW1=1,ROW2=1,ROW3=1,ROW4=1;COL1=1,COL2=1,COL3=1,COL4=1;}void scan() {u8 i, j;for(i = 0; i < ROW; i++) {// 初始都是 高電平ROW_COL_RESET();NOP1();ROW_ON(i);for(j = 0; j < COL; j++) {// 當(dāng)前是UP,當(dāng)之前是DOWN,則為UP// 當(dāng)前是DOWN,當(dāng)之前是UP,則為DOWNif(COL_STATE(j) != KEY_STATE(i, j)) {if(COL_STATE(j)) {// 修改當(dāng)前狀態(tài)為UPSET_KEY_UP(i, j);printf("(%d, %d) Up\r\n", (int)i, (int)j);} else {// 修改當(dāng)前狀態(tài)為DOWNSET_KEY_DOWN(i, j);printf("(%d, %d) Down\r\n", (int)i, (int)j);}}}}
}