|
實驗目的
①學習如何配置鍵盤控制器的寄存器
②掌握鍵盤掃描程序的實現過程
實驗內容
①熟悉PXA270提供的鍵盤接口
②分析Eeliod實驗平臺的鍵盤原理圖
③參考示例程序實現矩陣鍵盤掃描,利用數碼管顯示區分不同按鍵
④編譯程序,下載執行,驗證程序工作是否正常
實驗原理
①鍵盤控制
矩陣鍵盤的掃描方式有多種,逐行掃描,翻轉掃描等,本實驗中由于PXA270自帶了鍵盤控制器,且輸入輸出口是單向的,所以只能采用逐行掃描方式。本實驗采用手動掃描,不利用中斷,掃描控制方式與一般的矩陣鍵盤掃描方式一樣,都是列線上逐位送出高電平,行線讀取電平值,如果讀取到高電平則說明在當前列線和讀到的行線交叉點的按鍵被按下了。該實驗主要工作是設置鍵盤控制器相應的寄存器和讀取相應的寄存器。通過設置鍵盤接口寄存器KPC中相應的位來控制矩陣鍵盤4個列信號逐位為高,通過讀取矩陣鍵盤寄存器KPMK中相應的位來判斷矩陣鍵盤4個行信號的高低,進而根據當前的列信號狀態來確定按鍵的物理坐標。
②數碼管控制
數碼管控制與實驗一中的數碼管控制方法一樣。
實驗步驟
第一步 分析代碼
結合以上說明,對本實驗提供的示例代碼分析,深入理解針對具體的硬件實現,軟件是如何配合工作的。
第二步 程序的編譯和下載
利用ADS打開示例工程文件,執行Project→Make,編譯、鏈接生成可執行映像文件
第三步 觀察系統運行情況,對系統進行源碼調試
程序說明
①鍵盤程序
鍵盤程序通過依次給出列線高電平讀行線電平狀態來判斷當前按下的按鍵的位置,通過讀寫相應的寄存器即可,由于鍵盤實際連線對應的IO口實際上不是連續的,導致須通過4次判斷來完成,而不是利用循環實現。
②數碼管程序
數碼管程序在實驗一中已經寫過,本次實驗可以直接使用
③主程序
主程序為一死循環,通過觸發手動鍵盤掃描函數,讀取到鍵盤按下的按鍵,判斷鍵值,進行相應的處理
程序源代碼、注釋
①鍵盤程序
1)MyKeypad.h
#ifndef __MyKeypad_h__
#define __MyKeypad_h__
extern unsigned char KeypadScan(void);
#endif
2)MyKeypad.c
#define KPC_VALUE (*((volatile unsigned int *)(0x41500000))) //鍵盤接口控制寄存器
#define KPMK_VALUE (*((volatile unsigned int *)(0x41500018))) //矩陣鍵盤寄存器,讀取掃描的狀態
//這句宏定義控制鍵盤掃描返回值,不注釋時返回是4x4矩陣鍵盤的實際物理坐標,從上到下從左到右為0x00~0x0F
//注釋掉后返回的是4x4矩陣鍵盤按鍵上印刷的ASCII字符
//#define KEYPAD_RETPHY
void Delay(unsigned int x)
{
unsignedint i, j, k;
for(i =0; i <=x; i++)
for (j = 0; j <0xff; j++)
for(k = 0; k <0xff; k++)
;
}
unsigned char KeypadScan(void)
{
unsignedshort int inRow;
//掃描第一列
KPC_VALUE&= 0xFFE01FFF; //先將列線全復位拉低
KPC_VALUE|= (0x01 << 13); //再將列線第一列置1
Delay(1);
inRow= KPMK_VALUE;
Delay(1);
if(inRow== KPMK_VALUE) //消抖后還相等表明確實有按鍵按下
{
switch(inRow & 0xFF)
{
#ifdefKEYPAD_RETPHY
//注意這里返回的是掃描到的按鍵的物理坐標,從鍵盤左上角到右下角分別為0x00~0x0F
case 0x01: return 0x00;
case 0x02: return 0x04;
case 0x04: return 0x08;
case 0x20: return 0x0C;
default:;
#else
//注意這里返回的是鍵盤上印刷的字符的ASCII
case 0x01: return '1';
case 0x02: return '4';
case 0x04: return '7';
case 0x20: return '*';
default:;
#endif
}
}
//掃描第二列
KPC_VALUE&= 0xFFE01FFF; //先將列線全復位拉低
KPC_VALUE|= (0x01 << 14); //再將列線第二列置1
Delay(1);
inRow= KPMK_VALUE;
Delay(1);
if(inRow== KPMK_VALUE) //消抖后還相等表明確實有按鍵按下
{
switch(inRow & 0xFF)
{
#ifdefKEYPAD_RETPHY
//注意這里返回的是掃描到的按鍵的物理坐標,從鍵盤左上角到右下角分別為0x00~0x0F
case 0x01: return 0x01;
case 0x02: return 0x05;
case 0x04: return 0x09;
case 0x20: return 0x0D;
default:;
#else
//注意這里返回的是鍵盤上印刷的字符的ASCII
case 0x01: return '2';
case 0x02: return '5';
case 0x04: return '8';
case 0x20: return '0';
default:;
#endif
}
}
//掃描第三列
KPC_VALUE&= 0xFFE01FFF; //先將列線全復位拉低
KPC_VALUE|= (0x01 << 15); //再將列線第三列置1
Delay(1);
inRow= KPMK_VALUE;
Delay(1);
if(inRow== KPMK_VALUE) //消抖后還相等表明確實有按鍵按下
{
switch(inRow & 0xFF)
{
#ifdefKEYPAD_RETPHY
//注意這里返回的是掃描到的按鍵的物理坐標,從鍵盤左上角到右下角分別為0x00~0x0F
case 0x01: return 0x03;
case 0x02: return 0x06;
case 0x04: return 0x0A;
case 0x20: return 0x0E;
default:;
#else
//注意這里返回的是鍵盤上印刷的字符的ASCII
case 0x01: return '3';
case 0x02: return '6';
case 0x04: return '9';
case 0x20: return '#';
default:;
#endif
}
}
//掃描第四列
KPC_VALUE&= 0xFFE01FFF; //先將列線全復位拉低
KPC_VALUE|= (0x01 << 19); //再將列線第四列置1
Delay(1);
inRow= KPMK_VALUE;
Delay(1);
if(inRow== KPMK_VALUE) //消抖后還相等表明確實有按鍵按下
{
switch(inRow & 0xFF)
{
#ifdefKEYPAD_RETPHY
//注意這里返回的是掃描到的按鍵的物理坐標,從鍵盤左上角到右下角分別為0x00~0x0F
case 0x01: return 0x03;
case 0x02: return 0x07;
case 0x04: return 0x0B;
case 0x20: return 0x0F;
default:;
#else
//注意這里返回的是鍵盤上印刷的字符的ASCII
case 0x01: return 'A';
case 0x02: return 'B';
case 0x04: return 'C';
case 0x20: return 'D';
default:;
#endif
}
}
return0xFF;
}
②數碼管程序
本次實驗使用的數碼管程序為實驗一中的數碼管程序,可以直接使用。
③主函數
#include "SegLed.h"
#include "MyKeypad.h"
int main()
{
unsignedchar keyValue;
shorttempDisp = 0;
//這幾句用于調試時單步執行查看結果
SegLedDispNum(123,DISP_BLANKING);
SegLedDispNum(23,DISP_BLANKING);
SegLedDispNum(3,DISP_BLANKING);
SegLedDispNum(0,DISP_BLANKING);
while(1)
{
//手動掃描一次矩陣鍵盤,得到按鍵的ASCII碼
keyValue = KeypadScan();
switch(keyValue)
{
//普通數字鍵
case'0':
case'1':
case'2':
case'3':
case'4':
case'5':
case'6':
case'7':
case'8':
case'9':
{
tempDisp = tempDisp * 10 + keyValue - '0';
if(tempDisp > 9999)
tempDisp= 0;
SegLedDispNum(tempDisp, DISP_BLANKING);
break;
}
//取消鍵
case'*':
{
break;
}
//確認鍵
case'#':
{
break;
}
//清零鍵
case'A':
{
tempDisp = 0;
SegLedDispNum(tempDisp, DISP_BLANKING);
break;
}
//退位鍵
case'B':
{
tempDisp /= 10;
SegLedDispNum(tempDisp, DISP_BLANKING);
break;
}
case'C':
{
break;
}
case'D':
{
break;
}
default:
break;
} //endof switch(keyValue)
} //end of while(1)
} //endof main()
總結
在鍵盤程序中,在語句中間定義了變量,編譯時提示錯誤,看錯誤的提示,沒有發現問題,后來突然想到之前Keil中在語句中間定義變量C51的編譯器也提示錯誤,將變量定義放在函數開頭,果然編譯正確。
|
-
-
嵌入式實驗報告.rar
2016-3-14 16:47 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
34.79 KB, 下載次數: 8, 下載積分: 黑幣 -5
|