当前位置: 首页 > news >正文

建设部网站四库一平台百度网站网址是多少

建设部网站四库一平台,百度网站网址是多少,微网站设置,瑶海区网站建设文章目录 一、按键消抖简介1.1、为什么要按键消抖 二、C4开发板原理图三、按键消抖源码3.1、方案一(每当检测到下降沿便开始重新计数)3.2、方案二(检测到第一次下降沿后便开始计数) 四、仿真代码及仿真波形图五、拓展:…

文章目录

  • 一、按键消抖简介
    • 1.1、为什么要按键消抖
  • 二、C4开发板原理图
  • 三、按键消抖源码
    • 3.1、方案一(每当检测到下降沿便开始重新计数)
    • 3.2、方案二(检测到第一次下降沿后便开始计数)
  • 四、仿真代码及仿真波形图
  • 五、拓展:按键消抖版按键控制LED状态

一、按键消抖简介

1.1、为什么要按键消抖

生活中常用的按键为机械按键,而机械按键在按下后就会产生按键抖动

按键抖动:按键抖动通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动。当按下一次按键,可能在A点检测到一次低电平,在B点检测到一次高电平,在C点又检测到一次低电平。同时抖动是随机,不可测的。那么按下一次按键,抖动可能会误以为按下多次按键。
在这里插入图片描述
一般我们认为抖动存在时间保持在5-10ms左右,而在5-10ms后才会保持稳定,
因此我们很容易意识到可以通过延时采样稳定的按键信号进行消抖。而本次设计中博主在消抖后输出的是一个脉冲信号

本文博主提出两种按键消抖的解决方案:

  • 第一种:每当检测到下降沿便开始重复进行20ms计数
  • 第二种:检测到第一次下降沿后,进行一次并只进行这一次20ms计数

第一种方案为博主自行编写,代码略显繁琐。第二种方案为博主老师的方法,较容易理解(但博主认为从第一次下降沿开始便检测有些许不太严谨),大家可以依据自己的喜好进行选择。

二、C4开发板原理图

在这里插入图片描述
由原理图可以看出,博主的开发板按键按下后低电平有效,博主接下来提供的代码请各位根据自己实际的开发板进行适当的修改

三、按键消抖源码

3.1、方案一(每当检测到下降沿便开始重新计数)

源码分析:

  • 在方案一中,博主设计了key_r0、key_r1、key_r2三个中间寄存器,分别用于同步按键信号key_in并进行打两拍。大家可以认为同步打拍就是在时序电路中,分别将前一个信号的值寄存下来,第一次为同步,后续即为打拍(这里打一拍还是打两拍取决于各位,甚至只同步不打拍也可以进行下降沿检测)。

  • 由于是在时序电路中进行非阻塞赋值,因此三个中间信号分别相差了一个时钟周期,而博主就是利用后两个信号进行下降沿检测,具体如图:
    在这里插入图片描述
    由波形图可以看出,我们可以通过key_r1取反逻辑与上key_r2的运算,检测出下降沿就,即:assign nedge = ~key_r1 && key_r2

  • 在本方案中,博主设计的20ms计数器在不断的计数,但是通过前面的分析我们得知,要想按键消抖,应该在检测到下降沿的时候才开始计数,因此博主在计时器中添加了检测nedge的条件,一旦检测到nedge就会自动将进行计数器清零,以此确保计数器检测到下降沿后是从0开始计数。

  • 但大家又会想到,按键按下的时间如果远远大于20ms,计数器就会不止一次地计数到20ms,而我们也将采样多次,前文博主说道要求输出脉冲信号,因此在按键按下的低电平持续时间内会产生多个脉冲信号,并不符合要求。对此博主的解决方案是:在计数器计数到最大值-1(代码中是MAX - 2 因为计数是从0开始)时便输出脉冲信号,而一旦计数器计数到最大值(MAX - 1)便将cnt保持在最大值,从而避免产生多个脉冲。(最大值-1与最大值只相差一个时钟周期20ns,因此影响可以忽略不计)。

  • 同时注意在一切条件都满足后,输出的key_out的值不应该置1。如果只是单纯置1,假设抖动后按键仍保持在高电平,或者松开按键时产生的释放抖动也会输出一个脉冲信号,很明显在这两种情况下是不成立的,因此key_out的值应该赋为key_in(或者三个中间信号均可)并取反(按键低电平有效需要取反),并且在一个时钟周期后置0(初始值为0)才是输出脉冲信号。

  • 本方案每当检测到下降沿便会重新开始20ms计数

