找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 5083|回復(fù): 1
打印 上一主題 下一主題
收起左側(cè)

4*5矩陣鍵盤的掃描與顯示(1602)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
各類教材上面講4*4矩陣鍵盤的比較多,4*5掃描方法與其類似,我就試著編寫了一個(gè),讓鍵盤上面的標(biāo)示在1602液晶掃描顯示出來。在編寫的過程中遇到幾個(gè)初學(xué)者可能會(huì)遇到的問題:一是code里面的東西定以后就不能改動(dòng)了,使用如果一個(gè)數(shù)組內(nèi)容需要經(jīng)常變化,就不能定義成code。二是字符數(shù)組的賦值,在程序里面,只能一個(gè)一個(gè)字符的賦值。三是液晶顯示一個(gè)變量的方法。大家看注釋就知道了。
矩陣鍵盤如下圖所示,為了方便起見我把它橫著看,當(dāng)做4*5矩陣鍵盤。鍵盤與液晶和單片機(jī)的具體連接,看代碼的位定義就知道了。


#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";//個(gè)按鍵
uchar tabley[]="000";//不可使用code,因?yàn)檫@個(gè)數(shù)組內(nèi)容是變化的。
uchar KeySta[4][5] = {  //全部矩陣按鍵的當(dāng)前狀態(tài)
    {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()//矩陣鍵盤掃描函數(shù)
        {
                for (i=0; i<4; i++)  //循環(huán)檢測(cè)4*4的矩陣按鍵
        {
            for (j=0; j<5; j++)
            {
                if (backup[j] != KeySta[j])  //檢測(cè)按鍵動(dòng)作
                {
                    if (backup[j] != 0)         //按鍵按下時(shí)執(zhí)行動(dòng)作
                    {
                        //P0 = LedChar[i*5+j];       //將編號(hào)顯示到數(shù)碼管
                                                  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;  //設(shè)置T0為模式1
    TH0  = 0xFC;  //為T0賦初值0xFC67,定時(shí)1ms
    TL0  = 0x67;
    ET0  = 1;     //使能T0中斷
    TR0  = 1;     //啟動(dòng)T0
    P0 =0;   //默認(rèn)顯示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中斷服務(wù)函數(shù),掃描矩陣按鍵狀態(tài)并消抖 */
void InterruptTimer0() interrupt 1
{
    unsigned char i;
    static unsigned char keyout = 0;  //矩陣按鍵掃描輸出索引
    static unsigned char keybuf[4][5] = {  //矩陣按鍵掃描緩沖區(qū)
        {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個(gè)按鍵值移入緩沖區(qū)
    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;
    //消抖后更新按鍵狀態(tài)
    for (i=0; i<5; i++)  //每行5個(gè)按鍵,所以循環(huán)5次
    {
        if ((keybuf[keyout] & 0x0F) == 0x00)
        {   //連續(xù)5次掃描值為0,即4*4ms內(nèi)都是按下狀態(tài)時(shí),可認(rèn)為按鍵已穩(wěn)定的按下
            KeySta[keyout] = 0;
        }
        else if ((keybuf[keyout] & 0x0F) == 0x0F)
        {   //連續(xù)5次掃描值為1,即4*4ms內(nèi)都是彈起狀態(tài)時(shí),可認(rèn)為按鍵已穩(wěn)定的彈起
            KeySta[keyout] = 1;
        }
    }
    //執(zhí)行下一次的掃描輸出
    keyout++;                //輸出索引遞增
    keyout = keyout & 0x03;  //索引值加到4即歸零
    switch (keyout)          //根據(jù)索引,釋放當(dāng)前輸出引腳,拉低下次的輸出引腳
    {
        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;
    }
}



分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:186564 發(fā)表于 2017-6-30 09:03 | 只看該作者
MAIN.C(50): error C213: left side of asn-op not an lvalue,這個(gè)報(bào)錯(cuò)是什么原因。麻煩給指導(dǎo)下~!謝謝~!
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表