|
實(shí)驗(yàn)?zāi)康?/font>
①學(xué)習(xí)如何配置鍵盤控制器的寄存器
②掌握鍵盤掃描程序的實(shí)現(xiàn)過程
實(shí)驗(yàn)內(nèi)容
①熟悉PXA270提供的鍵盤接口
②分析Eeliod實(shí)驗(yàn)平臺(tái)的鍵盤原理圖
③參考示例程序?qū)崿F(xiàn)矩陣鍵盤掃描,利用數(shù)碼管顯示區(qū)分不同按鍵
④編譯程序,下載執(zhí)行,驗(yàn)證程序工作是否正常
實(shí)驗(yàn)原理
①鍵盤控制
矩陣鍵盤的掃描方式有多種,逐行掃描,翻轉(zhuǎn)掃描等,本實(shí)驗(yàn)中由于PXA270自帶了鍵盤控制器,且輸入輸出口是單向的,所以只能采用逐行掃描方式。本實(shí)驗(yàn)采用手動(dòng)掃描,不利用中斷,掃描控制方式與一般的矩陣鍵盤掃描方式一樣,都是列線上逐位送出高電平,行線讀取電平值,如果讀取到高電平則說明在當(dāng)前列線和讀到的行線交叉點(diǎn)的按鍵被按下了。該實(shí)驗(yàn)主要工作是設(shè)置鍵盤控制器相應(yīng)的寄存器和讀取相應(yīng)的寄存器。通過設(shè)置鍵盤接口寄存器KPC中相應(yīng)的位來控制矩陣鍵盤4個(gè)列信號(hào)逐位為高,通過讀取矩陣鍵盤寄存器KPMK中相應(yīng)的位來判斷矩陣鍵盤4個(gè)行信號(hào)的高低,進(jìn)而根據(jù)當(dāng)前的列信號(hào)狀態(tài)來確定按鍵的物理坐標(biāo)。
②數(shù)碼管控制
數(shù)碼管控制與實(shí)驗(yàn)一中的數(shù)碼管控制方法一樣。
實(shí)驗(yàn)步驟
第一步 分析代碼
結(jié)合以上說明,對(duì)本實(shí)驗(yàn)提供的示例代碼分析,深入理解針對(duì)具體的硬件實(shí)現(xiàn),軟件是如何配合工作的。
第二步 程序的編譯和下載
利用ADS打開示例工程文件,執(zhí)行Project→Make,編譯、鏈接生成可執(zhí)行映像文件
第三步 觀察系統(tǒng)運(yùn)行情況,對(duì)系統(tǒng)進(jìn)行源碼調(diào)試
程序說明
①鍵盤程序
鍵盤程序通過依次給出列線高電平讀行線電平狀態(tài)來判斷當(dāng)前按下的按鍵的位置,通過讀寫相應(yīng)的寄存器即可,由于鍵盤實(shí)際連線對(duì)應(yīng)的IO口實(shí)際上不是連續(xù)的,導(dǎo)致須通過4次判斷來完成,而不是利用循環(huán)實(shí)現(xiàn)。
②數(shù)碼管程序
數(shù)碼管程序在實(shí)驗(yàn)一中已經(jīng)寫過,本次實(shí)驗(yàn)可以直接使用
③主程序
主程序?yàn)橐凰姥h(huán),通過觸發(fā)手動(dòng)鍵盤掃描函數(shù),讀取到鍵盤按下的按鍵,判斷鍵值,進(jìn)行相應(yīng)的處理
程序源代碼、注釋
①鍵盤程序
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))) //矩陣鍵盤寄存器,讀取掃描的狀態(tài)
//這句宏定義控制鍵盤掃描返回值,不注釋時(shí)返回是4x4矩陣鍵盤的實(shí)際物理坐標(biāo),從上到下從左到右為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; //先將列線全復(fù)位拉低
KPC_VALUE|= (0x01 << 13); //再將列線第一列置1
Delay(1);
inRow= KPMK_VALUE;
Delay(1);
if(inRow== KPMK_VALUE) //消抖后還相等表明確實(shí)有按鍵按下
{
switch(inRow & 0xFF)
{
#ifdefKEYPAD_RETPHY
//注意這里返回的是掃描到的按鍵的物理坐標(biāo),從鍵盤左上角到右下角分別為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; //先將列線全復(fù)位拉低
KPC_VALUE|= (0x01 << 14); //再將列線第二列置1
Delay(1);
inRow= KPMK_VALUE;
Delay(1);
if(inRow== KPMK_VALUE) //消抖后還相等表明確實(shí)有按鍵按下
{
switch(inRow & 0xFF)
{
#ifdefKEYPAD_RETPHY
//注意這里返回的是掃描到的按鍵的物理坐標(biāo),從鍵盤左上角到右下角分別為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; //先將列線全復(fù)位拉低
KPC_VALUE|= (0x01 << 15); //再將列線第三列置1
Delay(1);
inRow= KPMK_VALUE;
Delay(1);
if(inRow== KPMK_VALUE) //消抖后還相等表明確實(shí)有按鍵按下
{
switch(inRow & 0xFF)
{
#ifdefKEYPAD_RETPHY
//注意這里返回的是掃描到的按鍵的物理坐標(biāo),從鍵盤左上角到右下角分別為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; //先將列線全復(fù)位拉低
KPC_VALUE|= (0x01 << 19); //再將列線第四列置1
Delay(1);
inRow= KPMK_VALUE;
Delay(1);
if(inRow== KPMK_VALUE) //消抖后還相等表明確實(shí)有按鍵按下
{
switch(inRow & 0xFF)
{
#ifdefKEYPAD_RETPHY
//注意這里返回的是掃描到的按鍵的物理坐標(biāo),從鍵盤左上角到右下角分別為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;
}
②數(shù)碼管程序
本次實(shí)驗(yàn)使用的數(shù)碼管程序?yàn)閷?shí)驗(yàn)一中的數(shù)碼管程序,可以直接使用。
③主函數(shù)
#include "SegLed.h"
#include "MyKeypad.h"
int main()
{
unsignedchar keyValue;
shorttempDisp = 0;
//這幾句用于調(diào)試時(shí)單步執(zhí)行查看結(jié)果
SegLedDispNum(123,DISP_BLANKING);
SegLedDispNum(23,DISP_BLANKING);
SegLedDispNum(3,DISP_BLANKING);
SegLedDispNum(0,DISP_BLANKING);
while(1)
{
//手動(dòng)掃描一次矩陣鍵盤,得到按鍵的ASCII碼
keyValue = KeypadScan();
switch(keyValue)
{
//普通數(shù)字鍵
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;
}
//確認(rèn)鍵
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()
總結(jié)
在鍵盤程序中,在語(yǔ)句中間定義了變量,編譯時(shí)提示錯(cuò)誤,看錯(cuò)誤的提示,沒有發(fā)現(xiàn)問題,后來突然想到之前Keil中在語(yǔ)句中間定義變量C51的編譯器也提示錯(cuò)誤,將變量定義放在函數(shù)開頭,果然編譯正確。
|
|