|
/*==================硬件電路===============================
*
*說(shuō)明:矩陣鍵盤(pán)為4*4,數(shù)據(jù)口為P2,行線(xiàn)為P2.0-P2.3,列線(xiàn)為P2.4-P2.7
*==========================================================*/
#include<reg52.h>
#include"Define.h"
#include"matrixkeyscan.h"
#define key P1 //矩陣鍵盤(pán)的數(shù)據(jù)口
#define no_key 0xff //無(wú)按鍵按下
#define key_state0 0 //狀態(tài)0,此時(shí)無(wú)按鍵按下
#define key_state1 1 //狀態(tài)1,此時(shí)處于確定按鍵是否按下
#define key_state2 2 //狀態(tài)2,此時(shí)判斷按鍵是否釋放
uchar key_value; //鍵值返回
/*==========================================================
*函數(shù)名稱(chēng):Keyscan()
*功 能:對(duì)矩陣鍵盤(pán)進(jìn)行掃描,掃描方式為狀態(tài)機(jī)+定時(shí)器中斷
*入口參數(shù):
*出口參數(shù):key_value,代表具體的鍵值
*說(shuō) 明:有個(gè)缺陷,剛開(kāi)始數(shù)碼管就亮,還沒(méi)找到是哪里出了問(wèn)題
*==========================================================*/
uchar Keyscan()
{
uchar key_temp;
uchar key1,key2;
uchar keyRetu=0; //返回的按鍵值
static uchar s_keyState=0;
static uint keyTime=0; //按鍵狀態(tài),按鍵按下的時(shí)間計(jì)數(shù)器
//key_temp=no_key;
key=0xf0;
key1=key;
key1=key&0xf0; //確定哪一行的按鍵按下
key=0x0f;
key2=key;
key2=key&0x0f; //確定哪一列的按鍵按下
key_temp=key1|key2; //確定按鍵位置
switch(s_keyState) //檢測(cè)當(dāng)前狀態(tài)
{
case 0: //之前無(wú)按鍵被按下
if(key_temp!=no_key) //說(shuō)明有按鍵按下或者抖動(dòng)
{
s_keyState=1; //轉(zhuǎn)換為狀態(tài)1,然后去判斷是否真的按下
}
break;
case 1: //狀態(tài)1,說(shuō)明之前已經(jīng)有按鍵按下或者抖動(dòng)
if(key_temp!=no_key) //有按鍵按下
{
keyTime++; // 一次10ms
if(keyTime>=3) // 消抖時(shí)間為:SINGLE_KEY_TIME*10ms = 30ms;
{
s_keyState=2; //跳到狀態(tài)2,進(jìn)而判斷是否被釋放 // 如果按鍵時(shí)間超過(guò) 消抖時(shí)間,即判定為按下的按鍵有效。按鍵有效包括兩種:?jiǎn)螕艋蛘唛L(zhǎng)按,進(jìn)入 按鍵狀態(tài)2, 繼續(xù)判定到底是那種有效按鍵
}
}else //確實(shí)有按鍵被按下
{
s_keyState=0; //返回到狀態(tài)0,
}
break;
case 2: //狀態(tài)2,判斷是否被釋放
if(key_temp==no_key) //檢測(cè)到按鍵松開(kāi)
{
s_keyState=0; //狀態(tài)轉(zhuǎn)到狀態(tài)0
}else
{
keyRetu=1; //輸出1
s_keyState=3; //狀態(tài)轉(zhuǎn)到狀態(tài)3
}
break;
case 3:
if(key_temp==no_key) //檢測(cè)到按鍵松開(kāi)
{
s_keyState=0; //狀態(tài)轉(zhuǎn)到狀態(tài)0
keyRetu=1;
}else
{
//keyTime++;
if(++keyTime>200)
{
keyTime=0;
keyRetu=2; // 輸出2
s_keyState=4;
}
}
case 4:
if(key_temp==no_key) //檢測(cè)到按鍵松開(kāi)
{
s_keyState=0; //狀態(tài)轉(zhuǎn)到狀態(tài)0,完成
//keyTime=0;
}
break;
default: // 特殊情況:key_state是其他值得情況,清零key_state。這種情況一般出現(xiàn)在 沒(méi)有初始化key_state,第一次執(zhí)行這個(gè)函數(shù)的時(shí)候
s_keyState=0; //狀態(tài)轉(zhuǎn)到狀態(tài)0,
break;
}
if(keyRetu==1)
{
switch(key_temp) //當(dāng)確定按鍵按下后,列舉所有的按鍵情況
{
case 0xee: key_value=0;break;//1110 1110
case 0xde: key_value=1;break;//1101 1110
case 0xbe: key_value=2;break;
case 0x7e: key_value=3;break;
case 0xed: key_value=4;break;
case 0xdd: key_value=5;break;
case 0xbd: key_value=6;break;
case 0x7d: key_value=7;break;
case 0xeb: key_value=8;break;
case 0xdb: key_value=9;break;
case 0xbb: key_value=10;break;
case 0x7b: key_value=11;break;
case 0xe7: key_value=12;break;
case 0xd7: key_value=13;break;
case 0xb7: key_value=14;break;
case 0x77: key_value=15;break;
}
}
if(keyRetu==2)
{
switch(key_temp) //當(dāng)確定按鍵按下后,列舉所有的按鍵情況
{
case 0xee: key_value=100;break;//1110 1110
case 0xde: key_value=101;break;//1101 1110
case 0xbe: key_value=102;break;
case 0x7e: key_value=103;break;
case 0xed: key_value=104;break;
case 0xdd: key_value=105;break;
case 0xbd: key_value=106;break;
case 0x7d: key_value=107;break;
case 0xeb: key_value=108;break;
case 0xdb: key_value=109;break;
case 0xbb: key_value=110;break;
case 0x7b: key_value=111;break;
case 0xe7: key_value=112;break;
case 0xd7: key_value=113;break;
case 0xb7: key_value=114;break;
case 0x77: key_value=115;break;
}
}
return key_value;
}
/*==========================================================
* 開(kāi)發(fā)人員:laowang
* 當(dāng)前版本:V1.0
* 創(chuàng)建時(shí)間:11/26/2013
* 修改時(shí)間:
* 功能說(shuō)明:對(duì)4*4矩陣鍵盤(pán)掃描,用8位數(shù)碼管進(jìn)行顯示,剛開(kāi)始時(shí)不亮,依次按下按鍵時(shí)
數(shù)碼管依次顯示0-F,掃描方法為狀態(tài)機(jī)方法+定時(shí)器中斷
*==========================================================*/
#include<reg52.h>
#include"Define.h"
#include"display.h"
#include"matrixkeyscan.h"
void Timer0_init(); //定時(shí)器初始化函數(shù)
uint flag=0; //按鍵掃描標(biāo)志,每中斷一次,掃描一次
//主函數(shù)
void main()
{
uchar key_state=0;
uchar readkey;
readkey=0xff;
Timer0_init();
Display_init(); //使之不亮
while(1)
{
if(flag)
{
flag=0;
readkey=Keyscan();
// Display(readkey);
switch(key_value)
{
case 0: P2=0x66;break;
case 1: P2=0x02;break;
case 2: P2=0x04;break;
case 3: P2=0x08;break;
case 4: P2=0x10;break;
case 5: P2=0x20;break;
case 6: P2=0x40;break;
case 7: P2=0xff;break;
case 100: P2=0x00;break;
case 101: P2=0x0f;break;
case 102: P2=0xf0;break;
case 103: P2=0x88;break;
default:break;
}
}
}
}
void Timer0() interrupt 1
{
TH0=0xd8; //10Ms產(chǎn)生一次中斷
TL0=0xf0;
flag=1;
}
void Timer0_init()
{
TMOD=0x01;
TH0=0xd8; //12MHz 10Ms
TL0=0xf0;
EA=1;
ET0=1;
TR0=1;
}
|
|