建站abc做的網(wǎng)站穩(wěn)定國內(nèi)手機(jī)怎么上google瀏覽器
這里寫目錄標(biāo)題
- 1、矩陣按鍵
- 2、代碼片段分析
1、矩陣按鍵
通過將4x4矩陣按鍵的每一行依次設(shè)為低電平,同時保持其它行為高電平,然后讀取所有列的電平狀態(tài),可以檢測到哪個按鍵被按下。如果某列變?yōu)榈碗娖?#xff0c;說明對應(yīng)行和列的按鍵被按下。這樣逐行掃描即可確定按鍵的位置。
2、代碼片段分析
/*********************************************************************@Function : 矩陣鍵盤行列讀寫操作@Parameter : ReadIo :讀輸入的IOWirteIo :寫輸出的IO@Return : 行列IO輸出狀態(tài)
**********************************************************************/
uint8_t GPIO_KEY_RW(uint16_t ReadIo,uint16_t WirteIo)
{uint16_t Wdata=0,Rdata=0; /* 寫操作 */KeyBordSetOut(KEY_ALL); //設(shè)置IOif(WirteIo==0x0f00)GPIO_SetBits(GPIOE,KEY_LINE); //寫行else GPIO_ResetBits(GPIOE,KEY_LIST); //寫列 Wdata = GPIO_ReadOutputData(GPIOE);//讀輸出 Wdata &= WirteIo; //取有效區(qū)域/* 讀操作 */KeyBordSetIn(ReadIo); //設(shè)置IO Rdata = GPIO_ReadInputData(GPIOE); //讀輸入Rdata &= ReadIo; //取有效區(qū)域/* 狀態(tài)返回 */Rdata |= Wdata; //合并兩次讀取的數(shù)據(jù)return (uint8_t)(Rdata>>8); //移位返回
}
初始化:
Wdata 和 Rdata 初始化為 0。
寫操作:
檢查 WirteIo 是否為 0x0f00(二進(jìn)制:0000111100000000):
如果是,則設(shè)置 GPIOE 中對應(yīng) KEY_LINE 的位(具體位取決于 KEY_LINE 的定義)。
如果不是,則復(fù)位 GPIOE 中對應(yīng) KEY_LIST 的位(具體位取決于 KEY_LIST 的定義)。
讀取 GPIOE 的輸出數(shù)據(jù)到 Wdata。
Wdata 與 WirteIo 進(jìn)行與操作,保留有效區(qū)域的數(shù)據(jù)。
讀操作:
使用 ReadIo 設(shè)置IO方向。
讀取 GPIOE 的輸入數(shù)據(jù)到 Rdata。
Rdata 與 ReadIo 進(jìn)行與操作,保留有效區(qū)域的數(shù)據(jù)。
狀態(tài)返回:
將 Wdata 和 Rdata 進(jìn)行或操作,合并兩次讀取的數(shù)據(jù)。
返回 Rdata 右移8位后的值。
假設(shè)按下第一個按鍵
假設(shè)按下的是第一個按鍵,具體的步驟如下:
初始化:
Wdata = 0
Rdata = 0
寫操作:
WirteIo == 0x0f00 假設(shè)為真,則設(shè)置 GPIOE 對應(yīng) KEY_LINE 的位。
讀取 GPIOE 輸出數(shù)據(jù):
假設(shè) GPIOE 輸出數(shù)據(jù)為 0000111100000000(二進(jìn)制)。
Wdata &= WirteIo:
Wdata = 0000111100000000 & 0000111100000000 = 0000111100000000
讀操作:
設(shè)置IO方向,具體操作取決于 KeyBordSetIn 函數(shù)。
讀取 GPIOE 輸入數(shù)據(jù):
假設(shè)按下第一個按鍵時,GPIOE 輸入數(shù)據(jù)為 0000000100000000(二進(jìn)制)。
Rdata &= ReadIo:
Rdata = 0000000100000000 & ReadIo(假設(shè) ReadIo 為 0000000100000000),結(jié)果 Rdata = 0000000100000000
狀態(tài)返回:
Rdata |= Wdata:
Rdata = 0000000100000000 | 0000111100000000 = 0000111100000000
返回值:
將 Rdata 右移8位后返回:Rdata >> 8 = 00001111
所以函數(shù)返回值為 0x0F(二進(jìn)制:00001111)
/*********************************************************************@Function : 矩陣鍵盤鍵值掃描@Parameter : N/A@Return : 鍵值
**********************************************************************/
uint8_t KeyBoardScan(void)
{uint8_t KeyValue=0,Key=0;uint8_t a = 0;/* 檢測鍵盤是否有按鍵按下,0x0f表示所有列都未按下 */if(GPIO_KEY_RW(KEY_LIST,KEY_LINE)!=0x0f){/* 測試列狀態(tài) */Key = GPIO_KEY_RW(KEY_LIST,KEY_LINE); // 讀取列的狀態(tài)/* 判斷列狀態(tài)并映射為按鍵值 */switch(Key){case(0x1F): // 第一列所有行都按下KeyValue = 1; // 對應(yīng)鍵值為1break;case(0x2F): // 第二列所有行都按下KeyValue = 2; // 對應(yīng)鍵值為2break;case(0x4F): // 第三列所有行都按下KeyValue = 3; // 對應(yīng)鍵值為3break;case(0x8F): // 第四列所有行都按下KeyValue = 4; // 對應(yīng)鍵值為4break;}/* 測試行狀態(tài) */Key = GPIO_KEY_RW(KEY_LINE,KEY_LIST); // 讀取行的狀態(tài)/* 判斷行狀態(tài)并映射為按鍵值 */switch(Key){case(0x0E): // 第一行所有列都按下KeyValue = KeyValue; // 保持當(dāng)前列的鍵值不變break;case(0x0D): // 第二行所有列都按下KeyValue = KeyValue + 4; // 當(dāng)前列的鍵值加4,對應(yīng)第二行break;case(0x0B): // 第三行所有列都按下KeyValue = KeyValue + 8; // 當(dāng)前列的鍵值加8,對應(yīng)第三行break;case(0x07): // 第四行所有列都按下KeyValue = KeyValue + 12; // 當(dāng)前列的鍵值加12,對應(yīng)第四行break;}/* 按鍵松手檢測 */while((a < 50) && (Key != 0x00)) // 循環(huán)檢測按鍵是否松手,最多檢測50次{delay_ms(5); // 延時5毫秒Key = GPIO_KEY_RW(KEY_LINE,KEY_LIST); // 再次讀取行的狀態(tài)a += 1; // 計數(shù)器加1}}/* 返回鍵值 */return KeyValue;
}