这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 关于按键消抖的再认识

共4条 1/1 1 跳转至

关于按键消抖的再认识

助工
2014-10-28 21:19:34     打赏

由于最近论坛课程安排时间比较久,就去看了一些FPGA大神们的文章,最近看了一位大神的关于按键消抖的文章,很受益,就自己写了个工程来加深对按键消抖的理解,由于代码比较简单就没有写testbench,如有谬误,恭请指正。

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: Charles Wang 
// 
// Create Date:    10/27/2014 
// Design Name: 	keyinput
// Module Name:   keyinput
// Project Name: 	keyinput
// Target Devices: EP4CE6E22C8
// Tool versions: Quartus II 12.0
// Description: 根据按键的单击与长击,分别点亮一个Led
//              
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//			
//////////////////////////////////////////////////////////////////////////////////
module keyinput(key,sys_clk,sys_rst_n,led);

input key;//按键输入
input sys_clk;//
input sys_rst_n;//异步复位,低电平有效

output [1:0]led;//LED 输出驱动

reg [27:0]cnt;
reg rst_n_r1;
reg rst_n_r2;
reg P1,P2;

wire isH2L;
wire isL2H;
parameter T50MS= 28'd2_500_000,
			 T5S   = 28'd250_000_000;
//////////////////////////////////////////////////////////////////////////////////
//将sys_rst_n 同步化
always@(posedge sys_clk)
	begin
		{rst_n_r2,rst_n_r1} <= {rst_n_r1,sys_rst_n};
	end
//////////////////////////////////////////////////////////////////////////////////
//用P2,P1分别保存第一和第二个时钟的按键值
always@(posedge sys_clk or negedge rst_n_r2)
	begin
		if(!rst_n_r2)
			begin
				{P2,P1} <= 2'b11;
			end
		else	
			begin
				{P2,P1} <= {P1,key};
			end
	end
assign isH2L = (P2 == 1'b1) && (P1 == 1'b0);
assign isL2H = (P2 == 1'b0) && (P1 == 1'b1);
				
reg [3:0]i;
reg isLClick;//用isLClick 作为长按标志,isSClick 作为单击
reg isSClick;
reg [1:0]flag;
//////////////////////////////////////////////////////////////////////////////////
always@(posedge sys_clk or negedge rst_n_r2)
	begin
		if(!rst_n_r2)
			begin
				i 			<= 4'd0;
				isLClick <= 1'b0;
				isSClick <= 1'b0;
				flag 		<= 2'd0;
				cnt		<= 28'd0;
			end
		else
			case(i)
				4'd0: //等待按键按下
					if(isH2L)
						begin
							i <= i + 1'b1;
						end
				4'd1://按下后消抖
					if(cnt == T50MS - 1'b1)
						begin
							cnt <= 28'd0;
							i	 <= i + 1'b1;
						end
					else
						cnt <= cnt + 1'b1;
				4'd2://判断是否是长按
					if({P2,P1} == 2'b00 && cnt >= T5S - 1'b1)
						begin
							cnt  <= 28'd0;
							i 	  <= i + 1'b1;
							flag <= 2'd1;
						end
					else if(isL2H)
						begin	
							cnt 	<= 28'd0;
							i		<= i + 1'b1;
							flag <= 2'd2;
						end
					else
						cnt <= cnt + 1'b1;
				4'd3://步骤3和4是为了产生一组高脉冲isLClick,isSClick
					if(flag == 2'd1)
						begin	
							isLClick <= 1'b1;
							i 			<= i + 1'b1;
						end
					else if(flag == 2'd2)
						begin
							isSClick	<= 1'b1;
							i 			<= i + 1'b1;
						end
				4'd4:
					begin	
						isLClick <= 1'b0;
						isSClick	<= 1'b0;
						i 			<= i + 1'b1;
					end
				4'd5://等待按键释放
					if(isL2H)
						begin
						i <= i + 'b1;
						end
				4'd6://释放后消抖
					if(cnt == T50MS - 1'b1)
						begin	
							cnt <= 28'd0;
							i	 <= 4'd0;
							flag<= 2'd0;
						end
					else
						cnt <= cnt + 1'b1;
				default: i <= 4'd0;
			endcase
end
//////////////////////////////////////////////////////////////////////////////////
//让led2,led1 根据isLClick,isSClick高脉冲不停的反转
reg led1,led2;
always@(posedge sys_clk or negedge rst_n_r2)
	begin	
		if(!rst_n_r2)
			begin
				{led2,led1} <= 2'b11;
			end
		else if(isSClick)
			begin
				led1 <= ~led1;
			end
		else if(isLClick)
			begin
				led2 <= ~led2;
			end
	end
assign led = {led2,led1};//使用led1,led2驱动led
endmodule
				

 现象如下链接:

http://v.youku.com/v_show/id_XODEyODcxOTEy.html







关键词: 关于     按键     消抖     认识    

院士
2014-10-29 13:19:25     打赏
2楼

菜鸟
2015-12-30 17:01:35     打赏
3楼
把按键这个动作用状态机来写,很有趣

高工
2016-01-21 09:19:19     打赏
4楼

学习下              


共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]