module key_filter(input       wire    clk     ,input       wire    rst_n   ,input       wire    key_in  ,//按键输入信号output      reg     key_out  //输出稳定的脉冲信号
);parameter MAX = 20'd1_000_000;reg     [19:0]  cnt_delay       ; //20ms延时计数寄存器
wire            add_cnt_delay   ; //开始计数的标志
wire            end_cnt_delay   ; //结束计数的标志reg             key_r0          ; //同步
reg             key_r1          ; //打一拍
reg             key_r2          ; //打两拍wire            nedge           ; //下降沿寄存器//同步打拍
always @(posedge clk or negedge rst_n) beginif(!rst_n)beginkey_r0 <= 1'b1;key_r1 <= 1'b1;key_r2 <= 1'b1;endelse beginkey_r0 <= key_in; //同步key_r1 <= key_r0; //寄存一拍key_r2 <= key_r1; //寄存两拍end
end//20ms计数器
always @(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_delay <= 1'b0;endelse if(add_cnt_delay )beginif(nedge)begin //检测到下降沿从0开始计数cnt_delay <= 1'b0;endelse if(cnt_delay == MAX - 1'b1)begincnt_delay <= cnt_delay; //计数计满结束后保持,避免产生多个输出脉冲endelse begincnt_delay <= cnt_delay + 1'b1;endendelse begincnt_delay <= 1'b0;end
endassign nedge = ~key_r1 && key_r2; //下降沿检测
assign add_cnt_delay = 1'b1; 
assign end_cnt_delay = add_cnt_delay && cnt_delay == MAX - 1'b1;//key_out脉冲信号赋值
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginkey_out <= 1'b0;endelse if(cnt_delay == MAX - 2'd2)begin //计数到最大值减1时产生按键脉冲key_out <= ~key_in;//不可直接置为1!!!!!!!!!endelse beginkey_out <= 1'b0;end
endendmodule

3.2、方案二(检测到第一次下降沿后便开始计数)

源码分析:

  • 原理与第一种方案类似,但是此方案引入了中间变量flag,初始值为0,检测到下降沿后便将flag置为1,此时再将flag作为开始计数的条件,同时计满20ms后再将flag置为0,也就省去了在最大值-1时赋值key_out并保持计数器最大值的繁琐。
  • 此方法与方案一的区别就在于,方案一相当于是在抖动过程中最后一次下降沿才开始计数,而此方案是在抖动过程中的第一次下降沿便开始计数。
/**************************************功能介绍***********************************
Date	: 2023-07-26 14:43:33
Author	: majiko
Version	: 1.0
Description: 按键消抖模块(1位按键)
*********************************************************************************///---------<模块及端口声名>------------------------------------------------------
module key_filter( input				clk		,input				rst_n	,input				key_in  ,output  reg         key_down //输出脉冲信号(按键按下1次) 
);								 
//---------<参数定义>--------------------------------------------------------- parameter TIME_20MS = 1000_000;//20ms//---------<内部信号定义>-----------------------------------------------------reg                 key_r0          ;//同步reg                 key_r1          ;//打两拍reg                 key_r2          ;wire                n_edge          ;//下降沿reg                 flag            ;//计数器计数的标志信号(按键按下抖动标志)reg			[19:0]	cnt_20ms	   	;//20ms计数器wire				add_cnt_20ms	;wire				end_cnt_20ms	;//****************************************************************
//--同步打拍
//****************************************************************//同步,将key_in信号,同步到clk时钟域下面always @(posedge clk or negedge rst_n)begin if(!rst_n)beginkey_r0 <= 1'b1;end else begin key_r0 <= key_in;end end//打两拍always @(posedge clk or negedge rst_n)begin if(!rst_n)beginkey_r1 <= 1'b1;key_r2 <= 1'b1;end else begin key_r1 <= key_r0;key_r2 <= key_r1;end end//****************************************************************
//--n_edge 
//****************************************************************assign n_edge = ~key_r1 & key_r2;//下降沿检测// assign p_edge = key_r1 & ~key_r2;//上升沿检测//****************************************************************
//--cnt_20ms
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_20ms <= 'd0;end else if(add_cnt_20ms)begin if(end_cnt_20ms)begin cnt_20ms <= 'd0;endelse begin cnt_20ms <= cnt_20ms + 1'b1;end endend assign add_cnt_20ms = flag;assign end_cnt_20ms = add_cnt_20ms && cnt_20ms == TIME_20MS - 1;//****************************************************************
//--flag
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)beginflag <= 'd0;end else if(n_edge)begin flag <= 1'b1;end else if(end_cnt_20ms)beginflag <= 1'b0;endend//****************************************************************
//--key_down
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)beginkey_down <= 1'd0;end else if(end_cnt_20ms)begin key_down <= ~key_in;end else begin key_down <= 1'b0;end endendmodule

