專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

基于51單片機(jī)開發(fā)之鍵盤

作者:佚名   來源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時間:2014年04月19日   【字體:

1、鍵盤分類

     鍵盤分編碼鍵盤和非編碼鍵盤,鍵盤上閉合鍵的識別由專用的硬件編碼器實(shí)現(xiàn),并產(chǎn)生鍵編碼或鍵值的稱為編碼鍵盤,如計(jì)算機(jī)鍵盤。

  • 而靠軟件編程來識別的稱為非編碼鍵盤;
  • 在單片機(jī)組成的各種系統(tǒng)中,用的最多的是非編碼鍵盤。也有用到編碼鍵盤的。
  • 非編碼鍵盤又分為:獨(dú)立鍵盤和行列式(又稱為矩陣式)鍵盤。
                              此圖為矩陣鍵盤



                     此圖為獨(dú)立鍵盤

  • 在單片機(jī)內(nèi)部P1,P2,P3口各I/O口線片內(nèi)均有固定的上拉電阻,當(dāng)這3個準(zhǔn)雙向I/O口作為輸入口使用時,向該口先寫“1”   才能讀取這個I/O的狀態(tài),P3.4 =1 ,如果這個I/O口沒有3態(tài)就是沒有3態(tài)關(guān)系這個I/O就跟連接的元器件是一個線與的關(guān)系,所以按鍵按下去就是低電平。如果有3態(tài)的I/O口就是跟連接的器件是一個線或的關(guān)系,高阻態(tài)并非是高電平還是低電平,而是高阻狀態(tài),如果外接高它就是高,接低它就是低電平。
  • 實(shí)例:先寫個程序檢測下吧

note:說明下這個程序就是每按下按鍵讓一個數(shù)碼管變一下,從0--9 然后再按變成0循環(huán)

#include

#define uchar unsigned char

sbit  d1= P1^0; //這個腳接的是發(fā)光二極管。

sbit key1= P3^4 ;//接的一個按鍵

sbit dula = P2^6;// 段啦   控制數(shù)碼管 

sbit wela = P^7;// 位啦   控制數(shù)碼管

uchar num;

 

uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,
0x76,0x79,0x38,0x3f,0};//編碼表 數(shù)組 code 是在ROM區(qū)

void main(){

  wela =1;

  P0= Oxfe;

  wela=0;   //位選就打開一個數(shù)碼管的 

    

  P3 = 0XFF;  //把P3都給寫1

   while(1){   //輪循的方式

        if(0==key1){

            d1= 0; //點(diǎn)亮燈

            num ++;//每按一次按鍵讓num++

            if (10==num)

                 num=0; //一個數(shù)碼管就只能顯示9

         

       }else {

         d1 = 1; //熄滅燈

        }

      dula =1;

      P0 = table[num];

      dula =0;

   }

 

以上程序存在問題:按下按鍵時候數(shù)碼管顯示的不是1 2.....9 0 1...  原因是:你按下的大概低電平持續(xù)了20毫秒,20毫秒此程序執(zhí)行了多少次了,所以數(shù)碼管顯示的不是1 可能是5 可能是8 9 。所以必須做一個松手檢測。

#include

#define uchar unsigned char

sbit  d1= P1^0; //這個腳接的是發(fā)光二極管。

sbit key1= P3^4 ;//接的一個按鍵

sbit dula = P2^6;// 段啦   控制數(shù)碼管 

sbit wela = P^7;// 位啦   控制數(shù)碼管

uchar num;

 

uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,
0x76,0x79,0x38,0x3f,0};//編碼表 數(shù)組 code 是在ROM區(qū)

