亚洲春色中文字幕久久久-三上亚,一吻二脱三床四吻胸,国产真实伦对白视频全集,在线毛片观看,精品成品入口黄网,国产毛aⅴ片久久久,亚洲AV色香蕉一区二区三区老师,萧皇后A级艳片,色情日本视频更新,99久久亚洲精品日本无码

標(biāo)題: 按鍵消抖方法與抖動(dòng)原因分析(狀態(tài)機(jī),延時(shí),邏輯關(guān)系消抖)單片機(jī)源程序 [打印本頁(yè)]

作者: 烏托邦的犬次郎    時(shí)間: 2018-8-31 02:34
標(biāo)題: 按鍵消抖方法與抖動(dòng)原因分析(狀態(tài)機(jī),延時(shí),邏輯關(guān)系消抖)單片機(jī)源程序
本人第一次發(fā)帖,如果有錯(cuò)誤,歡迎大家指正!!!有關(guān)按鍵消抖的話題已經(jīng)有很多人提出來(lái)了,在這里我把它進(jìn)行一個(gè)總結(jié)。希望能幫助到大家!
1.按鍵抖動(dòng)的原因
       按鍵消抖通常的按鍵所用開(kāi)關(guān)為機(jī)械彈性開(kāi)關(guān),當(dāng)機(jī)械觸點(diǎn)斷開(kāi)、閉合時(shí),由于機(jī)械觸點(diǎn)的彈性作用,一個(gè)按鍵開(kāi)關(guān)在閉合時(shí)不會(huì)馬上穩(wěn)定地接通,在斷開(kāi)時(shí)也不會(huì)一下子斷開(kāi)。形成以下的波形
   
2.按鍵抖動(dòng)的原理
      按鍵抖動(dòng)時(shí)間的長(zhǎng)短由按鍵的機(jī)械特性決定,一般為5ms~10ms。這是一個(gè)很重要的時(shí)間參數(shù),在很多場(chǎng)合都要用到。按鍵穩(wěn)定閉合時(shí)間的長(zhǎng)短則是由操作人員的按鍵動(dòng)作決定的,一般為零點(diǎn)幾秒至數(shù)秒。鍵抖動(dòng)會(huì)引起一次按鍵被誤讀多次。為確保單片機(jī)對(duì)按鍵的一次閉合僅作一次處理,必須去除鍵抖動(dòng)。在鍵閉合穩(wěn)定時(shí)讀取鍵的狀態(tài),并且必須判別到按鍵釋放到穩(wěn)定狀態(tài)后再去作處理。
3.按鍵消抖的方法
(1)硬件的消抖
      利用電容的充放電特性來(lái)對(duì)抖動(dòng)過(guò)程中產(chǎn)生的電壓毛刺進(jìn)行平滑處理,從而實(shí)現(xiàn)消抖。在按鍵的兩端并聯(lián)一個(gè)0.1uf的電容。如按鍵消抖硬件圖

(2)軟件的消抖
     1.延時(shí)消抖
        剛接觸單片機(jī)的時(shí)候,最常用的方法,利用延時(shí),消去抖動(dòng)。代碼如下:
       if(按鍵是否按下)
       {                        //按鍵按下的條件下
           Deadly_1ms(5); // 延時(shí)消去抖動(dòng)
           if(按鍵是否按下)
          {                   //按鍵再次確認(rèn)按下
              //執(zhí)行按鍵功能
             while(按鍵是否松開(kāi));
          }
       }
   注:按鍵詳細(xì)代碼見(jiàn)工程文件延時(shí)消抖
    2.狀態(tài)機(jī)消抖
      將按鍵的狀態(tài)分為三種 是否按下,是否抖動(dòng),是否彈起。檢測(cè)到按下時(shí),轉(zhuǎn)向判斷是否抖動(dòng),并執(zhí)行按鍵功能。等按鍵功能執(zhí)行完了以后直接跳到按鍵是否彈起的狀態(tài)。等彈起后,再來(lái)判斷是否按下的狀態(tài)。
       在按鍵的原理圖中,將1、2相接,則構(gòu)成的是4*4的矩陣鍵盤,并且矩陣鍵盤與單片機(jī)的P3口相接。
       //按鍵原理圖見(jiàn)上傳的圖片
        
//設(shè)置按鍵的三種狀態(tài)及按鍵接口
#define KEY P3
#define key_state_0  0  //判斷是否按下
#define key_state_1  1 //判斷是否為抖動(dòng)
#define key_state_2  2 //判斷是否彈起

