按键消抖+点亮led灯

本文详细介绍了按键消抖的原理和解决方案,通过实验展示了在LED控制中如何使用按键消抖模块,避免因按键抖动造成误操作。通过延迟采样和信号平稳后采样两种方法实现消抖,并提供了相应的Verilog代码实现。项目仿真验证了消抖模块的有效性,确保了LED灯控制的稳定性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

  本课程是按键消抖的一个扩展内容,主要是通过实验观察按键消抖和不消抖的一个区别。


一、按键消抖

  按键抖动:按键抖动通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动。当按下一次按键,可能在A点检测到一次低电平,在B点检测到一次高电平,在C点又检测到一次低电平。同时抖动是随机,不可测的。那么按下一次按键,抖动可能会误以为按下多次按键。

1.按键消抖目的:消除按键抖动对我们程序的影响。

真实按键

图1. 按键特写
2. 按键消抖解决方案1:延迟采样。

延迟采样1

图2. 延迟采样

3. 按键消抖解决方案2:信号变化频率平稳后并且持续20ms则采样。

延迟采样2

图3. 信号平稳后采样

二、任务描述

  使用按键控制开发板上一个led灯的亮灭,当按键按下的时候led灯就亮,当再一次按下按键的时候led就不亮了。由于按键存在抖动,按键松开的时候led灯就不亮,所以需要一个消抖模块对按键消抖。通过实验来观察消抖和不消抖的一个区别。


三、系统框图

在这里插入图片描述

图4. 系统框图

四、模块描述

在这里插入图片描述

图5. 模块关系示意图

五、模块代码

  1. 创建single_led文件,编写single_led模块代码
module single_led(
	input 	clk      ,//开发板晶振频率50MHz
	input 	rst_n    ,//复位下降沿有效
	input 	flag     ,//消抖完成标志
	input 	key_value,//稳定按键信号
	
	output 	reg	led //led灯
);

//计时器模块
always@(negedge rst_n or posedge clk)begin
	if(!rst_n)begin
		led <= 1'b0;//初始化led灯,高电平有效
	end
	else if(flag && ~key_value)begin
		led <= ~led;//稳定电平对led取反
	end 
	else begin
		led <= led;//其他时刻,led等于其自身
	end
end
endmodule  
  1. 创建key_debounce文件,编写key_debounce模块代码
module key_debounce(
	input 	wire 	clk  ,//时钟50MHz
	input 	wire 	rst_n,//复位信号,下降沿有效
	input 	wire 	key  ,//按键
	
	output 	reg 	flag ,//消抖完成标志,0表示还在抖动,1表示抖动结束
	output 	reg 	key_value//消抖完的有效电平
);
parameter 		DELAY = 20'd1000_000;//20ms	
reg 	[19:0]	delay_cnt		    ;//延迟计数器
reg 			key_reg 		    ;//中间按键寄存器,存放当前按键信号,用于和下次按键信号做比较

