這個例程也是開發闆上面的一個經典例程,我對程式的架構進行了修改,更适合以後的調用。具體的4*4鍵盤掃描原理較為基礎這裡不再贅述,這裡我認為比較重要的是要養成一個良好的寫程式的習慣,想4*4鍵盤掃描這樣的函數可以寫成一個固定的C或者H檔案,便于以後調用。先看看主程式:
/***********************************************
程式功能:掃描4X4鍵盤并将鍵值在數位管上顯示
------------------------------------------------
測試說明:按動K1~K16按鍵,觀察數位管顯示
************************************************/
#include <msp430x14x.h>
#include "Keypad.C"
//數位管7位段碼:0--f
unsigned char scandata[16] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
//記錄顯示位數的全局變量
unsigned char cnt = 0;
//顯示緩存
unsigned char Dispbuf[2];
//引用外部變量的聲明
extern unsigned char key_Pressed;
extern unsigned char key_val;
extern unsigned char key_Flag;
/********************主函數********************/
void main(void)
{
/*下面六行程式關閉所有的IO口*/
P1DIR = 0XFF;P1OUT = 0XFF;
P2DIR = 0XFF;P2OUT = 0XFF;
P3DIR = 0XFF;P3OUT = 0XFF;
P4DIR = 0XFF;P4OUT = 0XFF;
P5DIR = 0XFF;P5OUT = 0XFF;
P6DIR = 0XFF;P6OUT = 0XFF;
P6DIR |= BIT2;P6OUT |= BIT2; //關閉電平轉換
WDTCTL = WDT_ADLY_1_9; //設定内部看門狗工作在定時器模式,1.9ms中斷一次
IE1 |= WDTIE; //使能看門狗中斷
_EINT(); //打開全局中斷
Init_Keypad();
while(1)
{
Key_Event();
if(key_Flag == 1)
{
key_Flag = 0;
Dispbuf[1] = key_val / 10;
Dispbuf[0] = key_val % 10;
}
}
}
/*******************************************
函數名稱:watchdog_timer
功 能:看門狗中斷服務函數,在這裡輸出數位管的
段選和位選信号
參 數:無
傳回值 :無
********************************************/
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{
P4OUT = 0xff;
P5OUT = scandata[Dispbuf[cnt]]; //輸出段選信号
P4OUT &= ~(1 << (cnt+2)); //輸出位選信号
cnt++; //位計數變量在0~1之間循環
if(cnt == 2) cnt = 0;
主程式較為簡單,具體的原理參見上一個筆記,在主程式中與鍵盤掃描相關的函數被擊中在Keypad.C中,需要說明的是在主函數中需要對Keypad.C的部分變量做聲明,這樣才能使用Keypad.C中的變量。Keypad.C代碼如下:
/********************************************************
4*4鍵盤掃描函數
作者:孫浩
修改時間:2010.8.2
程式說明:
此程式以開發闆的例程做部分修改,更友善程式調用。
在調用之前需要注意需要在主函數中對程式中使用的變量做外部變量聲明
需要在主函數中聲明的變量如下:
//引用外部變量的聲明
extern unsigned char key_Pressed; //按鍵是否被按下:1--是,0--否
extern unsigned char key_val; //存放鍵值
extern unsigned char key_Flag; //按鍵是否已放開:1--是,0--否
另外對應的鍵值可以在本檔案的全局變量中修改,隻需要對應修改
數組uchar key_Map[]的對應的值即可。
調用示例如下:
Init_Keypad(); //先進行初始化
while(1)
{
Key_Event(); //在死循環中進行鍵值掃描
if(key_Flag == 1)//用來判斷有無按鍵按下,進而讀取鍵值進行操作
{
key_Flag = 0;//key_Flag需要手動清零
}
}
**********************************************************/
#include <msp430x14x.h>
//相應的函數聲明
void Init_Keypad(void);//鍵盤初始化
void Check_Key(void);
void delay();
void Key_Event(void);//讀取鍵盤函數,在使用時通過此函數進行鍵盤掃描
//選擇對應的端口
#define KEYOUT P1OUT
#define KEYIN P1IN
#define KEYDIR P1DIR
typedef unsigned char uchar;
typedef unsigned int uint;
/***************全局變量***************/
uchar key_Pressed; //按鍵是否被按下:1--是,0--否
uchar key_val; //存放鍵值
uchar key_Flag; //按鍵是否已放開:1--是,0--否
//設定鍵盤邏輯鍵值與程式計算鍵值的映射
uchar key_Map[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
函數名稱:Init_Keypad
功 能:初始化掃描鍵盤的IO端口
void Init_Keypad(void)
{
KEYDIR = 0xf0; //KEY.0~KEY.3設定為輸入狀态, KEY.4~KEY.7設定為輸出狀态
KEYOUT |= 0xf0; // KEY.4~KEY.7輸出高電平
key_Flag = 0;
key_Pressed = 0;
key_val = 0;
/*********************************************
* Check_Key(),檢查按鍵,确認鍵值
*********************************************/
函數名稱:Check_Key
功 能:掃描鍵盤的IO端口,獲得鍵值
void Check_Key(void)
uchar row ,col,tmp1,tmp2;
tmp1 = 0x80;
for(row = 0;row < 4;row++) //行掃描
KEYOUT = 0xf0; //KEY.4~KEY.7輸出全1
KEYOUT -= tmp1; //KEY.4~p1.7輸出四位中有一個為0
tmp1 >>=1;
if ((KEYIN & 0x0f) < 0x0f) //是否KEYIN的KEY.0~KEY.3中有一位為0
{
tmp2 = 0x01; // tmp2用于檢測出那一位為0
for(col = 0;col < 4;col++) // 列檢測
{
if((KEYIN & tmp2) == 0x00) // 是否是該列,等于0為是
{
key_val = key_Map[row * 4 + col]; // 擷取鍵值
return; // 退出循環
}
tmp2 <<= 1; // tmp2右移1位
}
}
函數名稱:delay
功 能:延時約15ms,完成消抖功能
void delay()
uint tmp;
for(tmp = 12000;tmp > 0;tmp--);
函數名稱:Key_Event
功 能:檢測按鍵,并擷取鍵值
void Key_Event(void)
uchar tmp;
KEYOUT &= 0x00; // 設定KEYOUT全為0,等待按鍵輸入
tmp = KEYIN; // 擷取 p1IN
if ((key_Pressed == 0x00)&&((tmp & 0x0f) < 0x0f)) //如果有鍵按下
{
key_Pressed = 1; // 如果有按鍵按下,設定key_Pressed辨別
delay(); //消除抖動
Check_Key(); // 調用check_Key(),擷取鍵值
}
else if ((key_Pressed == 1)&&((tmp & 0x0f) == 0x0f)) //如果按鍵已經釋放
key_Pressed = 0; // 清除key_Pressed辨別
key_Flag = 1; // 設定key_Flag辨別
else
_NOP();
具體的注意提防都已經在注釋中做了說明,在原來的程式中這個檔案是分為Keypad.C和Keypad.h兩個檔案,鍵盤掃描函數的聲明單獨為一個頭檔案,我覺得并不是特别需要。源程式中全局變量是單獨列為一個頭檔案gdata.h的。這樣在全局變量比較多的情況下可以使程式更有條理可以參考。
本文轉自emouse部落格園部落格,原文連結:http://www.cnblogs.com/emouse/archive/2010/08/02/2198218.html,如需轉載請自行聯系原作者