unsigned char key_read(void)
{
  static char key_state = key_state_0;
  unsigned char key_return=0, key_press;
  unsigned char key1,key2;
        
        KEY=0xf0;   
        key1=KEY&0xf0;
        KEY=0x0f;
        key2=KEY&0x0f;
        key_press =key1|key2;  //讀取矩陣按鍵每個(gè)按鍵的狀態(tài),存在key_press里
        
switch (key_state)  // 判斷按鍵狀態(tài)
{         
   case key_state_0:    //是否按下
   if (key_press!=0xff) key_state = key_state_1;  //沒(méi)有按鍵按下時(shí)則讀取出的0xff,若有不同說(shuō)明有按鍵按下,則跳轉(zhuǎn)到判斷是否為抖動(dòng)的狀態(tài)
   break;
         
   case key_state_1:     
   if (key_press !=0xff) //再次確認(rèn)是否按下,防止因單片機(jī)的速度過(guò)快,導(dǎo)致誤判。
   {   
       switch (key_press)//根據(jù)key_press的值來(lái)執(zhí)行相對(duì)應(yīng)的功能
       {
           case 0xee: key_return = 19; //這里的0xee是怎么的來(lái)的,簡(jiǎn)單來(lái)推一下
           case 0xed: key_return = 18; //單片機(jī)的P3口初始化輸出的是高電平,先將P3口輸出0xf0,如果有按鍵按下,則P3口中的高四位的某一位的電平會(huì)被拉低,此時(shí)記錄P3口的狀態(tài)(key1)
           case 0xeb: key_return = 17; //讀取了高四位的電平,之后再來(lái)讀取低四位的電平(key2) ,之后 | 在一起得到key_press,得到的key_press中一定有兩位是0;
           case 0xe7: key_return = 16;//舉例 : 當(dāng)我按下s19時(shí),key1 = 0xe0;(即P3^4 = 0,高四位的第一位電平被拉低),key2 = 0x0e;(即P3^0 = 0,低四位的第一位電平被拉低),這樣key_press = key_press =key1|key2  = 0xee;
           case 0xde: key_return = 15;//以此類推
           case 0xdd: key_return = 14;
           case 0xdb: key_return = 13;
           case 0xd7: key_return = 12;
           case 0xbe: key_return = 11;
           case 0xbd: key_return = 10;
           case 0xbb: key_return = 9;
           case 0xb7: key_return = 8;
           case 0x7e: key_return = 7;
           case 0x7d: key_return = 6;
           case 0x7b: key_return = 5;
           case 0x77: key_return = 4;
       }
                        key_state = key_state_2; //這里跳轉(zhuǎn)到判斷彈起的狀態(tài)
   }
   else
                        key_state = key_state_0;  
   break;

   case key_state_2:
   if (key_press==0xff) key_state = key_state_0;  //等待按鍵完全彈起
   break;
}
return key_return;
}
注:具體用法見(jiàn)工程狀態(tài)機(jī)消抖  

    3.邏輯關(guān)系消抖
       將按鍵的原理圖中,將2、3相接,則構(gòu)成的是獨(dú)立鍵盤(s4,s5,s6,s7),并且獨(dú)立鍵盤與單片機(jī)的P3口的低四位相接,另一端與gnd相接。
    利用邏輯關(guān)系 與&、或 | 、非 !、異或 ^,來(lái)消除抖動(dòng)。先貼出源代碼:

    unsigned char ReadData = KEYPORT^0xff;
    Trg = ReadData & (ReadData ^ Cont);      
    Cont = ReadData;

    Trg是判斷那個(gè)按鍵按下,Cont用來(lái)判斷長(zhǎng)按、短按的;
