久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

專注電子技術學習與研究
當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

Verilog按鍵消抖的理解

作者:liuyugde   來源:本站原創   點擊數:  更新時間:2010年08月30日   【字體:

  按鍵在按下時會產生抖動,釋放時也會產生抖動,所以在設計鍵盤掃描程序時必須考慮按鍵的消抖,我們一般只考慮按下時的抖動,而放棄對釋放時抖動的消抖。抖動時間一般為20ms左右。按下的最終結果是低電平。

  在單片機設計的的按鍵去抖思路是:檢測到按下時延時20ms,再檢測,如果狀態仍為按下,則確認是按下的;如果狀態為彈起的,則確認是干擾,無按鍵按下。



              圖1  按鍵抖動特性

有一個概念要理一下,按鍵按下時會有抖動,也就是說我們其實只按一次,但是實際產生的“按下”卻是許多次的,這些許多次集中在這20ms里。我們按的只是一次,而實際卻產生了許多次,那么就必須濾除其他的次數。單片機為了得到真正的“按下”,通過延時20ms,把其他的“按下”(也就是抖動)給濾除了。然后再次判斷是否有按下,因為有的時候干擾很大。

   而在FPGA中,基于下面的程序,理解如下:在這個程序里檢測按鍵是否按下的方法是脈沖邊沿檢法。而在單片機里是判斷是否為低電平的方法(那么在FPGA中可不可以也用這個方法呢?)第一次檢測到后,啟動20ms計數器,時間到后再檢測。這里的檢測方法跟脈沖邊沿檢測法有異曲同工之處,FPGA過20ms檢測按鍵是否按下,存儲檢測到的值,并且按位取反與前一個20ms檢測的值相與,得到一個值,如果為1,則判斷按鍵按下,否則則無按下。所以跟單片機按鍵掃描的原理是一樣的,不同的是檢測方法不一樣。

 圖2 FPGA按鍵的理解示意圖

其中key_an寄存器的功能是檢測第一次的“按下”,是cnt的啟動標志位。通過也能濾除干擾信號。

led_ctrl是確實有按鍵按下的信號,維持一個時鐘周期。

特權同學的Verilog鍵盤掃描程序

//說明:當三個獨立按鍵的某一個被按下后,相應的LED被點亮;

//            再次按下后,LED熄滅,按鍵控制LED亮滅
 

module sw_debounce(

                 clk,rst_n,

                     sw1_n,sw2_n,sw3_n,

                  led_d1,led_d2,led_d3

                 );

 

input   clk; //主時鐘信號,50MHz

input   rst_n;     //復位信號,低有效

input   sw1_n,sw2_n,sw3_n;      //三個獨立按鍵,低表示按下

output  led_d1,led_d2,led_d3;     //發光二極管,分別由按鍵控制

 

//---------------------------------------------------------------------------

reg[2:0] key_rst;  

 

always @(posedge clk  or negedge rst_n)

    if (!rst_n) key_rst <= 3'b111;

    else key_rst <= {sw3_n,sw2_n,sw1_n};

 

reg[2:0] key_rst_r;       //每個時鐘周期的上升沿將low_sw信號鎖存到low_sw_r中

 

always @ ( posedge clk  or negedge rst_n )

    if (!rst_n) key_rst_r <= 3'b111;

    else key_rst_r <= key_rst;

   

//當寄存器key_rst由1變為0時,led_an的值變為高,維持一個時鐘周期 

wire[2:0] key_an = key_rst_r & ( ~key_rst); //檢測到按下的第一次(cnt的啟動信號)

 

//---------------------------------------------------------------------------

reg[19:0]  cnt;    //計數寄存器

 

always @ (posedge clk  or negedge rst_n)

    if (!rst_n) cnt <= 20'd0;      //異步復位

       else if(key_an) cnt <=20'd0;

    else cnt <= cnt + 1'b1;

  

reg[2:0] low_sw;

 

always @(posedge clk  or negedge rst_n)

    if (!rst_n) low_sw <= 3'b111;

    else if (cnt == 20'hfffff)    //滿20ms,將按鍵值鎖存到寄存器low_sw中      cnt == 20'hfffff

      low_sw <= {sw3_n,sw2_n,sw1_n};

      

//---------------------------------------------------------------------------

reg  [2:0] low_sw_r;       //每個時鐘周期的上升沿將low_sw信號鎖存到low_sw_r中

 

always @ ( posedge clk  or negedge rst_n )

    if (!rst_n) low_sw_r <= 3'b111;

    else low_sw_r <= low_sw;

   

//當寄存器low_sw由1變為0時,led_ctrl的值變為高,維持一個時鐘周期 

wire[2:0] led_ctrl = low_sw_r[2:0] & ( ~low_sw[2:0]);

 

reg d1;

reg d2;

reg d3;

  

always @ (posedge clk or negedge rst_n)

    if (!rst_n) begin

        d1 <= 1'b0;

        d2 <= 1'b0;

        d3 <= 1'b0;

      end

    else begin          //某個按鍵值變化時,LED將做亮滅翻轉

        if ( led_ctrl[0] ) d1 <= ~d1;    

        if ( led_ctrl[1] ) d2 <= ~d2;

        if ( led_ctrl[2] ) d3 <= ~d3;

      end

 

assign led_d3 = d1 ? 1'b1 : 1'b0;           //LED翻轉輸出

assign led_d2 = d2 ? 1'b1 : 1'b0;

assign led_d1 = d3 ? 1'b1 : 1'b0;

  

endmodule

 

關閉窗口

相關文章

主站蜘蛛池模板: 国产成人99久久亚洲综合精品 | 久日精品 | 日韩和的一区二在线 | 色秀网站 | 国产98在线 | 免费, | 欧美专区在线 | 中文字幕成人av | 中文字幕一区二区三区不卡在线 | 成人av在线播放 | 成人精品啪啪欧美成 | 国产精品国产精品国产专区不片 | 久久在线看 | 日本精品视频一区二区三区四区 | 日韩午夜网站 | 日本精品视频 | aaa大片免费观看 | 国产精品亚洲精品 | 日韩欧美在线免费 | 黄色精品 | 涩涩视频网站在线观看 | 久久福利电影 | 一级免费在线视频 | 日韩视频一区二区三区 | 99免费精品| 夜夜夜操 | 亚洲 中文 欧美 日韩 在线观看 | 久久免费观看视频 | 成人福利在线观看 | 亚洲一区二区在线 | 一区二区在线 | 中文av字幕 | 日本精品在线一区 | 在线日韩视频 | 精品国产一区二区三区久久 | 一级电影免费看 | 亚洲精品一区二区三区四区高清 | 欧美激情在线精品一区二区三区 | 久久一区二区精品 | 亚洲自拍偷拍欧美 | av天天澡天天爽天天av | 精品二|