勇敢的芯伴你玩轉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的翻轉做相應處理。 |