<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 牛人業(yè)話(huà) > 小梅哥和你一起深入學(xué)習FPGA之獨立按鍵檢測(上)

小梅哥和你一起深入學(xué)習FPGA之獨立按鍵檢測(上)

作者: 時(shí)間:2015-03-28 來(lái)源:網(wǎng)絡(luò ) 收藏

  幾乎沒(méi)有哪一個(gè)系統沒(méi)有輸入輸出設備,大到顯示器,小到led燈,輕觸按鍵。作為一個(gè)系統,要想穩定的工作,輸入輸出設備的性能占了很重要的角色。本實(shí)驗,小梅哥就通過(guò)一個(gè)獨立按鍵的檢測實(shí)驗,來(lái)正式步入基本外設驅動(dòng)開(kāi)發(fā)的大門(mén)。

本文引用地址:http://dyxdggzs.com/article/271738.htm

  一、 實(shí)驗目的

  實(shí)現4個(gè)獨立按鍵的抖動(dòng)檢測實(shí)驗,并通過(guò)4個(gè)獨立按鍵控制4個(gè)led燈亮滅狀態(tài)的翻轉。

  二、 實(shí)驗原理

  實(shí)際系統中常用的按鍵大部分都是輕觸式按鍵,如圖2-1所示。該按鍵內部由一個(gè)彈簧片和兩個(gè)固定觸點(diǎn)組成,當彈簧片被按下,則兩個(gè)固定觸點(diǎn)接通,按鍵閉合。彈簧片松開(kāi),兩個(gè)觸點(diǎn)斷開(kāi),按鍵也就斷開(kāi)了。根據這種按鍵的機械特性,在按鍵按下時(shí),會(huì )先有一段時(shí)間的不穩定期,在這期間,兩個(gè)觸點(diǎn)時(shí)而接通,時(shí)而斷開(kāi),我們稱(chēng)之為抖動(dòng),當按鍵大約按下20ms后,兩個(gè)觸點(diǎn)才能處于穩定的閉合狀態(tài),按鍵松開(kāi)時(shí)和閉合時(shí)情況類(lèi)似。而我們的工作在很高的頻率,按鍵接通或斷開(kāi)時(shí)任何一點(diǎn)小的抖動(dòng)都能輕易的捕捉到,如果不加區分的將每一次閉合或斷開(kāi)都當做一次按鍵事件,那么勢必一次按鍵動(dòng)作會(huì )被識別為很多次按鍵操作,從而導致系統工作穩定性下降。

  

 

  圖2-1 輕觸按鍵實(shí)物圖

  一次按鍵動(dòng)作的大致波形如下圖所示:

  

 

  因此,我們所需要做的工作,就是濾除按鍵按下和釋放時(shí)各存在的20ms的不穩定波形

  三、 硬件設計

  獨立按鍵屬于一種輸入設備,其與連接的IO口被接上了10K的上拉電阻,在按鍵沒(méi)有按下時(shí),FPGA會(huì )檢測到高電平;當按鍵按下后,FPGA的IO口上則將呈現低電平。因此,的實(shí)質(zhì)就是讀取FPGA的IO上的電平。

  

 

  圖3-1 獨立按鍵典型電路

  四、 架構設計

  本實(shí)驗由總共四個(gè)模塊組成,分別為L(cháng)ED驅動(dòng)模塊、獨立模塊、控制模塊和頂層模塊,其架構如下:

  

 

  

 

  以下為按鍵抖動(dòng)檢測的代碼,采用狀態(tài)機的方式編寫(xiě),總共有兩個(gè)狀態(tài),按下消抖為狀態(tài)0,釋放消抖為狀態(tài)1。具體的消抖流程代碼中的注釋已經(jīng)寫(xiě)的比較清楚,但如果全部用文字解釋出來(lái)還是有一定的復雜性。這也是實(shí)地講解和網(wǎng)上文檔的一點(diǎn)點(diǎn)差距吧,希望我后期的視頻里面能講清楚。其實(shí)抖動(dòng)消除的核心思路就是對按鍵狀態(tài)的變化進(jìn)行計時(shí),若兩次電平變化之間時(shí)間小于20ms,則視為抖動(dòng),若低電平穩定時(shí)間超過(guò)20ms,則表明檢測到了穩定的按鍵狀態(tài)。釋放時(shí)的消抖過(guò)程與按下時(shí)的消抖過(guò)程類(lèi)似。

  以下是代碼片段:

  module normal_keys_detect #(parameter KEY_WIDTH = 4)

  (Clk,Rst_n,Key_in,Key_Flag,Key_Value);

  input Clk;

  input Rst_n;

  input [KEY_WIDTH-1:0]Key_in;

  output reg Key_Flag;

  output reg[KEY_WIDTH-1:0]Key_Value;

  reg [KEY_WIDTH-1:0]key_tmp,key_tmp1;

  reg [19:0]cnt1;

  reg state;

  wire level_change; /*按鍵狀態(tài)變化標志信號*/

  localparam cnt1_TOP = 1_000_000;

  /*-------存儲按鍵狀態(tài)的上一個(gè)狀態(tài)---------------*/

  always @ (posedge Clk or negedge Rst_n)

  begin

  if(!Rst_n)

  begin

  key_tmp <= 'd0;

  key_tmp1 <= 'd0;

  end

  else

  begin

  key_tmp <= Key_in;

  key_tmp1 <= key_tmp;

  end

  end

  /*---通過(guò)比較按鍵上一個(gè)狀態(tài)和此時(shí)刻狀態(tài)來(lái)獲知按鍵狀態(tài)是否改變---*/

  assign level_change = (key_tmp == key_tmp1)?1'b0:1'b1;

  always @ (posedge Clk or negedge Rst_n)

  if(!Rst_n)

  begin

  cnt1 <= 20'd0;

  state <= 1'b0;

  Key_Value <= 4'b0000;

  Key_Flag <= 1'b0;

  end

  else

  begin

  case(state)

  0: /*按下檢測*/

  //沒(méi)有電平變化,且按鍵輸入狀態(tài)不全為1

  if(!level_change & key_tmp1 != {KEY_WIDTH{1'b1}})

  begin

  if(cnt1 == cnt1_TOP)/*計數滿(mǎn)消抖所需時(shí)間*/

  begin

  Key_Value <= ~Key_in;

  Key_Flag <= 1;

  cnt1 <= 0;

  state <= 1;

  end

  else

  cnt1 <= cnt1 + 1'b1;

  end

  else

  begin

  cnt1 <= 0;

  Key_Flag <= 0;

  state <= 0;

  end

  1:/*釋放檢測*/

  begin

  Key_Flag <= 0;

  /*沒(méi)有電平變化,且按鍵輸入狀態(tài)全為1*/

  if(!level_change & key_tmp1 == {KEY_WIDTH{1'b1}})

  begin

  if(cnt1 == cnt1_TOP)/*計數滿(mǎn)消抖所需時(shí)間*/

  begin

  cnt1 <= 0;

  state <= 0;

  end

  else

  cnt1 <= cnt1 + 1'b1;

  end

  else

  begin

  cnt1 <= 0;

  state <= 1;

  end

  end

  endcase

  end

  endmodule

  七、 測試平臺設計

  本實(shí)驗主要對的結果進(jìn)行觀(guān)察和分析,通過(guò)仿真,驗證設計的正確性和合理性。按鍵消抖模塊的testbench的代碼如下:

  以下是代碼片段:

  `timescale 1ns/1ns

  module normal_keys_detect_tb;

  reg Clk;

  reg Rst_n;

  reg [3:0]Key_in;

  wire Key_Flag;

  wire [3:0]Key_Value;

  normal_keys_detect

  #(

  .KEY_WIDTH(4)

  )

  normal_keys_detect_inst1(

  .Clk(Clk),

  .Rst_n(Rst_n),

  .Key_in(Key_in),

  .Key_Flag(Key_Flag),

  .Key_Value(Key_Value)

  );

  initial begin

  Clk = 1;

  Rst_n = 0;

  Key_in = 4'b1111;

  #100;

  Rst_n = 1;

  press_key(0);

  #30000000;

  press_key(1);

  #30000000;

  press_key(2);

  #30000000;

  press_key(3);

  #30000000;

  $stop;

  end

  always #10 Clk = ~Clk;

  task press_key;

  input [1:0]Key;

  begin

  Key_in = 4'b1111;

  /*按下抖動(dòng)*/

  #100 Key_in[Key] = 0;

  #200 Key_in[Key] = 1;

  #300 Key_in[Key] = 0;

  #400 Key_in[Key] = 1;

  #500 Key_in[Key] = 0;

  #600 Key_in[Key] = 1;

  #700 Key_in[Key] = 0;

  #800 Key_in[Key] = 1;

  #900 Key_in[Key] = 0;

  /*穩定期*/

  #22000000;

  /*釋放抖動(dòng)*/

  #100 Key_in[Key] = 1;

  #200 Key_in[Key] = 0;

  #300 Key_in[Key] = 1;

  #400 Key_in[Key] = 0;

  #500 Key_in[Key] = 1;

  #600 Key_in[Key] = 0;

  #700 Key_in[Key] = 1;

  #800 Key_in[Key] = 0;

  #900 Key_in[Key] = 1;

  end

  endtask

  endmodule

  testben中使用了一個(gè)任務(wù)(task),該任務(wù)模擬按鍵抖動(dòng)的過(guò)程,給按鍵按下和釋放時(shí)增加抖動(dòng),調用時(shí)只需要輸入需要按下的按鍵編號,該任務(wù)便可自動(dòng)完成按下抖動(dòng)、穩定、松開(kāi)抖動(dòng)的過(guò)程。

  整個(gè)工程的testbench與消抖模塊的testbench一樣,只需要在例化部分將消抖模塊替換為頂層模塊即可,同時(shí)將每個(gè)按鍵的任務(wù)由一次調用該為兩次調用即可,詳細代碼如下:

  以下是代碼片段:

  `timescale 1ns/1ns

  module top_tb;

  reg Clk;

  reg Rst_n;

  reg [3:0]Key_in;

  wire [3:0]Led;

  top top_inst(

  .Clk(Clk),

  .Rst_n(Rst_n),

  .Key_in(Key_in),

  .Led(Led)

  );

  initial begin

  Clk = 1;

  Rst_n = 0;

  Key_in = 4'b1111;

  #100;

  Rst_n = 1;

  press_key(0);

  #30000000;

  press_key(0);

  #30000000;

  press_key(1);

  #30000000;

  press_key(1);

  #30000000;

  press_key(2);

  #30000000;

  press_key(2);

  #30000000;

  press_key(3);

  #30000000;

  press_key(3);

  #30000000;

  $stop;

  end

  always #10 Clk = ~Clk;

  task press_key;

  input [1:0]Key;

  begin

  Key_in = 4'b1111;

  /*按下抖動(dòng)*/

  #100 Key_in[Key] = 0;

  #200 Key_in[Key] = 1;

  #300 Key_in[Key] = 0;

  #400 Key_in[Key] = 1;

  #500 Key_in[Key] = 0;

  #600 Key_in[Key] = 1;

  #700 Key_in[Key] = 0;

  #800 Key_in[Key] = 1;

  #900 Key_in[Key] = 0;

  /*穩定期*/

  #22000000;

  /*釋放抖動(dòng)*/

  #100 Key_in[Key] = 1;

  #200 Key_in[Key] = 0;

  #300 Key_in[Key] = 1;

  #400 Key_in[Key] = 0;

  #500 Key_in[Key] = 1;

  #600 Key_in[Key] = 0;

  #700 Key_in[Key] = 1;

  #800 Key_in[Key] = 0;

  #900 Key_in[Key] = 1;

  end

  endtask

  endmodule

fpga相關(guān)文章:fpga是什么


可控硅相關(guān)文章:可控硅工作原理


比較器相關(guān)文章:比較器工作原理


led顯示器相關(guān)文章:led顯示器原理


上拉電阻相關(guān)文章:上拉電阻原理


關(guān)鍵詞: FPGA 按鍵檢測

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>