這是個矩陣按鍵,按下任意一個按鍵,數碼管顯示從0-F的值。
單片機C語言源程序如下:
- #include<reg52.h>
- sbit ADDR0 = P1^0;
- sbit ADDR1 = P1^1;
- sbit ADDR2 = P1^2;
- sbit ADDR3 = P1^3;
- sbit ENLED = P1^4;
- sbit KeyIn_1 = P2^7;
- sbit KeyIn_2 = P2^6;
- sbit KeyIn_3 = P2^5;
- sbit KeyIn_4 = P2^4;
- sbit KeyOut_1 = P2^3;
- sbit KeyOut_2 = P2^2;
- sbit KeyOut_3 = P2^1;
- sbit KeyOut_4 = P2^0;
- unsigned char code LedChar[16] = { //數碼管真值表
- 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
- 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
- };
- unsigned char keyStatus[4][4] = { //全部矩陣按鍵當前的狀態
- {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
- };
- void main(){
- unsigned char i,j;
- unsigned char cnt = 0;
- unsigned char backUp[4][4] = {{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}}; //按鍵狀態,保存前一次的值
- EA = 1;
- ENLED = 0;
- ADDR3 = 1;
- ADDR2 = 0;
- ADDR1 = 0;
- ADDR0 = 0;
- TMOD = 0x01;
- TH0 = 0xFC;
- TL0 = 0x67;
- ET0 = 1;
- TR0 = 1;
- P0 = LedChar[cnt];
-
- while(1){
- for(i = 0; i < 4; i++){
- for(j = 0;j < 4; j++){
- if(backUp[i][j] != keyStatus[i][j]){
- if(backUp[i][j] == 0){ //按鍵抬起
- cnt++;
- if(cnt >= 16){
- cnt = 0;
- }
- P0 = LedChar[cnt];
- }
- backUp[i][j] = keyStatus[i][j];
- }
- }
- }
- }
- }
- /*T0中斷服務函數,判斷按鍵狀態并消抖*/
- void interruptTimer0() interrupt 1{
- unsigned char i;
- static unsigned char keyOut = 0;
- static unsigned char keyBuff[4][4] = {
- {0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF} //矩陣按鍵掃描緩沖區
- };
- TH0 = 0xFC;
- TL0 = 0x67;
- keyBuff[keyOut][0] = (keyBuff[keyOut][0] << 1) | KeyIn_1; //按位與,將KeyIn_1的最后一位移入緩沖區。按位與的結果:最后1位是0就移入0,是1就移入1。
- keyBuff[keyOut][1] = (keyBuff[keyOut][1] << 1) | KeyIn_2; //按位與,將KeyIn_2的最后一位移入緩沖區。按位與的結果:最后1位是0就移入0,是1就移入1。
- keyBuff[keyOut][2] = (keyBuff[keyOut][2] << 1) | KeyIn_3; //按位與,將KeyIn_3的最后一位移入緩沖區。按位與的結果:最后1位是0就移入0,是1就移入1。
- keyBuff[keyOut][3] = (keyBuff[keyOut][3] << 1) | KeyIn_4; //按位與,將KeyIn_4的最后一位移入緩沖區。按位與的結果:最后1位是0就移入0,是1就移入1。
- //更新消抖狀態
- for(i = 0; i <= 3 ; i++){
- if((keyBuff[keyOut][i] & 0x0F) == 0x00){
- keyStatus[keyOut][i] = 0;
- }
- else if((keyBuff[keyOut][i] & 0x0F) == 0x0F){
- keyStatus[keyOut][i] = 1;
- }
- }
- //執行下一次的掃描輸出
- keyOut++;
- if(keyOut > 4){
- keyOut = 0;
- }
- //根據索引keyOut,釋放當前輸出引腳,拉低下次的輸出引腳。
- switch(keyOut){
- case 0: KeyOut_4 = 1; KeyOut_1 = 0; break;
- case 1: KeyOut_1 = 1; KeyOut_2 = 0; break;
- case 2: KeyOut_2 = 1; KeyOut_3 = 0; break;
- case 3: KeyOut_3 = 1; KeyOut_4 = 0; break;
- default: break;
- }
- }
復制代碼
問題:其中這段代碼放在switch的前面,有一排按鍵按下,數碼管就一直在累加。
雖然keyOut初始值為0,++一次為1,錯過了keyOut為0的判斷,但是KeyOut加到4的時候,就置0了,下一輪,case0就可以覆蓋的到。
- //執行下一次的掃描輸出
- keyOut++;
- if(keyOut > 4){
- keyOut = 0;
- }
復制代碼
這段代碼放到switch后就ok了,但是邏輯上我 實在不明白為什么放在前面就不可以。求各位大神給指點一下,答疑解惑!
|