系統的信號輸入中,鍵盤因其結構簡單而被廣泛使用。因此,對鍵盤的輸入(邏輯0或1)進行準確采樣,避免錯誤輸入是非常有必要的。理想的鍵盤輸入特性如圖1所示:按鍵沒有按下時,輸入為邏輯1,一旦按下則輸入立刻變為邏輯0,松開時輸入則立刻變為邏輯1。
圖 1理想鍵盤輸入特性
然而實際的鍵盤受制造工藝等影響,其輸入特性不可能如圖1完美。當按鍵按下時,在觸點即將接觸到完全接觸這段時間里,鍵盤的通斷狀態很可能已經改變了多次。即在這段時間里,鍵盤輸入了多次邏輯0和1,也就是輸入處于失控狀態。如果這些輸入被系統響應,則系統暫時也將處于失控狀態,這是我們要盡量避免的。在觸點即將分離到完全分離這段時間也是一樣的。實際鍵盤的輸入特性如圖2所示:
圖 2實際鍵盤輸入特性
我們可以看到:鍵盤在輸入邏輯轉換時,實際上是產生了瞬時的高頻干擾脈沖。按鍵消抖的目的在于消除此干擾,以達到接近圖1所示的理想輸入特性。有兩個階段可以設法消除此干擾:1.在鍵盤信號輸入系統之前(系統外);2.鍵盤信號輸入系統以后(系統內)。
在信號輸入系統之前將抖動干擾消除,可以節省系統資源,提高系統對其他信號的響應能力,也就是硬件消抖。一種比較巧妙的硬件消抖電路結構如圖3所示:
圖 3用基本SR鎖存器構成的消抖電路
該電路利用基本SR鎖存器的記憶作用消除開關觸點振動所產生的影響。開關S每切換一次,輸出端只有一次翻轉,不存在抖動波形(讀者可以根據SR鎖存器功能自行分析,此處略)。但是使用SR鎖存器消抖只適用于單刀雙擲開關,實際應用當中常用的鍵盤多是兩個接線端的按鍵。對此類按鍵的常用硬件消抖電路如圖4所示:
圖 4常用鍵盤硬件消抖電路
此電路利用電容平波,再經過施密特反相器整形之后就得到了沒有毛刺的脈沖波。
軟件消抖要占用系統資源,在系統資源充足的情況下使用軟件消抖更加簡單。軟件消抖的實質在于降低鍵盤輸入端口的采樣頻率,將高頻抖動略去。實際應用中通常采用延時跳過高頻抖動區間,然后再檢測輸入做出相應處理。一般程序代碼如下:
if(value == 0)//一旦檢測到鍵值 { Delay();//延時20ms,有效濾除按鍵的抖動 if(value == 0)//再次確定鍵值是否有效 { ……//執行相應處理 } } |
這段軟消抖程序從機理上看不會有什么問題,通常在軟件程序不太"繁忙"的情況下也能夠很好的消抖并做相應處理。但是如果在延時期間產生了中斷,則此中斷可能無法得到響應。
對于硬件資源豐富的FPGA系統,可以使用硬件來減輕軟件工作量,通常稱之為"硬件加速"。在按鍵信號輸入到軟件系統前用邏輯對其進行一下簡單的處理即可實現所謂的"硬件消抖",verilog代碼如下:
//對輸入信號inpio硬件濾波,每20ms采樣一次當前值 reg[18:0] cnt; //20ms計數器 always @(posedge clk_25m or negedge rst_n) if(!rst_n) cnt <= 19'd0; else if(cnt < 19'd500000) cnt <= cnt+1'b1; else cnt <= 19'd0; reg[1:0] inpior;//當前inpio信號鎖存,每20ms鎖存一拍 always @(posedge clk_25m or negedge rst_n) if(!rst_n) inpior <= 2'b11; else if(cnt == 19'h7ffff) inpior <= {inpior[0],inpior}; wire inpio_swin =inpior[0] | inpior[1];//前后20ms兩次鎖存值都為0時才為0 |
該程序中設置了一個20ms計數器,通過間隔20ms對輸入信號inpio采樣兩次,兩次相同則認為鍵盤輸入穩定,得到用硬件邏輯處理后的inpio_swin信號則是消抖處理過的信號。軟件程序就不再需要delay()來濾波了,也不會出現使用純軟件處理出現的"中斷失去響應"的情況了,這就是"硬件加速"的效果。
上述verilog代碼采用間隔采樣來達到消抖的目的,對于不同物理特性的鍵盤,最佳的間隔時間采樣時間也不同,因此還存在一些不穩定因素。下面介紹一種更好的軟消抖程序,同樣采用"硬件加速",不同之處在于使用了有限狀態機來實現,其VHDL代碼如下:
LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_unsigned.all; ENTITY xiaod IS //端口描述:clk輸入檢測時鐘;reset復位信號;din原始按鍵信號輸入;dout去抖動輸出信號 PORT ( clk : IN STD_LOGIC ; reset : IN STD_LOGIC ; din : IN STD_LOGIC ; dout : OUT STD_LOGIC ); END ENTITY; ARCHITECTURE RTL OF xiaod IS TYPE state IS( s0,s1,s2,s3); SIGNAL pre_s, next_s: state; BEGIN P0:PROCESS( reset, clk ) BEGIN if reset = '0' then pre_s <= s0; elsif rising_edge( clk ) then pre_s <= next_s; else null; end if; END PROCESS P0; P1:PROCESS( pre_s, next_s, din ) BEGIN case pre_s is when s0 => dout <= '1'; if din = '1' then next_s <= s0; else next_s <= s1; end if; when s1 => dout <= '1'; if din = '1' then next_s <= s0; else next_s <= s2; end if; when s2 => dout <= '1'; if din = '1' then next_s <= s0; else next_s <= s3; end if; when s3 => dout <= '0'; if din = '1' then next_s <= s0; else next_s <= s1; end if; end case; END PROCESS P1; END RTL; |
該VHDL代碼描述了一個狀態機,其狀態轉換圖如圖所示:
圖 5狀態轉換圖
該狀態機有4個狀態:S0、S1、S2、S3,其中前3個狀態輸出高電平,最后一個狀態輸出低電平。初始狀態為S0,設按鍵未按下時為高電平,按下則為低電平。在按鍵按下到完全生效期間有一系列的抖動,對于持續時間為1-2個時鐘周期的低電平抖動將被消除,對于持續時間為3個或以上時鐘周期的低電平則認為按鍵有效,輸出一個時鐘周期的低電平脈沖(讀者可以根據狀態轉換圖畫出相應的時序圖進行分析)。如果持續輸入為低電平,則每隔兩個時鐘周期輸出一個低電平,此時認為按鍵處于"長按"輸入狀態,可以編程設置相應功能。在按鍵松開階段其抖動也可以一樣被消除。
適用于FPGA的按鍵消抖方法還有一些,如計數器型、D觸發器型等,在此就不作介紹了。
通過上面一些按鍵消抖方法的介紹分析,我們可以看到,傳統單片機等系統大多是串行處理,即順序執行,只能并行處理一些中斷程序。對于這樣的系統,只能采用單純軟件或硬件消抖,但都不那么完美。而對于FPGA等并行處理的系統,其優勢就很明顯,只要片內邏輯資源夠用,通過硬件加速軟件消抖的處理,完全可以做到按鍵消抖并行化,不影響系統的實時性。
-
電路
+關注
關注
172文章
5901瀏覽量
172134 -
鍵盤
+關注
關注
4文章
859瀏覽量
39647 -
鎖存器
+關注
關注
8文章
906瀏覽量
41496
原文標題:按鍵原理和軟硬件按鍵消抖動
文章出處:【微信號:aidanpianji,微信公眾號:單片機】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論