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