//延迟计数器模块
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin//按键复位
		delay_cnt <= 20'd0;//初始延迟计数器默认为0
		key_reg <= 1'b1;//初始中间按键寄存器为高电平,按键高电平无效
	end 
	else begin
		key_reg <= key;
		if(key_reg ==1 && key == 0)begin//如果抖动
			delay_cnt <= DELAY;//开始设置延迟计数器初值
		end 
		else begin//没有抖动
			if(delay_cnt > 20'd0)begin//如果延迟计数器大于0
				delay_cnt <= delay_cnt - 20'd1;//开始倒数计时
			end 
			else begin
				delay_cnt <= 20'd0;//如果延迟计数器小于等于0,延迟计数器清0
			end 
		end 
	
	end 
	
end 

//根据延迟计数器获取状态以及稳定的按键信号
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin//复位信号
		flag <= 1'b0;//抖动标志,初始为抖动
		key_value <= 1'b1;//记录按键稳定信号
	end 
	else if(delay_cnt == 1'd1)begin//计数从0包括999_999一共1_000_000个数
		flag <= 1'b1;//条件满足,改变抖动标志
		key_value <= key;//key_value将稳定信号输出
	end 
	else begin
		flag <= 1'b0;//计数器没有记满1_000_000个数,始终为抖动
		key_value <= key_value;//key_value保持不变
	end 
end 
endmodule 
  1. 新建top_key_led文件,编写top_key_led模块代码
module top_key_led(
	input   wire 	clk  ,//时钟50MHz
	input 	wire 	rst_n,//复位信号,下降沿有效
	input 	wire 	key  ,//按键信号
	
	output  wire 	led//led灯信号
);
parameter DELAY = 20'd1_000_000;
wire 	flag	 ;
wire 	key_value;

key_debounce#(.DELAY (DELAY)) 	u_key_debounce(//实例化按键消抖模块
.clk  		(clk)  ,//时钟信号
.rst_n		(rst_n),//复位信号
.key		(key)  ,//按键信号
            
.flag 		(flag) ,//消抖信号
.key_value	(key_value)//按键稳定信号
);	

single_led	u_single_led(//实例化led控制模块
.clk  		(clk )     ,//时钟信号
.rst_n		(rst_n)    ,//复位信号
.flag 		(flag)     ,//消抖信号
.key_value	(key_value),//按键稳定信号

.led			(led)//led灯信号
);
 	
endmodule 

六、项目仿真

  1. 编写top_key_led_tb.v文件,进行仿真
`timescale 1ns/1ns//单位/精度
module top_key_led_tb();
parameter CYCLE = 20;
parameter DELAY = 4'd10;//倒计时10x20=200ns

reg clk  ;//时钟
reg rst_n;//复位信号
reg key  ;//按键信号

wire led;//led信号

always#(CYCLE/2) clk = ~clk;//模拟时钟信号,周期20ns

initial begin
   clk = 1'b0  		 ;//时钟低电平
   rst_n = 1'b0		 ;//复位信号低电平
   #(CYCLE)    		 ;//延迟20ns
   rst_n = 1'b1		 ;//复位信号拉高
   key = 1'b1  		 ;//按键高电平,未按下
   #(CYCLE)    		 ;//延迟20ns
   key = 1'b0  		 ;//按键按下
   #(CYCLE)    		 ;//延迟20ns
   key = 1'b1  		 ;//按键高电平,未按下
   #(CYCLE)          ;//延迟20ns
   key = 1'b0        ;//按键按下
   #(CYCLE)          ;//延迟20ns
   key = 1'b1        ;//按键高电平,未按下
   #(CYCLE)          ;//延迟20ns
   key = 1'b0        ;//按键按下
   #(CYCLE*DELAY*4);//延迟超过倒计时时间,观察led信号
   $stop             ;//停止
end 

//实例化顶层模块
top_key_led#(.DELAY (DELAY)) u_top_key_led(
.clk	(clk	),
.rst_n  (rst_n)  ,
.key	(key	),
   	 		
.led	(led	)
);

endmodule 
  1. 仿真结果

在这里插入图片描述

图6. 仿真结果

七、管脚信息

在这里插入图片描述

图7. pin planner
元件管脚
LED0G15
LED1F16
LED2F15
LED3D16
KEY0E15
KEY1E16
KEY2M16
KEY3M15
COLOCK(时钟)E1
表1. 管脚信息表

八、运行效果


按键控制led+按键消抖

总结

  消抖前的按键控制led和消抖后的按键控制led,效果是不一样的。按键的物理特性导致按键存在抖动,我们不能改变按键的物理特性,但是可以通过代码,来消除按键抖动带来的负面影响。下期课程——按键控制蜂鸣器,将加入同样的按键消抖模块,使用消抖的按键控制蜂鸣器鸣叫。敬请期待!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值