新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 51單片機(jī)4X4矩陣鍵盤驅(qū)動(dòng)與應(yīng)用程序(C語言)

51單片機(jī)4X4矩陣鍵盤驅(qū)動(dòng)與應(yīng)用程序(C語言)

作者: 時(shí)間:2016-11-18 來源:網(wǎng)絡(luò) 收藏
1、keydrive.c
#include
#include
/*
程序功能: 本程序用于測(cè)試4X4矩陣鍵盤驅(qū)動(dòng);
程序算法:
每2MS檢測(cè)一次按鍵的狀態(tài),若連續(xù)8次檢測(cè)都為相同,
說明現(xiàn)在是一個(gè)穩(wěn)定的狀態(tài),否就是干擾不與理采 ;
按鍵有三種狀態(tài):1、按下 2、松開 3、干擾或抖動(dòng);
其中前兩種都是穩(wěn)態(tài),后一種為抖動(dòng)。
接著若判斷按鍵的狀態(tài)是否改變,
若改變--》判斷原來的狀態(tài)是否為松開---是--說明
現(xiàn)在按鍵為按下,那么就把鍵值算出來;---返回0;
若改變--》判斷原來的狀態(tài)是否為松開---否--說明
現(xiàn)在按鍵為松開,那么就把鍵值返回;
*/
/*
矩陣鍵盤硬件引腳連接關(guān)系
*/
/*
keyin4 ----- P2^7;
keyin3 ----- P2^6;
keyin2 ----- P2^5;
keyin1 ----- P2^4;
keyout1 ----- P2^3;
keyout2 ----- P2^2;
keyout3 ----- P2^1;
keyout4 ----- P2^0;
*/
/*
定義外部變量
*///lcd1602顯示數(shù)組
unsigned char keynum[]="keynum:k ";
//鍵值查詢數(shù)組
//k1,k2,k3,k4,k5,k6,k7,k8,
unsigned char code keytabel[]={0xe7,0xd7,0xb7,0x77,0xeb,0xdb,0xbb,0x7b,
//k9,k10,k11,k12,k13,k14,k15,k16,
0xed,0xdd,0xbd,0x7d,0xee,0xde,0xbe,0x7e};
unsigned char status1;
/*
外部函數(shù)聲明
*/
extern bit Flag2Ms; //2ms到標(biāo)志 鍵盤驅(qū)動(dòng)中要用到這個(gè)外部變量
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
/*
函數(shù)功能:N毫秒延時(shí)
*/
void DelayMs(unsigned int ms)
{
unsigned int i,j;
for(i=0;i
for(j=0;j<113;j++);
}
/*
函數(shù)功能:矩陣鍵盤掃描
在該函數(shù)只是判斷按鍵的狀態(tài),即按下還是彈起;設(shè)置按鍵狀態(tài)標(biāo)置位;
算法:采用狀態(tài)機(jī)的機(jī)制
*/
void keyscan()
{
static unsigned char num1,keyon_num,num2; //設(shè)置為局部靜態(tài)變量
/*
num1---保存P2口狀態(tài)
num2---保存次數(shù) ,每次時(shí)間為2ms;
keyon_num----保存按下次數(shù)
*/
if(Flag2Ms==1) //2MS時(shí)間到
{
Flag2Ms=0;
num2++;
P2 = 0xf0;
num1=P2;
if(num1!=0xf0)
keyon_num++;
if(num2==8) //若連續(xù)8次檢測(cè)都為同一個(gè)狀態(tài)說明按鍵是一個(gè)穩(wěn)定的狀態(tài);
{ //否則就是一個(gè)干擾,或者說是一次抖動(dòng); 時(shí)間為16MS;
num2=0;
if(keyon_num==8)
status1=1; //按鍵已按下
else if(keyon_num==0)
status1=0; //按鍵已彈起
else
status1=2; //按鍵無效,是干擾
keyon_num=0; // 一定要復(fù)位該值;
}
}
}
/*
函數(shù)功能:獲取鍵值
算法: 先判斷按鍵的狀態(tài)是否改變,若改變--》判斷原來的狀態(tài)是否為松開---是--說明
現(xiàn)在按鍵為按下,那么就把鍵值算出來;---返回0;
若改變--》判斷原來的狀態(tài)是否為松開---否--說明
現(xiàn)在按鍵為松開,那么就把鍵值返回;
若按鍵的狀態(tài)沒有變化,就返回0;
*/
unsigned char getkey()
{
static unsigned char backstatus=0; //原來按鍵的狀態(tài),初始設(shè)為0,即松開狀態(tài);
static unsigned char temp,num3; //定義兩個(gè)局部靜態(tài)變量;
if((backstatus!=status1)&&(status1!=2))
{
if(backstatus==0) //若原來狀態(tài)為松開,就求出鍵值,但返回0;
{
P2=0xf0;
num3=P2;
temp=num3;
P2 = 0x0f;
num3=P2;
temp =temp|num3;
backstatus=status1; //備份按鍵狀態(tài)
return 0;
}
backstatus=0; //若原來狀態(tài)為按下,說明現(xiàn)在為松開
return temp; //返回鍵值;
}
return 0; //若狀態(tài)沒有改變,則返回0;
}
/*
函數(shù)功能:按鍵功能處理函數(shù)
在該函數(shù)中,收到按鍵后,就把相關(guān)的鍵值通過LCD1602顯示;
并通過串口顯示:keynum:kxx” xx為按k1-k16;
*/
void key_functoin(unsigned char keynum1)
{
unsigned char i;
if(keynum1!=0) //有鍵按下并松手
{
for(i=0;i<16;i++) // 循環(huán)查表,獲取按鍵編號(hào)
{
if(keynum1==keytabel[i])
break;
}
keynum[8]=(i+1)/10+0x30; //把編號(hào)轉(zhuǎn)換成字符放到顯示數(shù) 組中;
keynum[9]=(i+1)%10+0x30;
TI=1; //把按鍵值發(fā)送到串口;
printf("%s",keynum); //在串口上顯示“keynum:kxx” xx為按k1-k16;
while(TI!=1); //每次發(fā)送完畢,要手動(dòng)清TI標(biāo)志;
TI=0;
LcdShowStr(0,0,keynum); //1602顯示按鍵編號(hào)
}
}
2、keytest.c
#include
#include
/*
程序功能: 本程序用于測(cè)試4X4矩陣鍵盤;
當(dāng)按下按鍵后,在LCD1602上顯示出按下的鍵號(hào)如:K1 K2.... K16;
同時(shí)把鍵值通過串口發(fā)送到口上顯示;
在串口上顯示“keynum:kxx” xx為按k1-k16;
程序用到的資源:1、定時(shí)器T0、T1 2、P2口 3、LCD1602 4、串行口
程序作者:王廬山
程序編制日期:2015年3月13日
地址:湖北工業(yè)職業(yè)技術(shù)學(xué)院電子工程系電子創(chuàng)新中心
注意:在本程序中,把鍵盤相關(guān)的處理函數(shù)都寫在鍵盤驅(qū)動(dòng)中;
使用模塊化編程;本程序在金沙灘開發(fā)板上測(cè)試通過。
*/
//宏定義
#define TH0_NUM 1000 //便于程序的移植;
#define TL0_NUM 1000
bit Flag2Ms; //2ms到標(biāo)志
unsigned char code demo[]="key_4x4 " ;
unsigned char code demo1[]="scaning..." ;
/*
外部函數(shù)聲明
*/
extern void InitLcd1602();
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
extern void ConfigUART(unsigned int baud);
extern void DelayMs(unsigned int ms);
extern void keyscan();
extern unsigned char getkey();
extern void key_functoin(unsigned char keynum1);
//內(nèi)部函數(shù)聲明
void InitTimer0();
/*
主程序
*/
void main()
{
InitTimer0(); //定時(shí)0初始化
ConfigUART(9600); //串口初始化
InitLcd1602(); //1602初始化
LcdShowStr(0,0,demo); // 顯示字符串
LcdShowStr(0,1,demo1); // 顯示字符串
while(1)
{
keyscan(); //按鍵掃描
key_functoin(getkey());//根據(jù)獲取的鍵,進(jìn)行相關(guān)的處理;
}
}
/*
函數(shù)功能:定時(shí)器0初始化,設(shè)定每1MS中斷一次
*/
void InitTimer0()
{
TMOD &=0xf0; //這種操作模式,不會(huì)破壞寄存器的其它設(shè)置;
TMOD |=0x01; //方式1,16位定時(shí)器
TH0/=(65536-TH0_NUM)/256;
TL0=(65536-TL0_NUM)%256;
EA=1;
ET0=1;
TR0=1;
}
/*
函數(shù)功能:定時(shí)器0中斷服務(wù)程序
*/
void Timer0_Interrupt() interrupt 1
{
static unsigned char i;
TH0=(65536-TH0_NUM)/256;
TL0=(65536-TL0_NUM)%256;
i++;
if(i>2)
{
i=0;
Flag2Ms=1;
}
}



關(guān)鍵詞: 51單片機(jī)矩陣鍵

評(píng)論


技術(shù)專區(qū)

關(guān)閉