四、仿真代码及仿真波形图

本次仿真较为随意,只是为了展示逻辑功能

源码:

`timescale 1ns/1ns
module tb_key_filter();reg    clk     ;
reg    rst_n   ;
reg    key_in  ;wire    key_out; parameter CYCLE = 20;
always #(CYCLE / 2) clk = ~clk;initial beginclk = 1'b0;rst_n = 1'b1;key_in = 1'b1;#20rst_n = 1'b0;#20rst_n = 1'b1;#60key_in = 1'b0;#(30*CYCLE);$stop;
endkey_filter#(.MAX(10)) u_key_filter(.clk    (clk    ) ,.rst_n  (rst_n  ) ,.key_in (key_in ) ,.key_out(key_out)  
);endmodule

仿真波形图:
在这里插入图片描述

可以看出,成功输出了一次脉冲信号key_out

五、拓展:按键消抖版按键控制LED状态

按键消抖模块:

module key_filter(input       wire            clk     ,input       wire            rst_n   ,input       wire  [3:0]     key_in  ,//按键输入信号output      reg   [3:0]     key_out  //输出稳定的脉冲信号
);parameter MAX = 20'd1_000_000;reg     [19:0]          cnt_delay       ; //20ms延时计数寄存器
wire                    add_cnt_delay   ; //开始计数的标志
wire                    end_cnt_delay   ; //结束计数的标志reg     [3:0]           key_r0          ; //同步
reg     [3:0]           key_r1          ; //打一拍
reg     [3:0]           key_r2          ; //打两拍wire                    nedge           ; //下降沿寄存器//同步打拍
always @(posedge clk or negedge rst_n) beginif(!rst_n)beginkey_r0 <= 4'b1111;key_r1 <= 4'b1111;key_r2 <= 4'b1111;endelse beginkey_r0 <= key_in; //同步key_r1 <= key_r0; //寄存一拍key_r2 <= key_r1; //寄存两拍end
end//20ms计数器
always @(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_delay <= 1'b0;endelse if(add_cnt_delay )beginif(nedge)begin //检测到下降沿从0开始计数cnt_delay <= 1'b0;endelse if(cnt_delay == MAX - 1'b1)begincnt_delay <= cnt_delay; //计数计满结束后保持,避免产生多个输出脉冲endelse begincnt_delay <= cnt_delay + 1'b1;endendelse begincnt_delay <= 1'b0;end
endassign nedge = (~key_r1[0] && key_r2[0]) || (~key_r1[1] && key_r2[1]) || (~key_r1[2] && key_r2[2]) || (~key_r1[3] && key_r2[3]); //下降沿检测
assign add_cnt_delay = 1'b1; 
assign end_cnt_delay = add_cnt_delay && cnt_delay == MAX - 1'b1;//key_out脉冲信号赋值
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginkey_out <= 4'b0000;endelse if(cnt_delay == MAX - 2'd2)begin //计数到最大值减1时产生按键脉冲key_out <= ~key_in;endelse beginkey_out <= 4'b0000;end
endendmodule

LED控制模块:

module led (input   wire                clk     ,input   wire                rst_n   ,input   wire    [3:0]       key_in  ,output  reg     [3:0]       led
);parameter MAX = 15_000_000 ;
reg     [25:0]      cnt ;
reg     [3:0]       flag;always @(posedge clk or negedge rst_n) beginif(!rst_n)begincnt <= 1'b0;endelse if(cnt == MAX - 1'b1)begincnt <= 1'b0;endelse begincnt <= cnt + 1'b1;end
endreg [2:0]   state   ;always @(posedge clk or negedge rst_n)beginif(!rst_n)beginstate <= 1'b0;endelse if(cnt == MAX - 1'b1)beginstate <= state + 1'b1;endelse beginstate <= state;end
endalways@(posedge clk or negedge rst_n)beginif(!rst_n)beginflag <= 4'b0000;endelse if(key_in[0] == 1'b1)beginflag <= 4'b0001;endelse if(key_in[1] == 1'b1)beginflag <= 4'b0010;endelse if(key_in[2] == 1'b1)beginflag <= 4'b0100;endelse if(key_in[3] == 1'b1)beginflag <= 4'b1000;endelse beginflag <= flag;end
endalways @(posedge clk or negedge rst_n) beginif(!rst_n)beginled <= 4'b0001;endelse if(flag == 4'b0001)begincase(state)3'd0 : led <= 4'b0000;3'd1 : led <= 4'b0001;3'd2 : led <= 4'b0011;3'd3 : led <= 4'b0111;3'd4 : led <= 4'b1111;3'd5 : led <= 4'b0111;3'd6 : led <= 4'b0011;3'd7 : led <= 4'b0001;default:;endcaseendelse if(flag == 4'b0010 && cnt == MAX - 1'b1)beginled <= {led[2:0],led[3]};endelse if(flag == 4'b0100 && cnt == MAX - 1'b1)beginled <= {led[2:0],~led[3]};endelse if(flag == 4'b1000 && cnt == MAX - 1'b1)beginled <= 4'b1111;end
endendmodule

顶层模块:

module top_key_led(input   wire                clk     ,input   wire                rst_n   ,input   wire    [3:0]       key_in  ,output  wire    [3:0]       led
);wire [3:0]      key_out;key_filter u_key_filter(.clk     (clk   ),.rst_n   (rst_n ),.key_in  (key_in),.key_out (key_out) 
);led u_led(.clk     (clk    ),.rst_n   (rst_n  ),.key_in  (key_out),.led     (led    ) 
);endmodule

注意:led模块有一点问题,在key0跑马灯开始后再按下key1,key2时,呈现效果也许不是流水灯,因为跑马灯开始后led状态不再是4’b0001

六、参考资料
https://blog.csdn.net/weixin_43828944/article/details/122360794

http://www.khdw.cn/news/3317.html

相关文章:

  • 做智能网站系统下载seo网站首页推广
  • 用dw做php网站搜索引擎广告优化
  • 武汉做网站找谁站优云网络公司
  • 毕业设计代做网站价格怎么做网站优化排名
  • 武汉建设网站的公司哪家好做网站找哪个公司好
  • 网站制作相关知识百度指数关键词
  • 网站设计制作要多少钱百度排行榜
  • 专业网站建设技术百度收录规则
  • 这么做钓鱼网站app软件开发
  • 试用型网站搜索引擎广告图片
  • 企业网站seo优化怎么做软文营销写作技巧
  • 梵克雅宝四叶草项链专柜价格图片什么是网站seo
  • 深圳市珠宝网站建设学生个人网页设计作品
  • 惠州网站建设公司曾信息互联网推广
  • 做兼职的设计网站有哪些工作内容百度指数pc版
  • 小工程承包网appwin10优化大师官网
  • 自己做网站 搜索功能开发全国人大常委会委员长
  • 网站群cmsb站推广网站入口2023的推广形式
  • 网站做二级域名干什么用十大成功营销策划案例
  • 公司做网站怎么构思购买域名的网站
  • discuz注册昆山seo网站优化软件
  • 如何做百度网站推广郑州seo外包服务
  • 腾讯云建网站网站seo顾问
  • 申请付费网站如何进行搜索引擎优化 简答案
  • 百度站长对网站会有影响吗互联网营销师
  • 巢湖自助建站系统企业网站建设方案模板
  • 网站首页的概念长春网站建设定制
  • 兰州做网站的外包公司软件开发
  • 美国机房网站最近国际新闻
  • 网站 开发 合同万网注册域名查询