分析:   (1)沒(méi)有按鍵按下(初始值 Trg  =  0,Cont  = 0)
                  unsigned char ReadData = P3^0xff;  => ReadData  = 0xff ^0xff = 0x00;
                  Trg = ReadData & (ReadData ^ Cont); =>Trg  =0x00 &  (0x00 ^0x00)  = 0x00;
                  Cont = ReadData;    =>Cont  = 0x00;

                 結(jié)果 :
                         ReadData  = 0x00
                        Trg           = 0x00
                        Cont         = 0x00

            (2) s4按下
                  剛按下時(shí)
                  unsigned char ReadData = P3^0xff;  => ReadData  = 0xf7 ^0xff = 0x08;
                  Trg = ReadData & (ReadData ^ Cont); =>Trg  =0x08 &  (0x08^0x00)  = 0x08;
                  Cont = ReadData;    =>Cont  = 0x08;

               抖動(dòng)時(shí)
                  unsigned char ReadData = P3^0xff;  => ReadData  = 0xff ^0xff = 0x00;
                  Trg = ReadData & (ReadData ^ Cont); =>Trg  =0x00 &  (0x00^0x08)  = 0x00;
                  Cont = ReadData;    =>Cont  = 0x00;

                 結(jié)果 :
                       剛按下時(shí):
                        ReadData  = 0x08
                        Trg           = 0x08
                        Cont         = 0x08

                       抖動(dòng)時(shí):
                        ReadData  = 0x00
                        Trg           = 0x00
                        Cont         = 0x00


            (3) s4長(zhǎng)按
                  unsigned char ReadData = P3^0xff;  => ReadData  = 0xf7 ^0xff = 0x08;
                  Trg = ReadData & (ReadData ^ Cont); =>Trg  =0x08 &  (0x08 ^0x00)  = 0x00;
                  Cont = ReadData;    =>Cont  = 0x08;

                 結(jié)果 :
                         ReadData  = 0x08
                        Trg           = 0x00
                        Cont         = 0x08


            (4) s4松開(kāi)
                  unsigned char ReadData = P3^0xff;  => ReadData  = 0xff ^0xff = 0x00;
                  Trg = ReadData & (ReadData ^ Cont); =>Trg  =0x08 &  (0x08 ^0x00)  = 0x00;
                  Cont = ReadData;    =>Cont  = 0x00;

                 結(jié)果 :
                         ReadData  = 0x00
                        Trg           = 0x00
                        Cont         = 0x00


將上面的數(shù)據(jù)進(jìn)行匯總、分析
ReadData  Trg           Cont         
沒(méi)有按鍵按下 0x00 0x00 0x00
s4剛按下 0x08 0x08 0x08
s4有抖動(dòng)時(shí) 0x00 0x00 0x00
s4長(zhǎng)按 0x08 0x00 0x08
  s4松開(kāi) 0x00 0x00 0x00


Trg只有在按鍵剛按下時(shí)有不到等于0的值,因此我們檢測(cè)到Trg 不為0時(shí),說(shuō)明有按鍵按下;
Cont 只要有按鍵按下時(shí),它的值就不為0,因此我們定時(shí)一段時(shí)間,來(lái)檢測(cè)Cont,,若不變,則按鍵時(shí)長(zhǎng)按的狀態(tài)。
注:具體用法見(jiàn)工程邏輯關(guān)系消抖

          到這里只是簡(jiǎn)單的介紹了幾種按鍵消抖,還有很多方法沒(méi)有介紹,比如,中斷消抖,門電路消抖,計(jì)時(shí)消抖…,但萬(wàn)變不離其中。學(xué)會(huì)了其中一種,其他的就自然懂了。
         希望這篇帖子能幫助到大家!!!!

全部資料51hei下載地址(全部程序源碼):
按鍵.rar (68.28 KB, 下載次數(shù): 171)



作者: yinlingwei66    時(shí)間: 2018-8-31 14:09
樓主寫的非常詳細(xì) 好資料,51黑有你更精彩!!!

作者: keliandexiaowa    時(shí)間: 2021-3-26 14:36
樓主寫的很好,先收藏研究一下
作者: aaron800    時(shí)間: 2023-5-29 16:48
非常好的資料,謝謝樓主
作者: huaruolong    時(shí)間: 2023-6-21 10:55
不錯(cuò),萬(wàn)丈高樓平地起,越是看似簡(jiǎn)單的東西,越要用心去學(xué)。謝謝樓主分享。

作者: huaruolong    時(shí)間: 2023-6-21 11:01
樓主是你的資料有問(wèn)題,還是我的軟件有問(wèn)題。

error.JPG (50.54 KB, 下載次數(shù): 125)

error.JPG

作者: huaruolong    時(shí)間: 2023-6-21 11:03
oh,在不解壓下可以打開(kāi),解壓了反而打不開(kāi)了,是我的原因。

作者: zlj20181110    時(shí)間: 2023-8-13 09:16
感謝樓主,非常好的資料,很有用。
作者: dyx811    時(shí)間: 2023-8-15 10:45
分析很透徹!好辦法!
作者: likejian    時(shí)間: 2023-8-17 14:08
分析很透,佩服這些大神
作者: 量子工業(yè)    時(shí)間: 2023-8-20 09:55
很棒的分析,感謝分享。
作者: huaruolong    時(shí)間: 2023-8-30 13:19

