FPGA开发(九)----------按键消抖实验

        本次实验咱们主要完成按键消抖,并统计按下的次数,经过数码管进行显示。咱们在上一个数码管计数器的工做上实现按键消抖以后,将1hz信号改成消抖模块的输出便可。模块化

        首先咱们分析一下按键抖动,按键消抖一般的按键所用开关为机械弹性开关,当机械触点断开、闭合时,因为机械触点的弹性做用,一个按键开关在闭合时不会立刻稳定地接通,在断开时也不会一会儿断开。于是在闭合及断开的瞬间均伴随有一连串的抖动,按键抖动会引发一次按键被误读屡次。为了避免产生这种现象而做的措施就是按键消抖。抖动时间的长短由按键的机械特性决定,通常为5ms~10ms。相应的曲线图以下.net

                                                                    

        能够看到当抖动10ms以后按键值会趋于稳定,所以咱们的思路为若是自己高电平的按键,出现的持续20ms以上的低电平,那么说明此时的按键被按下,便可实现按键消抖的做用。3d

        能够获得按键消抖模块的输入为  按下的按键 输出为是按键是否按下,相应的咱们实现如下代码code

/*
	Author:Alawyssun
	Time:2020/03/26
	实现功能:按键消抖,经过检测有连续20ms以上的低电平实现
*/

module key_scan
(
	input clk,
	input rst,
	input key1,
	output reg button_out_reg
);
parameter N = 32 ; 
parameter FREQ = 50;  //时钟频率50MHz  50_000_000
parameter MAX_TIME = 20; //按键延时最大时间 20ms
localparam TIMER_MAX_VAL =   MAX_TIME * 1000 * FREQ;

reg count_flag;
reg[31:0] count_cnt;
always@(posedge clk)
begin
	if(rst==1'b0)
	begin
		button_out_reg<=0;
	end
	else
	begin
		if(key1==1'b0)
		begin
			if(count_flag==0)
			begin
				count_flag<=1;
			end
			else 
			begin
				if(count_cnt==TIMER_MAX_VAL)
				begin
					button_out_reg<=1;
				end
				else if(count_cnt>=TIMER_MAX_VAL+32'd1)
				begin
					button_out_reg<=0;
				end
			end
		end
		else
		begin
			count_flag<=0;
		end
	end
end


always@(posedge clk)
begin
	if(count_flag==1)
	begin
		count_cnt<=count_cnt+32'd1;
	end
	else if(count_flag==0)
	begin
		count_cnt<=32'd0;
	end
end
endmodule

              同时将主模块中的代码修改成以按键输出为输入频率信号便可。代码以下blog

/*
	Author:Alawyssun
	Time:2020/03/26
	实现功能:利用模块化的方法,实现六个数码管显示一个数字的功能
	该数字在按键消抖后的做用下,自动加一  同时将数字以前的0消去
*/
`timescale 1n/1ps
module seg_test(
	input clk,
	input rst,
	input key0,
	output [5:0] seg_pi,//片选
	output [7:0] seg_data//数据位
);
reg[31:0] time_cnt;
reg one_hz;

parameter CLK_FREQ = 50_000_000; //时钟频率
parameter CNT_SECOND = 1;     //计数器加一须要的时间 好比1秒 就写10  0.5秒就写5
parameter CNT_NUMBER = CNT_SECOND*CLK_FREQ;     //计数器加一须要的时间


/*
always@(posedge clk or negedge rst)
begin
	if(rst==1'b0)
	begin
		time_cnt<=32'd0;
	end
	else 
	begin
		if(time_cnt==32'd49_999_999)
		begin
			time_cnt<=32'd0;
			one_hz<=1'b1;
		end
		else
		begin
			time_cnt<=time_cnt+32'd1;	
			one_hz<=1'b0;
		end
	end
end
*/
key_scan key_scan_my(
	.clk (clk),
	.rst (rst),
	.key1 (key0),
	.button_out_reg(one_hz)
);



wire[3:0] count0;
wire t0;
wire[7:0] seg_data_0;
wire zero_my0,zero_my1,zero_my2,zero_my3,zero_my4,zero_my5;
num_cnt num_cnt0_my(
	 .rst  (rst),
    .clk    (clk),
    .en     (one_hz),
	 .zero_en1 (zero_my1),
	 .zero_en2 (zero_my0),
	 .pulse      (t0),
    .data   (count0)    
 );
num_show num_show0_my(
	.data (count0),
	.zero_en(1),//第一个数码管的0  不管如何须要显示
	.seg_data (seg_data_0)
);
 
wire[3:0] count1;
wire t1;
wire[7:0] seg_data_1;
num_cnt num_cnt1_my(
	 .rst  (rst),
    .clk    (clk),
    .en     (t0),
	 .zero_en1 (zero_my2),
	 .zero_en2 (zero_my1),
	 .pulse      (t1),
    .data   (count1)    
 );
num_show num_show1_my(
	.data (count1),
	.zero_en(zero_my1),
	.seg_data (seg_data_1)
);
 
wire[3:0] count2;
wire[7:0] seg_data_2;
wire t2;
num_cnt num_cnt2_my(
	 .rst  (rst),
    .clk    (clk),
    .en     (t1),
	 .zero_en1 (zero_my3),
	 .zero_en2 (zero_my2),
	 .pulse      (t2),
    .data   (count2)    
 );
num_show num_show2_my(
	.data (count2),
	.zero_en(zero_my2),
	.seg_data (seg_data_2)
);
 
wire[3:0] count3;
wire[7:0] seg_data_3;
wire t3;
num_cnt num_cnt3_my(
	 .rst  (rst),
    .clk    (clk),
    .en     (t2),
	 .zero_en1 (zero_my4),
	 .zero_en2 (zero_my3),
	 .pulse      (t3),
    .data   (count3)    
 );
num_show num_show3_my(
	.data (count3),
	.zero_en(zero_my3),
	.seg_data (seg_data_3)
);
 
wire[7:0] seg_data_4;
wire[3:0] count4;
wire t4;
num_cnt num_cnt4_my(
	 .rst  (rst),
    .clk    (clk),
    .en     (t3),
	 .zero_en1 (zero_my5),
	 .zero_en2 (zero_my4),
	 .pulse      (t4),
    .data   (count4)    
 );
num_show num_show4_my(
	.data (count4),
	.zero_en(zero_my4),
	.seg_data (seg_data_4)
);
 
wire[7:0] seg_data_5;
wire[3:0] count5;
wire t5;
num_cnt num_cnt5_my(
	 .rst  (rst),
    .clk    (clk),
    .en     (t4),
	 .zero_en1 (0),
	 .zero_en2 (zero_my5),
	 .pulse      (t5),
    .data   (count5)    
 );
num_show num_show5_my(
	.data (count5),
	.zero_en(zero_my5),
	.seg_data (seg_data_5)
);

num_scan num_scan_my(
	.clk (clk),
	.rst (rst),
	.seg_data_scan_0 (seg_data_0),
	.seg_data_scan_1 (seg_data_1),
	.seg_data_scan_2 (seg_data_2),
	.seg_data_scan_3 (seg_data_3),
	.seg_data_scan_4 (seg_data_4),
	.seg_data_scan_5 (seg_data_5),
	.seg_data_scan (seg_data),
	.seg_sel (seg_pi)
);
endmodule

     本实验的最终运行效果以下:能够看到按下一次按键,数码管加一。get

        咱们将延时时间改为1ms,能够看到按下一次按键数码管会一次增长好多数 ,可见咱们本次的实验实现了按键的消抖。input

        本次实验的工程文件下载地址:https://download.csdn.net/download/qq_34020487/12271838test