• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    Lattice MXO2: 按鍵消抖

    作者: 時間:2023-11-08 來源:電子森林 收藏

    按鍵


    在之前的實驗中我們學(xué)習(xí)了如何用按鍵作為的輸入控制,在本實驗中將學(xué)習(xí)如何進(jìn)行按鍵,用按鍵完成更多的功能。

    本文引用地址:http://www.czjhyjcfj.com/article/202311/452611.htm

    硬件說明


    按鍵是一種常用的電子開關(guān),電子設(shè)計中不可缺少的輸入設(shè)備。當(dāng)按下時使開關(guān)導(dǎo)通,松開時則開關(guān)斷開,內(nèi)部結(jié)構(gòu)是靠金屬彈片來實現(xiàn)通斷。

    按鍵抖動的原理

    抖動原理

    • 抖動的產(chǎn)生 :通常的按鍵所用的開關(guān)為機(jī)械彈性開關(guān),當(dāng)機(jī)械觸點斷開、閉合時,由于機(jī)械觸點的彈性作用,一個按鍵開關(guān)在閉合時不會馬上穩(wěn)定地接通,在斷開時也不會一下子斷開。因而在閉合及斷開的瞬間均伴隨有一連串的抖動,為了不產(chǎn)生這種現(xiàn)象而作的措施就是按鍵
    • 消除抖動的措施:一般我們采用軟件方法消抖。即檢測到按鍵按下動作之后進(jìn)行10ms~20ms左右的延時,當(dāng)前沿的抖動消失之后再一次檢測按鍵的狀態(tài)。如果仍然是按下的電平狀態(tài),則認(rèn)為這是一次真正的按鍵按下;同樣檢測到按鍵釋放,也要做10ms~20ms延時,檢測到后沿抖動消失后認(rèn)為是一個完整的按鍵彈起過程。
    • 消抖的好處:執(zhí)行按鍵消抖有兩個好處,
      • 消除誤觸發(fā):我們想通過按鍵來翻轉(zhuǎn)信號(例如按下一次led亮,在按一次led滅),如果沒有進(jìn)行消抖,則會產(chǎn)生很多誤觸發(fā)造成不必要的翻轉(zhuǎn)。
      • 記錄按鍵次數(shù):執(zhí)行按鍵消抖可以讓我們記錄按鍵動作的次數(shù),在很多應(yīng)用里這非常有用。

    在點亮LED實驗中我們知道了板子上按鍵的設(shè)計,當(dāng)按鍵未被按下時,連接到管腳認(rèn)為是高電平;當(dāng)按鍵被按下時,連接到管腳認(rèn)為是低電平。

    要消除按鍵的抖動,我們需要去掃描按鍵,也就是不斷的去采集按鍵的狀態(tài)。軟件消抖時我們一般只考慮按鍵按下時的抖動,而放棄對釋放時抖動的消除。用系統(tǒng)時鐘(頻率較高)去采集按鍵狀態(tài),當(dāng)檢測到按下時用計數(shù)器延時20ms,再去檢測按鍵狀態(tài),如果這時仍為按下狀態(tài),確認(rèn)是一次按下動作,否側(cè)的話認(rèn)為無按鍵按下。如何檢測按鍵狀態(tài)變化就需要用到脈沖邊沿檢測的方法。

    脈沖邊沿檢測

    檢測按鍵按下時要用到脈沖邊沿檢測的方法,捕捉信號的突變、捕捉時鐘的上升下降沿等經(jīng)常會用到這種方法。簡單地說就是用一個頻率更高的時鐘去觸發(fā)要檢測的信號,用兩個寄存器去儲存相鄰兩個時鐘采集到的值,然后進(jìn)行異或運(yùn)算,如果不為零,代表發(fā)生了上升沿或者下降沿。

    在按鍵消抖的過程中,同樣運(yùn)用了脈沖邊沿檢測。用兩個寄存器儲存相鄰時鐘采集的值(例如datapre,data),然后將data取反與前一個值相與(state=datapre&(~data)),如果為1,則判斷有下降沿既按鍵按下由高到低;否則無變化。
    將一個信號由連續(xù)時鐘采集,相鄰兩個鐘觸發(fā)的值存入兩個寄存器。理解verilog實現(xiàn)這個過程要充分了解其中的非阻塞賦值。


    Verilog代碼


    本實驗主要通過按鍵來控制led的翻轉(zhuǎn),當(dāng)按下一次led變亮,再按下一次led變暗。首先我們做個試驗,對按鍵不做處理通過按鍵來控制led翻轉(zhuǎn)。

    // ********************************************************************
    // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
    // ********************************************************************
    // File name    : top.v
    // Module name  : top
    // Author       : STEP
    // Description  : control led through the button
    // 
    // --------------------------------------------------------------------
    // Code Revision History : 
    // --------------------------------------------------------------------
    // Version: |Mod. Date:   |Changes Made:
    // V1.0     |2017/03/02   |Initial ver
    // --------------------------------------------------------------------
    // Module Function:按鍵控制led翻轉(zhuǎn),未做消抖 
    module top(
    		key,          //按鍵輸入
    		rst,          //復(fù)位輸入
    		led           //led輸出
    		); 	input key,rst;
    	output reg led; 	always @(key or rst)
    		if (!rst)             //復(fù)位時led熄滅
    			led = 1;
    		else if(key == 0)     
    			led = ~led;   //按鍵按下時led翻轉(zhuǎn)
    		else
    			led = led;
    			endmodule

    未經(jīng)過消抖的程序下載到上會發(fā)現(xiàn)按鍵有時不能夠控制led翻轉(zhuǎn),這是因為按鍵的抖動造成了led狀態(tài)變化不可控,所以我們必須將抖動消除。下面是一種延時去抖的程序

    // ********************************************************************
    // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
    // ********************************************************************
    // File name    : debounce.v
    // Module name  : debounce
    // Author       : STEP
    // Description  : 
    // 
    // --------------------------------------------------------------------
    // Code Revision History : 
    // --------------------------------------------------------------------
    // Version: |Mod. Date:   |Changes Made:
    // V1.0     |2017/03/02   |Initial ver
    // --------------------------------------------------------------------
    // Module Function:按鍵消抖 
    module debounce (clk,rst,key,key_pulse);         
    parameter       N  =  1;                      //要消除的按鍵的數(shù)量 	
    input             clk;
            input             rst;
            input 	[N-1:0]   key;                        //輸入的按鍵					
    	output  [N-1:0]   key_pulse;                  //按鍵動作產(chǎn)生的脈沖	         
    	reg     [N-1:0]   key_rst_pre;                //定義一個寄存器型變量存儲上一個觸發(fā)時的按鍵值
            reg     [N-1:0]   key_rst;                    //定義一個寄存器變量儲存儲當(dāng)前時刻觸發(fā)的按鍵值         
            wire    [N-1:0]   key_edge;                   //檢測到按鍵由高到低變化是產(chǎn)生一個高脈沖         
            //利用非阻塞賦值特點,將兩個時鐘觸發(fā)時按鍵狀態(tài)存儲在兩個寄存器變量中
            always @(posedge clk  or  negedge rst)
              begin
                 if (!rst) begin
                     key_rst <= {N{1'b1}};                //初始化時給key_rst賦值全為1,{}中表示N個1
                     key_rst_pre <= {N{1'b1}};
                 end
                 else begin
                     key_rst <= key;                     
                     //第一個時鐘上升沿觸發(fā)之后key的值賦給key_rst,同時key_rst的值賦給key_rst_pre
                     key_rst_pre <= key_rst;             
                     //非阻塞賦值。相當(dāng)于經(jīng)過兩個時鐘觸發(fā),key_rst存儲的是當(dāng)前時刻key的值,key_rst_pre存儲的是前一個時鐘的key的值
                 end    
               end         
               assign  key_edge = key_rst_pre & (~key_rst);//脈沖邊沿檢測。當(dāng)key檢測到下降沿時,key_edge產(chǎn)生一個時鐘周期的高電平         reg	[17:0]	  cnt;                       
               //產(chǎn)生延時所用的計數(shù)器,系統(tǒng)時鐘12MHz,要延時20ms左右時間,至少需要18位計數(shù)器              
               //產(chǎn)生20ms延時,當(dāng)檢測到key_edge有效是計數(shù)器清零開始計數(shù)
            always @(posedge clk or negedge rst)
               begin
                 if(!rst)
                    cnt <= 18'h0;
                 else if(key_edge)
                    cnt <= 18'h0;
                 else
                    cnt <= cnt + 1'h1;
                 end           reg     [N-1:0]   key_sec_pre;                //延時后檢測電平寄存器變量
            reg     [N-1:0]   key_sec;                     
             //延時后檢測key,如果按鍵狀態(tài)變低產(chǎn)生一個時鐘的高脈沖。如果按鍵狀態(tài)是高的話說明按鍵無效
            always @(posedge clk  or  negedge rst)
              begin
                 if (!rst) 
                     key_sec <= {N{1'b1}};                
                 else if (cnt==18'h3ffff)
                     key_sec <= key;  
              end
           always @(posedge clk  or  negedge rst)
              begin
                 if (!rst)
                     key_sec_pre <= {N{1'b1}};
                 else                   
                     key_sec_pre <= key_sec;             
             end      
           assign  key_pulse = key_sec_pre & (~key_sec);      
           endmodule

    以上就是一個N位按鍵的消抖程序,如果有按鍵按下會輸出一個時鐘周期的高脈沖。下面我們可以試試用這個按鍵消抖的輸出來觸發(fā)LED的顯示,既按鍵一次LED翻轉(zhuǎn)。你也可以不加按鍵消抖試試用按鍵來控制LED(按一次變亮,再按一次滅掉)。

    下面的程序是例化調(diào)用debounce模塊來控制LED

    // ********************************************************************
    // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
    // ********************************************************************
    // File name    : top.v
    // Module name  : top
    // Author       : STEP
    // Description  :  
    // 
    // --------------------------------------------------------------------
    // Code Revision History : 
    // --------------------------------------------------------------------
    // Version: |Mod. Date:   |Changes Made:
    // V1.0     |2017/03/02   |Initial ver
    // --------------------------------------------------------------------
    // Module Function:進(jìn)過按鍵消抖后控制led顯示翻轉(zhuǎn) 
    module top (clk,rst,key,led);         
    input             clk;
            input             rst;
            input 	          key;                      				
    	output   reg      led;                 
    	wire              key_pulse;         //當(dāng)按鍵按下時產(chǎn)生一個高脈沖,翻轉(zhuǎn)一次led
            always @(posedge clk  or  negedge rst)
               begin
                 if (!rst) 
    		led <= 1'b1;
    	     else if (key_pulse)
    		led <= ~led;
    	     else
                    led <= led;
    	   end    
             //例化消抖module,這里沒有傳遞參數(shù)N,采用了默認(rèn)的N=1     
             debounce  u1 (                               
                           .clk (clk),
                           .rst (rst),
                           .key (key),
                           .key_pulse (key_pulse)
                           );
     endmodule

    引腳分配


    設(shè)置好復(fù)位鍵可消抖的按鍵,編譯完成后下載,通過按鍵就可以翻轉(zhuǎn)LED。你也可以定義多個按鍵控制多個LED,還可以比較不加按鍵消抖情況下實際的效果對比如何。

    信號引腳
    clkC1
    rstL14
    keyN14
    ledN13

    小結(jié)


    在本實驗學(xué)習(xí)了如何進(jìn)行按鍵的消抖。在很多應(yīng)用情況下我們必須采取消抖才能更好地控制邏輯。在下一個實驗計時控制中我們將學(xué)習(xí)計時的顯示和控制,在這里我們要用到按鍵的消抖以及數(shù)碼管,我們甚至可以用做一個計時器甚至電子表。



    關(guān)鍵詞: 消抖 FPGA Lattice Diamond 小腳丫

    評論


    相關(guān)推薦

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

    關(guān)閉
    主站蜘蛛池模板: 南宁市| 陆川县| 天峻县| 潜江市| 马关县| 南陵县| 乌兰县| 南江县| 青海省| 隆回县| 永吉县| 泌阳县| 赞皇县| 海盐县| 彩票| 孝义市| 黑山县| 丽江市| 东乌珠穆沁旗| 荥阳市| 陵川县| 漯河市| 崇义县| 剑阁县| 姚安县| 密山市| 盐边县| 乌拉特中旗| 海伦市| 陇川县| 稻城县| 博白县| 广丰县| 尖扎县| 甘谷县| 宣威市| 增城市| 崇信县| 昆山市| 九江县| 蒙城县|