void main(){

  wela =1;

  P0= Oxfe;

  wela=0;   //位選就打開一個數(shù)碼管的 

    

  P3 = 0XFF;  //把P3都給寫1

   while(1){   //輪循的方式

        if(0==key1){

            d1= 0; //點(diǎn)亮燈

            num ++;//每按一次按鍵讓num++

            if (10==num)

                 num=0; //一個數(shù)碼管就只能顯示9

            while (!key1)  //松手檢測  只要你按鍵按下去是0 取反 一直等待 否則跳出去到下面

       }else {

         d1 = 1; //熄滅燈

 

        }

      dula =1;

      P0 = table[num];

      dula =0;

   }

 以上程序雖然得到改善,但是存在按一下會加得不是1現(xiàn)象,當(dāng)然幾率不大,但確實(shí)存在。

  • 按鍵在閉合和斷開時,觸點(diǎn)會存在抖動現(xiàn)象

  

 


      從這個圖看按下和松開有毛刺                            這個是硬件消抖動不要理解
我們解決的是按下去的毛刺去掉:延時函數(shù) 10毫秒   也就是說我們第一次按下去的時候我們延時個10毫秒,實(shí)際上毛刺抖動為5毫秒左右,我們給10毫秒更穩(wěn)定。程序如下:

 

#include

#define uchar unsigned char

sbit  d1= P1^0; //這個腳接的是發(fā)光二極管。

sbit key1= P3^4 ;//接的一個按鍵

sbit dula = P2^6;// 段啦   控制數(shù)碼管 

sbit wela = P^7;// 位啦   控制數(shù)碼管

uchar num;

 

uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,
0x76,0x79,0x38,0x3f,0};//編碼表 數(shù)組 code 是在ROM區(qū)

//此為延時 測試值為1毫秒級

void delay(uint z)
{
 uint t1,y;
 for(t1=z;t1>0;t1--)
  for(y=110;y>0;y--);
}

 

void main(){

  wela =1;

  P0= Oxfe;

  wela=0;   //位選就打開一個數(shù)碼管的 

    

  P3 = 0XFF;  //把P3都給寫1

   while(1){   //輪循的方式

        if(0==key1){

            delay(10);//延時10毫秒

            if (0==key1){  //再確認(rèn)下確實(shí)按下去了多了delay  和if 判斷

            d1= 0; //點(diǎn)亮燈

            num ++;//每按一次按鍵讓num++

            if (10==num)

                 num=0; //一個數(shù)碼管就只能顯示9

            }

            while (!key1)  //松手檢測  只要你按鍵按下去是0 取反 一直等待 否則跳出去到下面

       }else {

         d1 = 1; //熄滅燈

 

        }

      dula =1;

      P0 = table[num];

      dula =0;

   }

經(jīng)過以上的更改是改善了問題但是還是會存在抖動現(xiàn)象,原因是我們只是在按下去消除抖動,沒有在松手消除抖動,但是實(shí)際的項(xiàng)目中一般我們都是按下去的時候做消除抖動,如果想要達(dá)到更好的效果可以在松手也做消除抖動。程序簡單修改如下:

#include

#define uchar unsigned char

sbit  d1= P1^0; //這個腳接的是發(fā)光二極管。

sbit key1= P3^4 ;//接的一個按鍵

sbit dula = P2^6;// 段啦   控制數(shù)碼管 

sbit wela = P^7;// 位啦   控制數(shù)碼管

uchar num;

 

uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,
0x76,0x79,0x38,0x3f,0};//編碼表 數(shù)組 code 是在ROM區(qū)

//此為延時 測試值為1毫秒級

void delay(uint z)
{
 uint t1,y;
 for(t1=z;t1>0;t1--)
  for(y=110;y>0;y--);
}

 

void main(){

  wela =1;

  P0= Oxfe;

  wela=0;   //位選就打開一個數(shù)碼管的 

    

  P3 = 0XFF;  //把P3都給寫1

   while(1){   //輪循的方式

        if(0==key1){

            delay(10);//延時10毫秒

            if (0==key1){  //再確認(rèn)下確實(shí)按下去了多了delay  和if 判斷

            d1= 0; //點(diǎn)亮燈

            num ++;//每按一次按鍵讓num++

            if (10==num)

                 num=0; //一個數(shù)碼管就只能顯示9

            }

            while (!key1)  //松手檢測  只要你按鍵按下去是0 取反 一直等待 否則跳出去到下面

            dely(10);    //松手消除抖動  就是延時

           while(!key1);// 再確認(rèn)下 然后執(zhí)行下面語句

   

       }else {

         d1 = 1; //熄滅燈

 

        }

      dula =1;

      P0 = table[num];

      dula =0;

   }

 

以上程序是獨(dú)立鍵盤的應(yīng)用中確實(shí)存在的一些問題和本人的一些簡單的解決問題的思路。當(dāng)然延時也可以改成5毫秒盡量的不要讓MCU過多的等待。一般的項(xiàng)目中都不會采用延時來去抖動,可以用定時器來去除抖動。特別在一些嵌入式系統(tǒng)中常用定時器去抖動,因?yàn)榍度胧皆O(shè)備的硬件資源太寶貴了哦。希望大牛們給個定時器的去除抖動程序。。。!

關(guān)閉窗口

相關(guān)文章