各類教材上面講4*4矩陣鍵盤的比較多,4*5掃描方法與其類似,我就試著編寫了一個,讓鍵盤上面的標示在1602液晶掃描顯示出來。在編寫的過程中遇到幾個初學者可能會遇到的問題:一是code里面的東西定以后就不能改動了,使用如果一個數組內容需要經常變化,就不能定義成code。二是字符數組的賦值,在程序里面,只能一個一個字符的賦值。三是液晶顯示一個變量的方法。大家看注釋就知道了。
矩陣鍵盤如下圖所示,為了方便起見我把它橫著看,當做4*5矩陣鍵盤。鍵盤與液晶和單片機的具體連接,看代碼的位定義就知道了。
4-5.JPG (14.76 KB, 下載次數: 102)
下載附件
2016-6-7 20:11 上傳
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar num;
unsigned char i, j, key;
sbit KEY_IN_1 = P1^4;//第一列
sbit KEY_IN_2 = P1^5;
sbit KEY_IN_3 = P1^6;
sbit KEY_IN_4 = P1^7;
sbit KEY_IN_5 = P3^0;//第五列
sbit KEY_OUT_1 = P1^3;//第一行
sbit KEY_OUT_2 = P1^2;
sbit KEY_OUT_3 = P1^1;
sbit KEY_OUT_4 = P1^0;
sbit rs=P2^3;
sbit wr=P2^4;
sbit lcden=P2^5;
uchar code table1[]="Di";//第
uchar code table2[]="Ge An jian";//個按鍵
uchar tabley[]="000";//不可使用code,因為這個數組內容是變化的。
uchar KeySta[4][5] = { //全部矩陣按鍵的當前狀態
{1, 1, 1, 1, 1}, {1, 1, 1, 1, 1}, {1, 1, 1, 1, 1}, {1, 1, 1, 1, 1}
};
uchar backup[4][5] = { //按鍵值備份,保存前一次的值
{1, 1, 1, 1, 1}, {1, 1, 1, 1, 1}, {1, 1, 1, 1, 1}, {1, 1, 1, 1, 1}
};
void delay(uint x)
{
uchar m,n;
for(m=x;m>0;m--)
{
for(n=120;n>0;n--);
}
}
keyscan()//矩陣鍵盤掃描函數
{
for (i=0; i<4; i++) //循環檢測4*4的矩陣按鍵
{
for (j=0; j<5; j++)
{
if (backup[j] != KeySta[j]) //檢測按鍵動作
{
if (backup[j] != 0) //按鍵按下時執行動作
{
//P0 = LedChar[i*5+j]; //將編號顯示到數碼管
key=i*5+j;
}
backup[j] = KeySta[j]; //更新前一次的備份值
}
}
}
return key;
}
void display(uchar x)
{
switch(x)
{ case 0: tabley[0]='E';tabley[1]='n';tabley[2]='t'; break;
case 1: tabley[0]='E';tabley[1]='s';tabley[2]='c'; break;
case 2: tabley[0]='D';tabley[1]='o';tabley[2]='w'; break;
case 3: tabley[0]='U';tabley[1]='p';tabley[2]=' '; break;
case 4: tabley[0]='*';tabley[1]=' ';tabley[2]=' '; break;
case 5: tabley[0]='R';tabley[1]='i';tabley[2]='t'; break;
case 6: tabley[0]='9';tabley[1]=' ';tabley[2]=' '; break;
case 7: tabley[0]='6';tabley[1]=' ';tabley[2]=' '; break;
case 8: tabley[0]='3';tabley[1]=' ';tabley[2]=' '; break;
case 9: tabley[0]='#';tabley[1]=' ';tabley[2]=' '; break;
case 10: tabley[0]='0';tabley[1]=' ';tabley[2]=' '; break;
case 11: tabley[0]='8';tabley[1]=' ';tabley[2]=' '; break;
case 12: tabley[0]='5';tabley[1]=' ';tabley[2]=' '; break;
case 13: tabley[0]='2';tabley[1]=' ';tabley[2]=' '; break;
case 14: tabley[0]='F';tabley[1]='2';tabley[2]=' '; break;
case 15: tabley[0]='L';tabley[1]='e';tabley[2]='f'; break;
case 16: tabley[0]='7';tabley[1]=' ';tabley[2]=' '; break;
case 17: tabley[0]='4';tabley[1]=' ';tabley[2]=' '; break;
case 18: tabley[0]='1';tabley[1]=' ';tabley[2]=' '; break;
case 19: tabley[0]='F';tabley[1]='1';tabley[2]=' '; break;
default: break;
}
}
void write_com(uchar com)
{
rs=0;
wr=0;
lcden=0;
P0=com;
lcden=1;
delay(5);
lcden=0;
}
void write_data(uchar dat)
{
rs=1;
wr=0;
lcden=0;
P0=dat;
lcden=1;
delay(5);
lcden=0;
}
void init()
{
write_com(0x38);
// write_com(0x08);
write_com(0x01);
write_com(0x06);
write_com(0x0f);
}
void main()
{
EA = 1; //使能總中斷
TMOD = 0x01; //設置T0為模式1
TH0 = 0xFC; //為T0賦初值0xFC67,定時1ms
TL0 = 0x67;
ET0 = 1; //使能T0中斷
TR0 = 1; //啟動T0
P0 =0; //默認顯示0
init();
while (1)
{
keyscan();
display(key);
// tabley[0]=(key/10)+0x30;
// tabley[1]=(key%10)+0x30;
write_com(0x80+0x02);
for(num=0;num<2 ;num++)
{
write_data(table1[num]);
// delay(10);
}
write_com(0x80+0x05);
/* write_data(key/10+48);//第一種方法
write_data(key%10+48);
delay(10);*/
for(num=0;num<3 ;num++)//第二種方法
{
write_data(tabley[num]);
// delay(10);
}
write_com(0x80+0x40);
for(num=0;num<10 ;num++)
{
write_data(table2[num]);
// delay(10);
}
}
}
/* T0中斷服務函數,掃描矩陣按鍵狀態并消抖 */
void InterruptTimer0() interrupt 1
{
unsigned char i;
static unsigned char keyout = 0; //矩陣按鍵掃描輸出索引
static unsigned char keybuf[4][5] = { //矩陣按鍵掃描緩沖區
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
};
TH0 = 0xFC; //重新加載初值
TL0 = 0x67;
//將一行的5個按鍵值移入緩沖區
keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN_1;
keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN_2;
keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN_3;
keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN_4;
keybuf[keyout][4] = (keybuf[keyout][4] << 1) | KEY_IN_5;
//消抖后更新按鍵狀態
for (i=0; i<5; i++) //每行5個按鍵,所以循環5次
{
if ((keybuf[keyout] & 0x0F) == 0x00)
{ //連續5次掃描值為0,即4*4ms內都是按下狀態時,可認為按鍵已穩定的按下
KeySta[keyout] = 0;
}
else if ((keybuf[keyout] & 0x0F) == 0x0F)
{ //連續5次掃描值為1,即4*4ms內都是彈起狀態時,可認為按鍵已穩定的彈起
KeySta[keyout] = 1;
}
}
//執行下一次的掃描輸出
keyout++; //輸出索引遞增
keyout = keyout & 0x03; //索引值加到4即歸零
switch (keyout) //根據索引,釋放當前輸出引腳,拉低下次的輸出引腳
{
case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;
case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;
case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;
case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;
default: break;
}
}
|