系統的訊號輸入中,鍵盤因其結構簡單而被廣泛使用。因此,對鍵盤的輸入(邏輯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) //
一旦檢測到鍵值 }
這段軟消抖程式從機理上看不會有什麼問題,通常在軟體程式不太"繁忙"的情況下也能夠很好的消抖並做相應處理。但是如果在延時期間產生了中斷,則此中斷可能無法得到響應。
對於硬體資源豐富的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 <= ;
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等並行處理的系統,其優勢就很明顯,只要片內邏輯資源夠用,通過硬體加速軟體消抖的處理,完全可以做到按鍵消抖並行化,不影響系統的實時性。
按鍵消抖電路原理
按鍵消抖電路原理 fpga開發中按鍵消抖與單脈衝發生器電路 為了使按鍵消抖電路模組簡潔,移植性好,在此用計數器的方式實現按鍵消抖的功能。計數器模值n根據抖動訊號的脈衝寬度和取樣脈衝訊號clk的週期大小決定。計數模值n 延時 脈衝訊號取樣週期。一般按鍵抖動時間為5 10 ms,甚至更長。筆者用的開發板...
微控制器 按鍵消抖及原理(硬體和軟體方法詳解)
在設計微控制器按鍵輸入的時候,進行按鍵消抖是防止按鍵輸入被cpu誤讀多次的必要手段。一 按鍵抖動 通常的按鍵所用開關為機械彈性開關,當機械觸點斷開 閉合時,由於機械觸點的彈性作用,乙個按鍵開關在閉合時不會馬上穩定地接通,在斷開時也不會一下子斷開。因而在閉合及斷開的瞬間均伴隨有一連串的抖動,為了不產生...
從硬體電路和軟體方面進行按鍵消抖
什麼是按鍵抖動及按鍵抖動產生的原因?最近在專案中用到了機械彈性開關,這種開關在按下時候不會馬上就有穩定的接通,在彈開時候也不會馬上斷開,在按下和彈開的瞬間會產生一系列抖動。而我專案中stm32晶元是通過中斷對按鍵進行判斷的,當晶元檢測到上公升沿時認為按鍵按下一次,因為存在開關抖動,所以一次按鍵操作會...