乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      按鍵消抖

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

       

       

       輕觸按鍵實(shí)物圖

       

      一次按鍵動作的大致波形如下圖所示:

       

       

            因此,我們所需要做的工作,就是濾除按鍵按下和釋放時各存在的20ms的不穩(wěn)定波形。做法思路是:檢測按鍵按下---》等待20Ms ----》檢測此時按鍵鍵值,若為按下值則按下有效,否則按下無效(后面可以檢測亦可以不檢測,據(jù)具體情況而定----》檢測到按鍵松開----》延遲20Ms ----》檢測此時的鍵值,若為按下值則松開無效,否則按鍵松開)
      硬件電路:    
              獨(dú)立按鍵屬于一種輸入設(shè)備,其與FPGA連接的IO口被接上了10K的上拉電阻,在按鍵沒有按下時,F(xiàn)PGA會檢測到高電平;當(dāng)按鍵按下后,F(xiàn)PGA的IO口上則將呈現(xiàn)低電平。因此,按鍵檢測的實(shí)質(zhì)就是讀取FPGA的IO上的電平。


      獨(dú)立按鍵典型電路
       verilog 程序如下所示:
        
      復(fù)制代碼
      /********************************Copyright**************************************                           
      **----------------------------File information--------------------------
      ** File name  :key_shake.v  
      ** CreateDate :2015.03
      ** Funtions   : 按鍵的消抖操作:在復(fù)位之后的100us內(nèi),不響應(yīng)按鍵的操作,在之后有按鍵按下后,有20ms的延遲,之后輸出按鍵輸出.
      ** Operate on :M5C06N3L114C7
      ** Copyright  :All rights reserved[F]. 
      ** Version    :V1.0
      **---------------------------Modify the file information----------------
      ** Modified by   :
      ** Modified data :        
      ** Modify Content:V1.1:clk-->clk_100M, 常數(shù)聲明放到一起,便于修改。
      *******************************************************************************/
       
       module  key_shake (
                 clk_100M,
                 rst_n,
                 
                  key_in,
                  key_out
                   );
       input          clk_100M;            //100Mhz
       input          rst_n;
       
       input          key_in;
       output         key_out;
       
       //--------------------------------------
       //在復(fù)位之后的100us內(nèi),不響應(yīng)按鍵的操作
       localparam    t_100us  = 14'd9999;
       localparam    t1ms = 17'd99999;       //定時1ms 
       localparam    t_20ms = 5'd20;
          
        reg    [13:0]   cnt;
          reg             key_en;         //復(fù)位之后允許按鍵輸入標(biāo)志
       always @(posedge clk_100M or negedge rst_n)
       begin
        if(!rst_n)
         begin
            cnt <= 0;
                  key_en <=0;
          end
        else 
          begin
            if(cnt == t_100us)
                    begin
                         key_en <= 1;
                       end
             else
                    begin
                          key_en <= 0; 
                         cnt <= cnt + 1;
                    end
          end
        end
       
       //--------------------------------------------------
       wire         HtoL_flag;         //下降沿標(biāo)志
       wire         LtoH_flag;         //上升沿標(biāo)志
       reg   [2:0]   key_reg;
       always @(posedge clk_100M or negedge rst_n)
       begin
        if(!rst_n)
         begin
            key_reg <= 3'b111;            //默認(rèn)沒按下狀態(tài)為高,按下之后為低.反之則為3'b000;
          end
        else 
          begin
            key_reg <= {key_reg[1:0],key_in};  
          end
        end
          
       assign HtoL_flag = key_en?(key_reg[2:1] == 2'b10):0;            //下降沿檢測,一個時鐘的高電平
       assign LtoH_flag = key_en?(key_reg[2:1] == 2'b01):0;               //上升沿檢測,一個時鐘的高電平  
      //---------------------------------------------
       reg          cnt_en;                 //計數(shù)使能標(biāo)志
      
       reg   [16:0]  cnt2; 
       always @(posedge clk_100M or negedge rst_n)
       begin
        if(!rst_n)
         begin
            cnt2 <= 17'd0;
          end
        else if((cnt_en)&&(cnt2 == t1ms))
          begin
            cnt2 <= 17'd0;
          end
          else if(cnt_en)
          begin
            cnt2 <= cnt2 + 17'd1;
          end    
          else 
                cnt2 <= 17'd0;    
        end
          
       reg   [4:0]   cnt3; 
       always @(posedge clk_100M or negedge rst_n)
       begin
        if(!rst_n)
         begin
             cnt3 <= 5'd0;
          end
        else if((cnt_en)&&(cnt2 == t1ms))
          begin
                  if(cnt3 == t_20ms )
                     cnt3 <= t_20ms;
                  else
               cnt3 <= cnt3 + 1;                              
          end
          else if(!cnt_en)
             cnt3 <= 5'd0;        
        end
          
      //----------------------------------
      //按鍵狀態(tài)機(jī)
          reg  [2:0]  i;
          reg      key_down;        //按鍵按下標(biāo)志
          reg      key_up;          //按鍵釋放標(biāo)志  
          always @(posedge clk_100M or negedge rst_n)
           begin
            if(!rst_n)
             begin
                      key_down <= 0;
                      key_up <= 0;
                      i <= 0;
                      cnt_en <= 0;
              end
            else 
              begin
                case(i)
                       'd0:
                          begin
                                   key_down <= 0;
                             key_up <= 0;    
                            if(HtoL_flag) i <= 'd1;         //檢測到按下
                                  else if(LtoH_flag) i <= 'd2;    //檢測到釋放按鍵
                                  else  i  <= 'd0;
                           end
                          'd1:
                            begin
                                  if(cnt3 == t_20ms )
                                    begin
                                          if(!key_in)                  //檢測到按鍵依然被按下
                                         begin
                                             key_down <= 1;            //按鍵按下成功
                                             i <= 'd3;
                                             cnt_en <= 0;
                                            end
                                          else
                                              begin
                                                 key_down <= 0; 
                                               i <= 'd0;
                                               cnt_en <= 0;        
                                               end
                                       end
                                   else
                                     cnt_en <= 1;
                                  end
                          'd2:
                            begin
                                  if(cnt3 == t_20ms )
                                    begin
                                          if(key_in)                  //檢測到按鍵被釋放
                                         begin
                                             key_up <= 1;             //按鍵釋放成功
                                             i <= 'd3;
                                             cnt_en <= 0;
                                            end
                                          else
                                              begin
                                                 key_up <= 0;  
                                               i <= 'd0;
                                               cnt_en <= 0;        
                                               end
                                       end
                                   else
                                     cnt_en <= 1;
                                  end
                          'd3:
                            begin
                                   key_up <= 0;  
                                   key_down <= 0;            
                                   i <= 'd0;                             
                               end                    
                        default:i <= 'd0;    
                      endcase            
              end
            end
              
       assign      key_out = key_down;         //當(dāng)按鍵被按下有效時
      // assign   key_out = key_up;         //當(dāng)按鍵被釋放后才有效時
      endmodule
      復(fù)制代碼

       

       測試代碼如下:     

      復(fù)制代碼
      /********************************Copyright**************************************                           
      **----------------------------File information--------------------------
      ** File name  :key_testbench.v  
      ** CreateDate :2015.03
      ** Funtions   :按鍵消抖的測試文件
      ** Operate on :M5C06N3L114C7
      ** Copyright  :All rights reserved. 
      ** Version    :V1.0
      **---------------------------Modify the file information----------------
      ** Modified by   :
      ** Modified data :        
      ** Modify Content:
      *******************************************************************************/
       
       module  key_testbench;
        
          reg          clk;
          reg          rst_n;
          reg          key_in;
          wire         key_out;
          
       
       key_shake  key_shake_1(
                                           .clk,
                                           .rst_n,
                                           
                                           .key_in,
                                           .key_out
                                               );
                                               
      
      localparam  tck = 24;
      localparam  t = 1000/tck;
      
      always  #(t/2)  clk = ~clk;
      
      task key_in_down;
       begin
           #(3*t)       key_in = 1;
           #(3*t)       key_in = 0;     
           #(8*t)       key_in = 1;
           #(8*t)    key_in = 0;
           #(13*t)   key_in = 1;
           #(13*t)     key_in = 0;
        end
       endtask
       
      task key_in_up;
       begin
           #(3*t)        key_in = 0;     
           #(3*t)        key_in = 1;     
         #(8*t)        key_in = 0;     
           #(8*t)        key_in = 1;         
           #(13*t)      key_in = 0;     
           #(13*t)      key_in = 1;                   
        end
      endtask
          
      initial 
        begin
          clk = 0;
              rst_n = 0;
              key_in = 1;
              
              #(100*t)  rst_n = 1;
              
              #(100*t);
            #(10*t)    key_in_down;
            #(100*t);
            #(10*t)    key_in_up;
              
            #(8000*t);         
          #(10*t) repeat(2)     key_in_down;          //按下時抖動
           
            #(640000*t);                             //按下時間
           
            #(10*t) repeat(2)  key_in_up;            //釋放時抖動
              
        end
          
      endmodule
      復(fù)制代碼

       仿真結(jié)果:

       1、在復(fù)位之后100us之前按下按鍵時,不響應(yīng)。

       2、抖動(按下后20ms之內(nèi)釋放)。

       
        3、按下之后檢測以及釋放之后的檢測。
        

       

      如果將按鍵按下有效時刻、按鍵釋放有效時刻和按鍵所處狀態(tài)全部表現(xiàn)出來,則代碼稍作修改即可:

        

      復(fù)制代碼
      /********************************Copyright**************************************                           
      **----------------------------File information--------------------------
      ** File name  :key_shake.v  
      ** CreateDate :2015.03
      ** Funtions   : 按鍵的消抖操作:在復(fù)位之后的100us內(nèi),不響應(yīng)按鍵的操作,在之后有按鍵按下后,有20ms的延遲,檢測,然后松開時也有20ms的檢測,之后輸出按鍵輸出.
      ** Operate on :M5C06N3L114C7
      ** Copyright  :All rights reserved[F]. 
      ** Version    :V1.0
      **---------------------------Modify the file information----------------
      ** Modified by   :
      ** Modified data :        
      ** Modify Content:V1.1:clk-->clk_100M, 常數(shù)聲明放到一起,便于修改。
      *******************************************************************************/
       
       module  key_shake (
                           clk,
                           rst_n,
                 
                           key_in,
                           key_down_out,   
                           key_up_out,
                           key_in_out
                   );
       input          clk;            //24Mhz
       input          rst_n;
       
       input          key_in;
       output         key_down_out;     //按下輸出
       output         key_up_out;       //釋放輸出
       output         key_in_out;       //跟隨輸入輸出
       
       //--------------------------------------
       //在復(fù)位之后的100us內(nèi),不響應(yīng)按鍵的操作
         parameter  t_20ms = 5'd20;
           
          `define      CLK_20M
      //    `define      CLK_24M
      //    `define      CLK_50M
              
        `ifdef   CLK_20M
             parameter  t_100us  = 12'd1999;
               parameter  t1ms = 16'd19999;       //定時1ms 
          `endif
       
        `ifdef   CLK_20M
             parameter  t_100us  = 12'd2399;
               parameter  t1ms = 16'd23999;       //定時1ms 
          `endif
       
       
        `ifdef   CLK_20M
             parameter  t_100us  = 13'd4999;
               parameter  t1ms = 16'd49999;       //定時1ms 
          `endif
       
       
      
          reg    [12:0]   cnt;
          reg             key_en;         //復(fù)位之后允許按鍵輸入標(biāo)志
        always @(posedge clk or negedge rst_n)
        begin
         if(!rst_n)
           begin
            cnt <= 0;
            key_en <=0;
           end
        else 
          begin
            if(cnt == t_100us)
              begin
                key_en <= 1;
              end
            else
              begin
                key_en <= 0; 
                cnt <= cnt + 1;
              end
          end
        end
       
       //--------------------------------------------------
       wire          HtoL_flag;         //下降沿標(biāo)志
       wire          LtoH_flag;         //上升沿標(biāo)志
       reg   [2:0]   key_reg;
       always @(posedge clk or negedge rst_n)
       begin
        if(!rst_n)
         begin
            key_reg <= 3'b111;            //默認(rèn)沒按下狀態(tài)為高,按下之后為低.反之則為3'b000;
          end
        else 
          begin
            key_reg <= {key_reg[1:0],key_in};  
          end
        end
          
       assign HtoL_flag = key_en?(key_reg[2:1] == 2'b10):0;            //下降沿檢測,一個時鐘的高電平
       assign LtoH_flag = key_en?(key_reg[2:1] == 2'b01):0;               //上升沿檢測,一個時鐘的高電平  
      //---------------------------------------------
       reg           cnt_en;                 //計數(shù)使能標(biāo)志
       reg   [15:0]  cnt2; 
       always @(posedge clk or negedge rst_n)
       begin
        if(!rst_n)
         begin
            cnt2 <= 16'd0;
          end
        else if((cnt_en)&&(cnt2 == t1ms))
          begin
            cnt2 <= 16'd0;
          end
          else if(cnt_en)
          begin
            cnt2 <= cnt2 + 16'd1;
          end    
          else 
                cnt2 <= 16'd0;    
        end
          
      
       reg   [4:0]   cnt3; 
       always @(posedge clk or negedge rst_n)
       begin
        if(!rst_n)
         begin
             cnt3 <= 5'd0;
          end
        else if((cnt_en)&&(cnt2 == t1ms))
          begin
             if(cnt3 == t_20ms )
                cnt3 <= t_20ms;
             else
               cnt3 <= cnt3 + 1;                              
          end
          else if(!cnt_en)
             cnt3 <= 5'd0;        
        end
          
      //----------------------------------
      //按鍵狀態(tài)機(jī)
          reg  [2:0]  i;
          reg      key_down;        //按鍵按下標(biāo)志
          reg      key_up;          //按鍵釋放標(biāo)志  
          always @(posedge clk or negedge rst_n)
           begin
            if(!rst_n)
             begin
                      key_down <= 0;
                      key_up <= 0;
                      i <= 0;
                      cnt_en <= 0;
              end
            else 
              begin
                case(i)
                 'd0:
                     begin
                       key_down <= 0;
                       key_up <= 0;    
                       if(HtoL_flag) i <= 'd1;         //檢測到按下
                       else if(LtoH_flag) i <= 'd2;    //檢測到釋放按鍵
                       else  i  <= 'd0;
                      end
                     'd1:
                       begin
                         if(cnt3 == t_20ms )
                             begin
                              if(!key_in)                  //檢測到按鍵依然被按下
                                begin
                                   key_down <= 1;            //按鍵按下成功
                                   i <= 'd3;
                                   cnt_en <= 0;
                                 end
                                else
                                   begin
                                      key_down <= 0; 
                                      i <= 'd0;
                                      cnt_en <= 0;        
                                   end
                                end
                              else
                                cnt_en <= 1;
                             end
                      'd2:
                          begin
                             if(cnt3 == t_20ms )
                               begin
                                if(key_in)                  //檢測到按鍵被釋放
                                  begin
                                       key_up <= 1;             //按鍵釋放成功
                                       i <= 'd3;
                                       cnt_en <= 0;
                                     end
                                 else
                                   begin
                                       key_up <= 0;  
                                       i <= 'd0;
                                       cnt_en <= 0;        
                                     end
                                  end
                              else
                                cnt_en <= 1;
                             end
                     'd3:
                          begin
                            key_up <= 0;  
                            key_down <= 0;            
                            i <= 'd0;                             
                          end                    
                   default:i <= 'd0;    
                 endcase            
              end
            end
      
      //---------------------------
       reg          key_out;
       always @(posedge clk or negedge rst_n)
       begin
        if(!rst_n)
         begin
            key_out <= 1; 
          end
        else 
          begin
            if(key_down)
                 key_out <= 0;               //按下為低
            else  if(key_up)
                 key_out <= 1;              //釋放為高
            else
                 key_out <= key_out;         //否則保持
          end
        end
          
       assign   key_down_out = key_down;         //當(dāng)按鍵被按下有效時
       assign   key_up_out = key_up;         //當(dāng)按鍵被釋放后才有效時
       assign   key_in_out = key_out;
      endmodule
      復(fù)制代碼

       

       

       

      仿真:

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多