勇敢的芯伴你玩轉Altera FPGA連載59:按鍵消抖與LED開(kāi)關(guān)實(shí)例

發(fā)布時(shí)間:2018-4-3 20:17    發(fā)布者:rousong1989
勇敢的芯伴你玩轉Altera FPGA連載59:按鍵消抖與LED開(kāi)關(guān)實(shí)例
特權同學(xué),版權所有
配套例程和更多資料下載鏈接:
http://pan.baidu.com/s/1i5LMUUD
         除了前面所論及的按鍵消抖處理,該實(shí)驗還需要用到LED指示燈進(jìn)行按鍵狀態(tài)的指示。該實(shí)驗要實(shí)現一個(gè)獨立按鍵控制一個(gè)發(fā)光二極管亮暗狀態(tài)翻轉。上電初始,發(fā)光二極管不亮,當某一個(gè)按鍵被按下后(即鍵值為0),發(fā)光二極管被點(diǎn)亮,當按鍵再次被按下時(shí),發(fā)光二極管則又滅了,按鍵控制發(fā)光二級管如此反復的進(jìn)行亮暗變化。
         本實(shí)例代碼如下。
module cy4(
            input ext_clk_25m, //外部輸入25MHz時(shí)鐘信號
            input ext_rst_n,   //外部輸入復位信號,低電平有效
            input[3:0] key_v,//4個(gè)獨立按鍵輸入,未按下為高電平,按下后為低電平
            output reg[7:0] led    //8個(gè)LED指示燈接口   
            );
//-------------------------------------
//按鍵抖動(dòng)判斷邏輯
wire key;   //所有按鍵值相與的結果,用于按鍵觸發(fā)判斷
reg[3:0] keyr;  //按鍵值key的緩存寄存器
assign key = key_v[0] & key_v[1] & key_v[2] & key_v[3];
always @(posedge ext_clk_25m or negedge ext_rst_n)
    if (!ext_rst_n) keyr <=4'b1111;
    else keyr <= {keyr[2:0],key};
wire key_neg = ~keyr[2] & keyr[3]; //有按鍵被按下  
wire key_pos = keyr[2] & ~keyr[3]; //有按鍵被釋放
//-------------------------------------
//定時(shí)計數邏輯,用于對按鍵的消抖判斷
reg[19:0]  cnt;
    //按鍵消抖定時(shí)計數器
always @ (posedge ext_clk_25m or negedge ext_rst_n)
   if (!ext_rst_n) cnt <= 20'd0;   
    else if(key_pos || key_neg) cnt<= 20'd0;
    else if(cnt < 20'd999_999) cnt<= cnt + 1'b1;
    else cnt <= 20'd0;
  
reg[3:0] key_value[1:0];
    //定時(shí)采集按鍵值
always @(posedge ext_clk_25m or negedge ext_rst_n)
    if (!ext_rst_n) begin
        key_value[0] <= 4'b1111;
        key_value[1] <= 4'b1111;
    end
    else begin
        key_value[1] <=key_value[0];      
        if(cnt == 20'd999_999)key_value[0] <= key_v;  //定時(shí)鍵值采集
        else ;  
    end
wire[3:0] key_press = key_value[1] & ~key_value[0];       //消抖后按鍵值變化標志位
//-------------------------------------
//LED切換控制
always @ (posedge ext_clk_25m or negedge ext_rst_n)
    if (!ext_rst_n) led <= 8'hff;
    else if(key_press[0]) led[0]<= ~led[0];
    else if(key_press[1]) led[1] <=~led[1];
    else if(key_press[2]) led[2] <=~led[2];
    else if(key_press[3]) led[3] <=~led[3];
    else ;
  
endmodule
         這段代碼的前提是,所有4個(gè)獨立按鍵,在任意一個(gè)按鍵被按下和釋放期間,不會(huì )有其它按鍵也被按下或釋放。在通常的應用中,一定也是符合這個(gè)假設的場(chǎng)景。
         我們處理消抖的邏輯是這樣的:首先將所有按鍵輸入信號做“邏輯與”操作,得到信號key。信號key的值鎖存4拍分別存儲到寄存器keyr[0]、keyr[1]、keyr[2]和keyr[3]中(此時(shí)的采樣頻率和基準時(shí)鐘一致,為25MHz),通過(guò)keyr[2]和keyr[3]這兩個(gè)寄存器獲得key信號的上升沿標志位key_pos和下降沿標志位key_neg。key_pos和key_neg的獲得過(guò)程分別如圖8.13和圖8.14所示,這是很典型的“脈沖邊沿檢測法”,后續很多代碼中我們都會(huì )用到這個(gè)邏輯。
圖8.13 上升沿脈沖檢測波形
圖8.14 下降沿脈沖檢測波形
計數器cnt在key_pos和key_neg有效拉高時(shí),都會(huì )清零重新開(kāi)始計數,計數器cnt的最大計數值為40ms,若在某個(gè)固定時(shí)間內按鍵有抖動(dòng)(這個(gè)抖動(dòng)通常不會(huì )大于40ms,這是經(jīng)驗值),那么這段時(shí)間內計數器cnt會(huì )頻繁的清0,cnt的計數值就不會(huì )計數到最大值。一旦cnt計數到最大值,我們就會(huì )對當前所有的按鍵值做一次鎖存,鎖存到4位寄存器key_value[0]中(即這個(gè)鎖存操作的采樣率是40ms為周期的,若按鍵的抖動(dòng)小于40ms,那么采樣的按鍵值是不會(huì )變化的,那么就達到了消除抖動(dòng)的目的)。隨后,以系統時(shí)鐘節拍下,key_value[1]會(huì )鎖存key_value[0]的值。當按鍵按下操作,產(chǎn)生按鍵值的下降沿變化,那么key_press就會(huì )獲得一個(gè)時(shí)鐘周期高脈沖的鍵值指示信號,通過(guò)這個(gè)鍵值指示信號,我們就可以對LED的翻轉做相應處理。

本文地址:http://selenalain.com/thread-524214-1-1.html     【打印本頁(yè)】

本站部分文章為轉載或網(wǎng)友發(fā)布,目的在于傳遞和分享信息,并不代表本網(wǎng)贊同其觀(guān)點(diǎn)和對其真實(shí)性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問(wèn)題,我們將根據著(zhù)作權人的要求,第一時(shí)間更正或刪除。
您需要登錄后才可以發(fā)表評論 登錄 | 立即注冊

關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點(diǎn)地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權所有   京ICP備16069177號 | 京公網(wǎng)安備11010502021702
快速回復 返回頂部 返回列表
午夜高清国产拍精品福利|亚洲色精品88色婷婷七月丁香|91久久精品无码一区|99久久国语露脸精品|动漫卡通亚洲综合专区48页