樓主寫的非常詳細(xì) 好資料,51黑有你更精彩!!!
作者: newlined    時(shí)間: 2024-8-14 13:40
謝謝大佬
作者: Tao濤    時(shí)間: 2024-8-16 19:18
哎呀,你為什么把每個(gè)按鍵都定義呢,直接橫掃縱掃不就行了
作者: donglw    時(shí)間: 2024-8-17 03:04
使用硬件去抖動(dòng)電路:1)RS觸發(fā)器去抖動(dòng),2)單穩(wěn)觸發(fā)器——74HC221,3)同相器組成的積分去抖動(dòng)電路。
作者: 藍(lán)藍(lán)小星星    時(shí)間: 2024-8-17 03:09
程序啰里啰唆,采樣后僅判斷2次,完全沒(méi)這個(gè)必要的邏輯,后面的keycode重新賦值也根本沒(méi)必要,采樣出來(lái)本來(lái)已經(jīng)是按鍵值,沒(méi)必要再次轉(zhuǎn)換。除非還有其他的采樣,要放在一個(gè)8位的byte里面去識(shí)別。
作者: 勞資蜀道山111    時(shí)間: 2024-8-17 09:34
寫的非常詳細(xì)
作者: 新昌小徐    時(shí)間: 2024-8-17 12:16
看了一下,你的狀態(tài)機(jī)消抖,你key_press!=0xff時(shí),表明有鍵按下,賦key_state=1,則執(zhí)行case=1語(yǔ)句,再判斷key_press!=0xff,就幾條語(yǔ)句,也就幾個(gè)微秒而已,延時(shí)很短的,這有問(wèn)題。
還是手把手教你學(xué)51單片機(jī) 宋學(xué)松處理陣列按鍵程序來(lái)得好。
它的思路是:采用中斷的形式,1毫秒中斷,在1毫秒中斷中,使某一行為低電平,其它為高電平。然后把這一行中的按鍵狀態(tài)緩存在狀態(tài)字節(jié)數(shù)組中(4*4的二維數(shù)組中),有四行,則要執(zhí)行4次,花4毫秒才能把各個(gè)按鍵的狀態(tài)存儲(chǔ)一遍。存儲(chǔ)的字節(jié)先左移一位,然后從最低位移入狀態(tài)位(列狀態(tài)),1為按鍵沒(méi)按下,0表示按下。通過(guò)16次,16毫秒掃描,就存儲(chǔ)了四次矩陣按鍵狀態(tài),這樣存儲(chǔ)在字節(jié)的低四位中。
假設(shè)4次都是1,表明已穩(wěn)定彈起,假設(shè)4次都為0,表明穩(wěn)定鍵下,如果不全是1或是0,則在按鍵過(guò)渡期。只要把這16這字節(jié)的數(shù)組與0x0f按位與,就能判斷是不是穩(wěn)定按下,或是穩(wěn)定彈出,如果是,就返回某按鍵值為1或是0,使代表按鍵消抖狀態(tài)的二維數(shù)組中的某個(gè)數(shù)為1或是0
作者: 新昌小徐    時(shí)間: 2024-8-17 12:23
貼上宋學(xué)松的程序片段:此程序在1毫秒中斷程序中執(zhí)行
//將一行的 4 個(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;
//消抖后更新按鍵狀態(tài)
for (i=0; i<4; i++) //每行 4 個(gè)按鍵,所以循環(huán) 4 次
{
if ((keybuf[keyout][i] & 0x0F) == 0x00)
{ //連續(xù) 4 次掃描值為 0,即 4*4ms 內(nèi)都是按下?tīng)顟B(tài)時(shí),可認(rèn)為按鍵已穩(wěn)定的按下
KeySta[keyout][i] = 0;
}
else if ((keybuf[keyout][i] & 0x0F) == 0x0F)
{ //連續(xù) 4 次掃描值為 1,即 4*4ms 內(nèi)都是彈起狀態(tài)時(shí),可認(rèn)為按鍵已穩(wěn)定的彈起
KeySta[keyout][i] = 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;
}

作者: 東籬南山客    時(shí)間: 2024-8-31 10:17
看了樓主的貼子對(duì)按鍵消抖又有了新的理解




歡迎光臨 (http://www.denmoz.com/bbs/) Powered by Discuz! X3.1