FPGA实验二:拨动开关的消抖电路的设计
按键消抖的原理和基于fpga的消抖设计
按键消抖1功能概述按键开关是各种电子设备不可或缺的人机接口,如电脑的键盘等。
实际应用中,按键开关通常为机械式弹性开关。
当机械点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定接通,断开时也不会马上断开,在闭合和断开的瞬间均伴随有一连串的抖动。
为保证系统及时正确识别,必须对这种情况作出相应处理。
我们称之为按键消抖。
按键消抖可分为硬件消抖和软件消抖。
硬件消抖的原理是在信号输入系统之前消除抖动干扰,在按键较少的情况下比较适宜。
如果按键较多,则使用软件消抖。
软件消抖的实质在于降低键盘输入端口的采样频率,将高频抖动略去。
需要注意的是,软件消抖需要占据一定的系统资源。
尽管硬件消抖和软件消抖能实现按键消抖功能,串行处理的方式都存在一定的局限性,显得不那么完美。
而硬件资源丰富的FPGA系统采用并行处理的模式,利用硬件来减轻软件工作量,通过硬件加速软件消抖处理,即可做到软件消抖并行化,因而在按键消抖处理方面具备非常明显的优势。
优秀的设计程序应该是用最简单的代码(架构、信号)实现功能。
在本例中,我们的只需要用4个信号界定,并用很短的代码即可。
下面我们先来看看功能要求:在系统设计中,消除按键抖动的方法五花八门,无论是硬件电路和软件设计都十分成熟。
在本项目中,我们将用Verilog语言给出具体实现过程,设计一个程序来检查键值,有效滤除按键抖动区间20 ms的毛刺脉冲。
2 设计思路一般按键所用开关为机械弹性开关,由于机械触点的弹性作用,每个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。
因而在闭合及断开的瞬间均伴随有一连串的抖动,如下图。
抖动时间的长短由按键的机械特性决定,一般为5 ms~10 ms。
1图1 按键抖动过程示意当系统检测出按键闭合后,执行一个延时程序,产生5ms~10ms的延时;前沿抖动消失后,再一次检测键的状态;如果仍保持闭合状态电平,则确认为真正有键按下。
当检测到按键释放后,也要给5ms~10ms的延时,待后沿抖动消失后才能转入该键的处理程序。
FPGA按键去抖程序
FPGA按键去抖程序代码是特权同学的,我将其理解后加上了注释。
去抖的原理和单片机是一样的,即通过延时来过滤掉按键抖动产生的毛刺信号。
不同的是判断按键按下的条件不同,单片机通常是已知按键不按时IO口的电平(如高电平),当IO口电平发生改变时(如低电平),则开启定时器进行延时,延时20ms后再次读取IO口的电平,若仍为低电平,则说明有按键按下;若为高电平,则说明是按键抖动,没有按键按下。
FPGA的采样频率很高,它可以在每个时钟周期的上升沿到来时对IO口的电平进行一次读取。
通过读取相邻2个时钟周期内IO口的电平值并进行比较,若电平值发生改变(此代码中是判断电平从0变为1),则计数器清零,若持续20ms后电平值没有发生改变,则读取按键的键值,同时将这一键值存储起来,当下一个20ms后再次读取键值,将2次键值进行比较,若键值发生改变,则说明按键有动作(要么按下,要么松手)。
此代码中是判断键值从0变为1,即松手检测。
// 按键去抖// 实现一个简单的三个按键分别控制三个发光二极管亮或暗的控制。
// 例如,按键1控制发光二极管1。
上电初始发光二极管1不亮,// 当检测到按键1被按下后,发光二极管1则点亮,// 按键1再次被按下时,发光二极管1则不亮,如此反复。
// 该实验需要把握好按键消抖检测的设计技巧。
// 注:此代码的按键操作是包括松手检测的,// 即按键按下后要等到松手才算一次按键操作module key_debounce(clk,rst_n,key1_n,key2_n,key3_n,led1_n,led2_n,led3_n);input clk;input rst_n;input key1_n,key2_n,key3_n;output led1_n,led2_n,led3_n;reg [2:0] key_rst;always @(posedge clk or negedge rst_n)beginif(!rst_n)key_rst <= 3'b111;elsekey_rst <= {key3_n,key2_n,key1_n}; // 读取当前时刻的按键值endreg [2:0] key_rst_r;always @(posedge clk or negedge rst_n)beginif(!rst_n)key_rst_r <= 3'b111;elsekey_rst_r <= key_rst; // 将上一时刻的按键值进行存储endwire [2:0]key_an = key_rst_r & (~key_rst); // 当键值从0到1时key_an改变//wire [2:0]key_an = key_rst_r ^ key_rst; // 注:也可以这样写reg [19:0] cnt; // 延时用计数器always @(posedge clk or negedge rst_n)beginif(!rst_n)cnt <= 20'd0;else if(key_an)cnt <= 20'd0;elsecnt <= cnt + 20'd1;endreg [2:0] key_value;always @(posedge clk or negedge rst_n)beginif(!rst_n)key_value <= 3'b111;else if(cnt == 20'hfffff) // 2^20*1/(50MHZ)=20ms key_value <= {key3_n,key2_n,key1_n}; // 去抖20ms 后读取当前时刻的按键值endreg [2:0] key_value_r;always @(posedge clk or negedge rst_n)beginif(!rst_n)key_value_r <= 3'b111;elsekey_value_r <= key_value; // 将去抖前一时刻的按键值进行存储endwire [2:0] key_ctrl = key_value_r & (~key_value); // 当键值从0到1时key_ctrl改变reg d1;reg d2;reg d3;always @(posedge clk or negedge rst_n)beginif(!rst_n)begin // 一个if内有多条语句时不要忘了begin end d1 <= 0;d2 <= 0;d3 <= 0;endelsebeginif(key_ctrl[0]) d1 <= ~d1;if(key_ctrl[1]) d2 <= ~d2;if(key_ctrl[2]) d3 <= ~d3;endendassign led1_n = d1? 1'b1:1'b0; // 此处只是为了将LED输出进行翻转,RTL级与下面注释代码无差别assign led2_n = d2? 1'b1:1'b0; assign led3_n = d3? 1'b1:1'b0; endmodule。
【豆丁-精品】-基于FPGA的按键消抖动设计
2009年11月吉林师范大学学报(自然科学版)№.4第4期Journal of Jilin Normal University (Natural Science Edition )Nov.2009收稿日期:2009209222 基金项目:吉林省信息产业厅专项发展基金项目(2007042)作者简介:许德成(19772),男,吉林省辽源市人,现为吉林师范大学信息技术学院讲师,硕士.研究方向:基础电子技术,单片机及可编程逻辑器件技术.基于FPG A 的按键消抖动设计许德成(吉林师范大学信息技术学院,吉林四平136000)摘 要:在研制测量仪表、电子仪器及电子设计的过程中,按键是常用器件,而按键的弹跳现象是数字系统设计中存在的客观问题.这就要求电路具有消抖措施,即对于由于机械弹跳产生的噪声信号经过消抖电路滤除,保证电路能够正确的响应.本文介绍了基于FPG A 的两种消除按键抖动的方法,并给出了相应的VH D L 代码以及仿真图形,从而解决了按键的机械抖动影响,保证电路稳定工作.关键词:机械抖动;仿真图形;电路中图分类号:T N912 文献标识码:A 文章编号:1674238732(2009)04201542030 引言我们通常所用的按键都为机械触点开关.由于机械触点存在弹性作用,当我们按下按键或松开按键时,都不可避免的要在触点闭合及断开的瞬间产生有一连串的键抖动.其按键信号的实际波形如图1所示.图1 按键信号的实际波形 由图1可见,在按键闭合和断开时产生了多个边沿.而在实际中每按一次键,我们只需要一组稳定的上升或下降边沿.所以对于电路中的按键信号,如果我们不滤除抖动的话,还是简单的读取信号的边沿,会引起一次按键被误读多次.这样就会引起电路的误动作.为了保证按一次键电路只有一次正确的响应,即在键闭合稳定时读取键的状态,就要求电路中必须采取滤除抖动的措施.消除案件抖动的方法一般有硬件和软件两种方式.对于硬件方式一般可用RS 触发器作为常用的消抖电路,从根本上解决按键抖动问题.但对于按键较多且从节省硬件资源和易于修改的角度考虑,我们常应用软件滤抖.1 基于计数器模式消抖电路的设计方法应用计数器实现,即采用延时的方法.先正确设定计数的时钟脉冲.当判断到按键按下时计数器开始计数,等计数器计满后再一次判断键的状态.如果仍为按下状态,则认为是按键稳定闭合.这时再针对具体按键信号做相应的处理,否则认为是抖动信号,电路不做任何处理.应用这种方法消除按键抖动,其计数器模值的确定和计数时钟的频率是按键抖动消除的关键问题,因为它们共同决定了延时的时间.如果延时时间过长,就会使正确的按键信号得不到处理;如果延时时间过短,则会将抖动误认为是输入信号,从而导致后电路做出错误处理.一般人按键的时间大于100ms ,抖动时间一般·451·为5ms ~10ms.按这种常规处理,我们一般认为接收到的按键信号持续时间如果小于40ms 则其为抖动信号,如果时间大于40ms 则为正确的按键信号.即让计数器的模值和计数时钟周期的乘积略大于40ms 即可.这样就可以把按下的时间小于40ms 的抖动信号滤掉.其VH D L 代码为:library ieee ;use ieee.std -logic -1164.all ;entity anjian is port (clk ,input :in std -logic ;output :out std -logic );end anjian ;architecture one of anjian is signal a :std -logic ;signal count :integer range 0to 9;beginprocess (clk )beginif input =′0′then count <=0;elsif clk ’event and clk =′1′thenif count =9then count <=count ;else count <=count +1;end if ;end if ;if count =8then a <=′1′;else a <=′0′;end if ;end process ;output <=a ;end one; 由上仿真图可以看出:当信号维持时间小于八个计数时钟周期的时候,认为这时的信号是短时间的抖动信号,所以电路输出不做任何反应.保持原电平不变,后续电路也无需处理.当信号维持时间超过八个计数时钟周期,认为这时定稳定的按键信号,即键稳定的闭合.所以输出一个按键脉冲,以供后续电路处理.2 基于RS 触发器模式的消抖动电路设计在设计中用时钟信号进行采样.对于按键输入信号,当两次采样信号相同时,这是判定已经稳定的按下或放开了按键.触发器相应的被置成0态或1态.如两次采样结果不相同.则触发器维持原输出信号不变.由于直接由触发器输出的信号时间宽度可能过长,所以在触发器后再接一级同步化电路,保证每次输出的信号只占有一个时钟周期的宽度.应用这种方法去滤除抖动,关键是确定采样时钟的频率.保证两次采样的时间间隔能够大于按键的抖动时间,且小于正常按键时的按键稳定闭合时间.其VH D L 代码和仿真如下:library ieee ;use ieee.std -logic -1164.all ;entity dou is port (din ,clk :in std -logic ;dout :out std -logic );end entity dou ;architecture one of dou issignal clr0,clr1,q0,q1,d1,d0:std -logic ;beginclr0<=din ;clr1<=q0;process (clk ,clr0,clr1)beginif clr0=′0′then q0<=′0′;elsif clk ′event and clk =′1′thenq0<=′1′;end if ;if clr1=′0′then q1<=′0′;elsif clk ′event and clk =′1′thenq1<=′1′;end if ;end process ;process (clk )beginif clk ′event and clk =′1′thend0<=q1;d1<=d0;end if ;end process ;dout <=d0and (not d1);end ;·551· 由上仿真图形可以看出:当两次的采样信号结果相同时,这时输出信号才可能发生变化,对应的按键的稳定闭合或断开,当两次的采样信号结果不同时,认为输入的信号定抖动信号.这时电路输出维持原状态不变,同时由于有同步化的处理,输出信号的高电平宽度只为采样时钟的一个周期.3 结束语通过以上的仿真图形可以看出,对于带有机械抖动的按键信号,当它经过消抖电路处理后其输出信号已经将抖动滤除,且输出信号只占有一个时钟信号的周期,从而能使后续电路能够正确的读取键值,做相应的响应,有效的避免了误动作.因此该设计有很大的实际应用意义.参 考 文 献[1]潘 松,黄继业.E DA 技术实用教程[M].北京:科学出版社,20051[2]谭会生,瞿遂春.E DA 技术综合应用实例与分析[M].西安:西安电子科技大学出版社,2004.[3]林明权等.VH D L 数字控制系统设计范例[M].北京:电子工业出版社,2003.[4]方 龙,肖献保,李 威.关于消除按键机械抖动的研究[J ].广西轻工业,2008,1:92.[5]潘永雄,泌河,刘向阳.电子线路CAD 实用教程[M].西安:西安电子科技大学出版社,2004.[6]杨 恒,李爱国,王辉,王新安.FPG A/CP LD 最新实用技术指南[M].北京:清华大学出版社,2005.[7][美]沃尔夫(W olr.w )基于FPG A 的系统设计(英语版)[M].北京:机械工业出版社,2005.[8]王强,曾繁泰,励娜.EPA 工程的理论与实践—S OC 系统蕊片设计[M].北京:电子工业出版社,2004.[9]李国洪,胡辉,沈阳山等.E DA 技术与实验[M].北京:电子工业出版社,2005.Shaking R elease Design on the K eys of FPGAXU De 2cheng(C ollege of In formation T echnology ,Jilin N ormal University ,S iping 136000,China )Abstract :K eys were the comm on elements during the research of measure instrument ,electronic apparatus ,and design of the electronic.The bounce phenomenon of keys was the objective problem in the digital system design.Therefore ,the shaking release measurement was necessary.That is to rem ove the noise signal at the engine bounce through the elimi 2nating the shaking circuit in order to ensure the right response of the circuit.The paper introduced tw o methods of elim 2inating shaking on FPG A and gave the relative VH D L code and the imitating picture.It res olved the in fluence of engine shaking on keys and ensurd the steady w orking of the circuit.K ey w ords :engine shaking ;imitating picture ;circuit·651·。
FPGA学习按键消抖实验Verilog代码
FPGA学习按键消抖实验Verilog代码modulesw_de(clk,rst_n,sw1_n,sw2_n,sw3_n,led_d1,led_d2,led_d3);input clk; //主时钟信号 50MHzinput rst_n; //复位信号低有效input sw1_n,sw2_n,sw3_n;//三个独立按键低表示按下output led_d1,led_d2,led_d3;//发光二级管,分别由按键控制//------------------------------------------------------reg[2:0] key_rst;always @ (posedge clk or negedge rst_n)if(!rst_n) key_rst<=3'b111;else key_rst <= {sw3_n ,sw2_n ,sw1_n};reg[2:0] key_rst_r;//每个时钟周期的上升沿将low_sw信号锁存到low_sw_r中always @ (posedge clk or negedge rst_n)if(!rst_n) key_rst_r<=3'b111;else key_rst_r<=key_rst;//当寄存器key_rst由1变为0时,led_an的值变为高,维持一个时钟周期wire[2:0]key_an=key_rst_r&(~key_rst);//-----------------------------------------------------reg[19:0] cnt;//计数寄存器always @ (posedge clk or negedge rst_n)/*always块clk时钟的上升沿和rst_n复位信号的下降沿触发执行*/if (!rst_n) cnt<=20'd0;else if (key_an) cnt<=20'd0;else cnt<=cnt+1'b1;reg[2:0] low_sw;always @ (posedge clk or negedge rst_n)if (!rst_n) low_sw<=3'b111;else if(cnt==20'hfffff)/*满20ms,将按键值锁存到寄存器low_sw中20'hfffff='d1048575 t=1/48000000*1048575=0.021s*/ low_sw<={sw3_n,sw2_n,sw1_n};/*将按键sw3_n,sw2_n,sw1_n,用位拼接符{}拼接为一个三位的数传给low_sw*///-----------------------------------------------------------reg[2:0] low_sw_r; //每个时钟周期的上升沿将low_sw信号锁存到low_sw_ralways @ (posedge clk or negedge rst_n)if (!rst_n) low_sw_r<=3'b111;else low_sw_r<=low_sw;//当寄存器low_sw由1变为0时,led_ctr1的值变为高,维持一个时钟周期wire[2:0] led_ctr1=low_sw_r[2:0]&(~low_sw[2:0]);//找出变化的键存到led_ctr1中reg d1;reg d2;reg d3;always @ (posedge clk or negedge rst_n)if (!rst_n)begind1<=1'b0;d2<=1'b0;d3<=1'b0;endelse begin //某个按键值变化时,LED将亮灭翻转 if (led_ctrl[0]) d1<=~d1;if (led_ctrl[1]) d2<=~d2;if (led_ctrl[2]) d3<=~d3;endassign led_d3=d1?1'b1:1'b0; assign led_d2=d2?1'b1:1'b0; assign led_d1=d3?1'b1:1'b0; endmodule。
FPGA开发中按键消抖与单脉冲发生器电路
FPGA开发中按键消抖与单脉冲发生器电路作者:邢自茹史明健来源:《现代电子技术》2009年第21期摘要:在介绍FPGA开发中按键消抖电路和单脉冲发生器电路原理的基础上,设计实现了键控单脉冲发生器,利用计数器解决了按键高频消抖问题,并通过按键产生与时钟脉冲完全相同的单脉冲。
该单脉冲键控发生器可独立应用于其他FPGA电路设计中。
在Quartus环境下给出Verilog HDL语言的行为及描述,并进行仿真实验,结果显示该电路合理可行。
关键词:单脉冲发生器;按键消抖;FPGA;Verilog HDL中图分类号:TN782 文献标识码:A文章编号:1004-373X(2009)21-171-02Elimination Buffeting of Keystroke and Single Pulse GeneratorCircuit in FPGA Development ProcessXING Ziru,SHI Mingjian(Inner Mongolia University of Technology,Huhhot,010051,China)Abstract:The circuit principle of elimination buffeting of keystroke and a single pulse generator in FPGA development are introduced,and keying single pulse generator is achieved.It solves eliminating high-frequency buffeting problem by a counter and produces the single pulse which has the same pulse width and same phase with clock cycle.Keying a single pulse generator can be applied to other independent FPGA design.The behavior and description based on Verilog HDL language are given and it is simulated in Quartus software,the method is proved logical and feasible as a result.Keywords:single pulse generator;elimination buffeting of keystroke;FPGA;Verilog HDLFPGA开发中常用到单脉冲发生器。
基于FPGA的抖动及消抖的方法
基于FPGA的抖动及消抖的方法抖动的产生通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。
因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖。
抖动时间抖动时间的长短由按键的机械特性决定,一般为5ms~10ms。
这是一个很重要的时间参数,在很多场合都要用到按键稳定闭合时间的长短则是由操作人员的按键动作决定的,一般为零点几秒至数秒。
键抖动会引起一次按键被误读多次。
为确保FPGA对键的一次闭合仅作一次处理,必须去除键抖动。
在键闭合稳定时读取键的状态,并且必须判别到键释放稳定后再作处理。
FPGA内实现消抖的方法在FPGA内实现按键消抖的方法多种多样,但是最简单的是采用移位寄存器的方法进行消抖。
因为移位寄存器的方法不需要对时钟进行分频,也不需要进行延时等复杂操作,即可实现对按键边沿的检测。
假设未按下时键值=1.1、在无键按下时,移位寄存器samp[7:0]始终采集到高电平,即samp[7:0]=8b1111_1111;2、当键按下时,samp[7:0]将采集到低电平,数据的变化方式为samp[7:0]=8b1111_1110--8b1111_1100--8b1111_1000-- ........8b0000_0000;samp[7:0]=8b1111_ 1110即为按键下降沿。
3、当松开按键时,samp[7:0]将重新采集到高电平,数据变化方式为samp[7:0]=8b0000_0001--8b0000_0011-- ........--8b1111_1111;当samp[7:0]=8b0111_1111时,即为按键上升沿。
参考Verilog代码//模块名:EdgeDetect,边沿检测//button:按键,无键按下时为高电平//clk:10M时钟//rst:复位按钮,低电平有效//rise:检测到上升沿,高电平有效,宽度为1个clk//fall:检测到下降沿,高电平有效,宽度为1个clkmodule EdgeDetect(input clk,input rst,input button,output reg rise,output reg fall);。
fpga按键消抖原理
fpga按键消抖原理fpga按键消抖原理___________________FPGA按键消抖是一种用于处理按键输入信号的技术,它可以有效地降低噪声对按键信号的影响,从而确保按键输入的正确性。
## 一、什么是fpga按键消抖FPGA按键消抖是一种应用于处理外部输入的技术,它可以有效地减少按键输入的误差,同时防止因由噪声或触发时间过长等原因导致的误操作,从而保证操作系统的稳定性和正确性。
## 二、fpga按键消抖的原理FPGA按键消抖的原理是:当用户按下一个按钮时,FPGA会连续采集多个采样点,并判断采样点的平均值,如果采样值与平均值相差不大,则认为是有效的输入;如果采样点的平均值与采样值相差较大,则认为采样点受到了噪声干扰,此时不认为是有效的输入。
此外,FPGA还会根据按钮被按下的时间来决定是否应该将其作为有效输入:如果用户在一定的时间内多次重复按下一个按钮,FPGA会自动将其作为无效输入,从而避免重复操作。
## 三、fpga按键消抖的应用FPGA按键消抖在实际应用中最常用于处理用户输入,它可以有效地避免由于噪声或触发时间过长而导致的误差。
此外,FPGA也可以用于处理传感器输出,例如测量传感器的输出信号、光学传感器的输出信号等。
## 四、fpga按键消抖的注意事项在使用FPGA进行按键消抖时,应该注意以下几点:1. FPGA采样点的数量要适当:采样点的数量不宜过多或过少,要根据实际情况适当调整。
2. FPGA采样点的间隔要适当:采样点之间的间隔应该尽可能小,以便能够有效地减少噪声对信号的影响。
3. FPGA采样点的平均值要适当:采样点的平均值应该尽可能小,以便能够有效地减少噪声对信号的影响。
4. FPGA采样时间要适当:FPGA在采样信号时应该尽可能快,以便能够有效地减少噪声对信号的影响。
## 五、总结FPGA是一种常用的电子设备,它可以有效地处理外部输入信号,从而避免因由噪声或触发时间过长而导致的误差。
消抖电路原理及实现
实 验 报 告实验日期: 学 号:姓 名:实验名称:消抖电路总 分:一、实验概述运用LPM 原件定制DFF 触发器,并调用LPM 定制的DFF 触发器,用VHDL 语言的元件例化实现消抖电路并了解其工作原理。
二、实验原理 1、触发器原理触发器是一种可存储1位二进制码的逻辑电路,是构成各种时序电路的最基本逻辑单元。
触发器有一对互补输出端,输出状态不仅与当前输入有关,还与前一输出状态有关。
触发器有两个稳定状态,在一定的外界信号作用下会发生状态翻转。
2、消抖电路原理脉冲按键与电平按键通常采用机械式开关结构,其核心部件为弹性金属簧片。
按键信号在开关拨片与触电接触后经多次弹跳才会稳定,而在按键过程中,可能出现了多个脉冲。
因此需要根据实际情况进行按键消抖处理以提取稳定脉冲,在按键过程中提取稳定的电平状态,通过对抖动脉冲多次检测信号按键电平值,并提取一前一后两个信号按键电平值来进行比较,以此来获取开关状态。
输出一个周期的脉冲时,要求前一次检测到的电平信号为低电平,后一次检测到的电平信号为高电平时。
3、结构图:三、实验设计时钟信号 元件记忆当前的按键信号电平 元件记忆上一次按键信号电平 两次按键的电平进行比较 脉冲信号1、LPM元件定制DFF触发器(1)设置lpm_ff元件选择Installed Plug-Ins→Storage→lpm_ff项。
(2)LPM元件定制步骤,设置输入data为1位,clock为时钟信号,类型为D 型。
(3)添加异步清零和异步置1。
(4)aclr异步清零且高电平有效,aset异步置1且高电平有效,二者无效时,q输出由clock上升沿触发更新为data。
(5)调出其vhd文件添加至消抖电路的工程中。
(6)仿真验证并下载。
功能仿真波形分析参数:end time 为2.0ns,grid size为100ns;信号:alcr 异步清零且高电平有效,二进制;aset异步置1且高电平有效,二进制;二者无效,q(二进制)输出由clock(二进制)上升沿触发更新为data(二进制)。
FPGA入门系列实验教程——按键消抖控制LED亮灭
FPGA入门系列实验教程——按键消抖控制LED亮灭1.实验任务实现按键控制LED亮灭。
通过这个实验,掌握采用Verilog HDL语言编程实现按键控制LED亮灭及按键消抖方法。
2.实验环境硬件实验环境为艾米电子工作室型号EP2C8Q208C8增强版开发套件。
软件实验环境为Quartus II8.1开发软件。
3.实验原理当独立按键key1按下后,相应的LED被点亮;再次按下后,LED做翻转输出,即LED熄灭,从而实现按键控制LED亮灭。
本实验对按键进行了消抖处理。
作为机械开关的按键,操作时,机械触点的弹性及电压突跳等原因,在触点闭合或开启的瞬间会出现电压抖动,实际应用中如果不进行处理将会造成误触发。
按键去抖动的关键在于提取稳定的低电平状态,滤除前沿、后沿抖动毛刺。
按键消抖处理一般有硬件和软件两种方法。
软件消抖是检测到有触发后,延时一段时间后再检测触发状态,如果与之前检测到的状态相同,则认为有按键按下;如果没有则认为是误触发。
硬件就是加去抖电路。
4.实验程序module key_debounce(rst_n,clk,key,led);input rst_n;input clk;input key;output led;//通过降采样对key的输入做低通滤波,将其高频分量滤除,得到low_sw值reg[17:0]cnt;always@(posedge clk)if(!rst_n)cnt<=18'd0;elsecnt<=cnt+1'b1;wire sample_pulse=cnt==18'h3ffff;reg low_sw;always@(posedge clk)if(!rst_n)low_sw<=1'b1;else if(sample_pulse)low_sw<=key;//在整个low_sw(active_low)有效过程中取一个控制量作为led的控制信号//本实例中使用low_sw的下降沿reg low_sw_r;//将low_sw信号锁存一个时钟周期,延时不是真的“锁存”always@(posedge clk)low_sw_r<=low_sw;wire led_ctrl=low_sw_r&(!low_sw);reg led;always@(posedge clk or negedge rst_n)if(!rst_n)led<=1'b0;else if(led_ctrl)led<=~led;endmodule5.实验步骤(1)建立新工程项目:打开Quartus II软件,进入集成开发环境,点击File→New project wizard建立一个工程项目key_debounce。
10_基于FPGA进行按键消抖
10_基于FPGA进⾏按键消抖10_基于FPGA进⾏按键消抖实验原理计数器型消抖电路:计数器型消抖电路(⼀) 计数器型消抖电路(⼀)是设置⼀个模值为(N+1)的控制计数器,clk在上升沿时,如果按键开关key_in='1',计数器加1,key_in='0'时,计数器清零。
当计数器值为2时,key_out输出才为1,其他值为0时。
计数器值为N时处于保持状态。
因此按键key_in持续时间⼤于N个clk时钟周期时,计数器输出⼀个单脉冲,否则没有脉冲输出。
如果按键开关抖动产⽣的⽑刺宽度⼩于N个时钟周期,因⽽⽑刺作⽤不可能使计数器有输出,防抖动⽬的得以实现。
clk的时钟周期与N的值可以根据按键抖动时间由设计者⾃⾏设定。
下图为N为3的波形仿真图,当按键持续时间⼤于3个时钟周期,计数器输出⼀个单脉冲,其宽度为1个时钟周期,⼩于3个时钟周期的窄脉冲⽤作模拟抖动⼲扰,从图1可以看出,抖动不能⼲扰正常的单脉冲输出。
该⽅法的特点是能很好消除按键抖动产⽣的窄脉冲,还可以滤去⼲扰、噪⾳等其他尖峰波,但遇到脉宽⼤于N个Tclk时钟周期的⼲扰、噪⾳等时会有输出从⽽产⽣误操作,⽽对于按键操作要求按键时间必须⼤于N个Tclk时钟周期,否则按键操作也没有输出。
计数器型消抖电路(⼆) 计数器型消抖电路(⼆)是控制计数器⼯作⼀个循环周期(N+1个状态),且仅在计数器为0时输出为"1"。
电路设计了连锁控制设施。
在计数器处于状态0时,此时若有按键操作,则计数器进⼊状态1,同时输出单脉冲(其宽度等于时钟周期)。
计数器处于其他状态,都没有单脉冲输出。
计数器处于状态N时,控制en='0',导致计数器退出状态N,进⼊状态0。
计数器能否保持状态0,取决于⼈⼯按键操作,若按键key_in='1',控制en='1'(计数器能正常⼯作),key_in='0',计数器状态保持。
基于FPGA的按键消抖电路设计方法的研究
基于FPGA的按键消抖电路设计方法的研究于晶;杨晓慧;黄勇【摘要】采用了VHDL语言编程的设计方法,通过FPGA来实现按键消抖的硬件电路。
论述了基于计数器、RS触发器和状态机3种方法来实现按键消抖电路,并给出仿真结果。
通过下载到CycloneEP1C6T144芯片中进行验证,表明这3种方法设计的消抖电路都能够实现电路功能,其中有限状态机的方法更能确保每一次按键操作后准确输出按键确认信号,且性能稳定。
%In order to solve key jitter of FPGA system,use the design method of VHDL language programming to realize key-jitter.Discusses three methods base on counter,RS flip-flop and state machine with simulation and analysis.Being verified by theCycloneEP1C6T144,the three methods all able to achieve the circuit function,can guarantee a quick keypress once every time the response,and have stable property.The main innovation is using the most simple programming to realize key-jitter.【期刊名称】《电子设计工程》【年(卷),期】2011(019)022【总页数】3页(P1-3)【关键词】按键消抖;计数器;RS触发器;状态机【作者】于晶;杨晓慧;黄勇【作者单位】长春理工大学,吉林长春130000;长春理工大学,吉林长春130000;吉林博安消防设备有限公司,吉林长春130000【正文语种】中文【中图分类】TP274通常所用的按键都为机械触点开关,由于机械触点存在弹性作用,当按下按键或松开按键时,都不可避免地要在触点闭合及断开的瞬间产生一连串的键抖动。
基于FPGA的按键弹跳消除电路的研究与应用
摘 要: . 按健在 数字 电路设 计 中经 常用到 。按 键 的弹 疏现象是数 字 系统 设计 中存在 的客观 问意 。按键是 机械触点 , 当接 触点断开 或闭 合 时会 产生抖 动。为使每一 次按 键 只做 一次响应 , 就必须去 除抖 动 。本文对按 键的抖 动信号进行 了分析 , 并通 过计数 器的方式完成 了 消除抖 动电路模块 的设 计。把 该模块 应用到按键控 . LC j D显示的 系统 中, 并在 Me c i tx MB 系统实验 板上实现 了该 东统 。消 me v re 一4
维普资讯
兰嫂 . Q: Q 竺
Sic a e nlyn vtn e l cn d c og Ioao Hrd e e n T h o n i a
工 业 技 术
基于 F GA的按键 弹跳消 除电路的研 究与应用 P
李 婷 ( 同济大学微 电子 中心 上海 2 0 9 ) 0 02
r s t e e ,
a y  ̄( s g l rn g t ee l s p e ec o e  ̄ g r t wa o d k e s)
b gn e i
i(rst o n 0 2 ’0 0 0 f!ee)c u t<= 1h 0 0 0I e e i b t n o t= 0 c u t l f ut — u 1 =l b ) s ( o o n0 <=c u t +1 / o n 0 ; /对低电平计数
es ou 0<=2 l c nt e 1’h0 0  ̄ l 00 e d n
/ /输 出 a y  ̄(oe g l rn g d e r e l s p s ec o e e g e t wa d k s)
e i b gn
i(rst u tn o t— e <=lb1 f!ee)b to — u lr g ’ I e f o n 0 = l h 3 2 0 /判断 l i c u t: 2 『 l lD )/ e s ( 低 电平信 号是否符合输 出条件 b to _ u i rg u tn o t— e <=lb l / O /如 果符合 条件 , 则输 出低 电平 es fc u t==2 ’ 1 1 D0 /判 断 le i(o n l l h 3 2 )/ 低 电平 信号是否符合输 出条件
(整理)拨码开关控制实验电路图
拨码开关控制实验电路图流程图/* 基本开关控制实验 *///==宣告区=================================#include <reg51.h> //定义8051头文件,引入reg52.h#define SW P2//定义开关接至P2#define LED P1//定义LED接至P 1//==主程式=================================main()//主程序开始{ SW=0xff;//规划输入端口while(1)//无穷循环,程式一直跑LED=SW;//读取开关(P2)状态,输出到LED(P1)}//主程序结束思考一下!在本实验里,有没有“抖动”的困扰?若希望拨码开关中的S1、S3、S5三个开关都on,则前四个LED 亮;S2 或 S4 或 S6开关 on,则后四个LED 亮;S7及 S8 开关 on,则所有LED全亮,程序应如何编写?若将拨码开关换成一般家里墙壁上的开关,而LED换成继电器(RELAY),是否可作为家里的负载控制?按钮ON-OFF控制实验按钮ON-OFF 控制实验电路图流程图如下:/* 基本按钮ON-OFF控制实验*///==声明区======================================= #include<reg51.h>//定义8051头文件,引入reg52.h sbit PB1=P2^0;//声明按钮1接至P2.0sbit PB2=P2^1;//声明按钮2接至P2.1sbit LED=P1^0;//声明LED为P1.0//==主程式======================================= main()//主程序开始{ LED=1;//关闭LEDPB1=PB2=1;//规划输入端口while(1)//无穷循环,程式一直跑{if (PB2==0)LED=1;//若按下PB2,则关闭LEDelse if (PB1==0)LED=0;//若按下PB1,则点亮LED}//while循环结束}//结束程序思考一下!在本实验里,有没有“抖动”的困扰?若将按钮开关当成启动电机的ON-OFF开关,而LED换成继电器(RELAY),是否可作为电机控制?若同时按下PB1 与PB2按钮会怎样?按钮切换式控制实验按钮切换式控制实验电路图流程图实验代码:/* 按钮切换式控制实验*///==声明区===================================== #include<reg51.h>//定义8051头文件,引入reg52.h sbit PB1=P2^0;//声明PB1接至P2.0sbit LED=P1^0;//声明LED接至P1.0void debouncer(void);//声明防弹跳函数//==主程序===================================== main()//主程式开始{ LED=1;//关闭LEDPB1=1;//规划P2.0为输入埠while(1)//无穷循环,程序一直跑{ if (PB1==0)//若按下PB1{ debouncer();//呼叫防弹跳函数(按下时)LED=!LED;//切换LED为反相while(PB1 != 1);//若仍按住PB1,继续等debouncer();//呼叫防弹跳函数(放开时)}//if叙述结束}//while循环结束}//主程序结束//==子程序=====================================/* 防弹跳函数函数,延迟约20ms */void debouncer(void)//防弹跳函数开始{ int i;//声明整数变数ifor(i=0;i<2400;i++);//计数2400次,延迟约20ms}//防弹跳函数结束思考一下!在本实验里,改变debouncer函数的时间长短,看看有什么影响?若按住PB1不放会怎样?如何改善?按钮开关应用电路图流程图代码如下:/* 按钮开关应用(两按钮控制七段显示器上下数) *///==声明区==========================================#include<reg51.h>//定义8051头文件,引入reg52.h文件#define SEG P0//定义七节显示器接至P0端口/* 声明七节显示器驱动信号阵列(共阳) */char codeTAB[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x83,0xf8,0x80,0x98};//数字0-9sbit PB1=P2^0;//声明按钮1接至P2.0sbit PB2=P2^1;//声明按钮2接至P2.1void debouncer(void);//声明防弹跳函数//==主程式=================================main()//主程序开始{ unsigned char i=0;//声明变量i初值=0PB1=PB2=1;//规划输入端口SEG=TAB[i];//输出数字至七段显示器while(1)//无穷循环,程式一直跑{ if (PB1==0)//判断PB1是否按下{ debouncer();//呼叫防弹跳函数i= (i<9)? i+1:0;//若i<9则i=i+1,若i>=9清除为0SEG=TAB[i]; //输出数字至七段显示器while(PB1==0); //PB1是否按住?debouncer(); //呼叫防弹跳函数}//if叙述结束if (PB2==0)//判断PB2是否按下{ debouncer();//呼叫防弹跳函数i= (i>0)? i-1:9;//若i>0则i=i-1,i<=0重设为9SEG=TAB[i];//输出数字至七段显示器while(PB2==0);//PB1是否按住?debouncer();//呼叫防弹跳函数}//if叙述结束}//while循环结束}//主程序结束//==子程序==================================/* 防弹跳函数函数,延迟约20ms */void debouncer(void)//防弹跳函数开始{ int i;//声明整数变量ifor(i=0;i<2400;i++);//计数2400次,延迟约20ms}//防弹跳函数结束思考一下!在本实验里,若按钮按住不放,会怎样?如何改善?在本实验里,若PB1与PB2两个按钮同时按,会怎样?BCD数字型拨码开关实验BCD数字型拨码开关实验电路图流程图实验代码:/* BCD数字型指拨开关实验*///==声明区======================================#include<reg51.h>//定义8051头文件,引入reg52.h文件#define SEG P0//定义七节显示器接至P0#define SW P2//定义开关接至P2/* 声明七节显示器驱动信号阵列(共阳) */char codeTAB[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x83,0xf8,0x80,0x98};//数字0-9#define SW_H() SW&0x0f//读取开关值(P2清除高4bits)//==主程序======================================main()//主程序开始{ SW=0xff;//规划输入埠while(1)//无穷循环,程序一直跑SEG=TAB[SW_H()];//读取开关值,输出至七节显示器(P0)}//主程序结束思考一下!在本实验里,有没有“抖动”的困扰?若把本单元的BCD数字型拨码开关,改为16进位数字型拨码开关,程序应如何修改?多重按钮开关实验多重按钮开关实验电路图流程图实验中的自编库函数/* myio.h自己写的程序库*///==声明区============================== #define LED P1//定义LED接至P1void debouncer(void);//声明防弹跳函数void delay10ms(int);//声明10毫秒延迟函数void alter(int);//声明交互闪烁函数void left(int);//声明单灯左移函数void right(int);//声明单灯右移函数void pili(int); //声明霹雳灯函数void flash(int);//声明闪烁函数//==自己写的子程序========================/* 防弹跳函数函数,延迟约20ms */void debouncer(void)//防弹跳函数开始{ delay10ms(2);//延迟约20ms}//防弹跳函数结束/* 延迟函数开始,延迟约x 10ms */void delay10ms(int x)//延迟函数开始{ int i,j;//声明整数变量i,jfor (i=0;i<x;i++)//计数x次,延迟约x 10msfor (j=0;j<1200;j++);//计数1200次,延迟约10ms }//延迟函数结束/* 高低位元交互闪烁函数,执行x次*/void alter(int x)//高低位元交互闪烁函数开始{ int i;//声明变量iLED=0x0f;//初始状态(高位元亮,低位元灭)for(i=0;i<2*x-1;i++)//i变量for循环执行2x-1次{ delay10ms(50);//延迟50*10m=0.5sLED=~LED;//LED反相输出}//i变量for循环结束delay10ms(50);//延迟50 10m=0.5s}//高低位元交互闪烁函数结束/* 全灯闪烁函数,执行x次*/void flash(int x)//全灯闪烁函数开始{ int i;//声明变量iLED=0x00;//初始状态(全亮)for(i=0;i<2*x-1;i++)//i变量for循环执行2x-1次{ delay10ms(50);//延迟50 10m=0.5sLED=~LED;//P0反相输出}//i变量for循环结束delay10ms(50);//延迟50 10m=0.5s}//全灯闪烁函数结束/* 单灯左移函数,执行x圈*/void left(int x)//单灯左移函数开始{ int i, j;//声明变量i,jfor(i=0;i<x;i++)//i循环,执行x圈{ LED=0xfe;//初始状态=1111 1110for(j=0;j<7;j++)//j循环,左移7次{ delay10ms(25);//延迟25 10m=0.25sLED=(LED<<1)|0x01;//左移1位後,LSB设为1 }//j循环结束delay10ms(25);//延迟25 10m=0.25s}//i循环结束*/}//单灯左移函数结束/* 单灯右移函数,执行x圈*/void right(int x)//单灯右移函数开始{ int i, j;//声明变量i,jfor(i=0;i<x;i++)//i循环,执行x圈{ LED=0X7f;//初始状态=0111 1111for(j=0;j<7;j++)//j循环,右移7次{ delay10ms(25);//延迟25 10m=0.25sLED=(LED>>1)|0x80;//左移1位後,MSB设为1 }//j循环结束delay10ms(25);//延迟25 10m=0.25s}//i循环结束}//单灯左移函数结束/* 霹雳灯函数,执行x圈*/void pili(int x)//霹雳灯函数开始{ int i;//声明变量ifor(i=0;i<x;i++)//i循环,执行x圈{ left(1);//单灯左移一圈right(1);//单灯左移一圈}//i循环结束}//霹雳灯函数结束多重按钮开关实验之一:代码/* 多重按钮开关实验之1 *///==声明区================================#include<reg52.h>//定义8051头文件,引入reg52.h文件#include"myio.h"//自己写的I/O程序库sbit PB1=P2^0;//声明PB1=P2.0sbit PB2=P2^1;//声明PB2=P2.1sbit PB3=P2^2;//声明PB3=P2.2sbit PB4=P2^3;//声明PB4=P2.3//==主程序================================ main()//主程序开始{ LED=0xff;//初始状态(LED全灭)P2=0xff;//规划P2输入端口while(1)//无穷循环,程序一直跑{ if (PB1==0)//如果按下PB1{ debouncer();//防弹跳alter(3);//高低位元交互闪烁三次flash(3);}//全灯闪烁三次else if (PB2==0)//如果按下PB2{ debouncer();//防弹跳left(3);//单灯左移三圈flash(3);}//全灯闪烁三次else if (PB3==0)//如果按下PB3{ debouncer();//防弹跳right(3);//单灯右移三圈flash(3);}//全灯闪烁三次else if (PB4==0)//如果按下PB4{ debouncer();//防弹跳pili(3);//霹雳灯三圈flash(3);}//全灯闪烁三次}//while循环结束}//主程序结束思考一下!在本实验里,若同时按下多个按钮会如何?在本实验里,若按住按钮不放会如何?在本实验里,其中debouncer函数是个延迟20毫秒的函数,而delay10ms函数是个延迟10毫秒的函数,可否使用delay10ms 函数取代debouncer函数?如何修改?在本实验里,其中alter函数是个高四位与低四位交替闪烁的函数,而flash函数是个8灯闪烁的函数,其不同在于其初始值。
阐述基于FPGA的按键抖动的消除方法
阐述基于FPGA的按键抖动的消除方法我们在进行数字电路的设计的过程中,经常会碰到信号抖动相关的问题。
抖动信号大致分为两类:一类是时间极短的干扰信号(比如毛刺);另一类是时间较长的干扰信号(如本文所研究的按键抖动问题)。
对于第一类干扰信号——毛刺,它的时间极短,通常只有几纳秒,不能满足触发器的建立时间与保持时间,因此我们可以用一个D触发器去读带毛刺的信号,由于D触发器具有对毛刺不敏感的特点,可以去除信号中的毛刺,达到消除抖动的效果(消除毛刺的方法很多,在这里不做讨论,本文重点说明按键抖动的消除及其代码设计)。
在数字电路设计中,按键通常为一个个具有弹性的机械触点开关,其开启或者闭合的瞬间都会产生按键抖动,实际波形如图1所示:由图1可知,在按键闭合和断开的瞬间,我们往往只需要一组稳定的上升边沿和下降边沿,但实际上却产生了若干个边沿。
所以,在实际电路中,我们仅仅按动按键,简单地读取信号的边沿,却不滤除抖动,会导致一次按键操作被误读多次,从而引起电路的误动作。
为了达到一次按键操作得到一次正确的响应的目的(在按键闭合或者断开),信号稳定的状态下读取此时按键的状态,就必须在电路中采取消除抖动的措施。
在纯数字电路设计中,下面介绍几种消除按键抖动的常用实现方法。
1 设计硬件消抖电路(硬件方法)设计一个具有延时作用的滤波电路或者经常用到的单稳态电路等硬件电路,来消除按键的抖动(避免抖动时间)。
图2所示的电路,即为典型的滤波延时消抖电路,S为按键,Di为CPU数据线。
当按键S未闭合时,与非门的输入电压Vi(即电容的端电压)为0,从而输出电压Vo为1。
我们按下按键S,电容C的端电压不会发生突变,充电延迟时间取决于R1、R2和C值的大小,当电容端电压在充电时间内未达到与非门的开启电压,将不会改变门的输出电压;当电容端电压大于门的开启电压时,与非门的输出Vo发生改变,即输出为0(我们在数字电路的设计过程中,为了避开按键抖动的影响,需要使充电延时大于或等于100ms)。
fpga按键消抖的原理和方法
FPGA(现场可编程门阵列)是一种可按照用户需求重新配置其硬件资源的可编程硅芯片。
在数字电路中,按键消抖 (Debounce) 是一个非常常见但重要的问题,因为机械按钮在按下和释放时会产生不稳定的信号。
为了解决这个问题,我们需要消除机械按键所产生的抖动信号。
消抖的原理是为输入信号添加处理和判断逻辑,将抖动视为一个单位的无效信号,从而过滤有问题的输入信号。
针对 FPGA,常用的按键消抖方法有以下两种:1. **计数器方法 (Counter Method)**这种方法检测按键输入是否持续一定时间内(假设我们使用n 个时钟周期)保持稳定。
如果输入持续稳定,则将其作为有效输入信号。
通过计数器实现的消抖具备可配置的消抖时间,从而适应各种不同类型的按键。
以下是计数器消抖方法的大致步骤:1. 初始化一个 n 位计数器。
2. 如果按键输入保持稳定(按下或释放),计数器增加,否则计数器清零。
3. 当计数器达到预定的阈值时,改变按键的状态(按下或释放)。
4. **移位寄存器方法 (Shift Register Method)**其实现原理是将多个连续的抖动信号视为一个有效输入,适用于按键抖动时间较短的场景。
以下是移位寄存器消抖方法的大致步骤:1. 初始化一个 n 位移位寄存器。
2. 每个时钟周期将输入信号添加到移位寄存器的低位(或高位),同时向右(或左)移动一位。
3. 当移位寄存器中所有位的值都相同(全为 0 或全为 1)时,认为信号稳定,将其视为有效输入信号。
在消抖方法的选择上,实际应用要考虑系统性能、消抖精度、按键抖动时间等因素。
简单的消抖算法可能只跟踪按键的状态改变,而更高级的算法可以检测按键被按下并保持的持续时间,从而在功能上更灵活。
【黑金原创教程】【FPGA那些事儿-驱动篇I】实验二:按键模块①-消抖
【⿊⾦原创教程】【FPGA那些事⼉-驱动篇I】实验⼆:按键模块①-消抖实验⼆:按键模块① - 消抖按键消抖实验可谓是经典中的经典,按键消抖实验虽曾在《建模篇》出现过,⽽且还惹来⼀堆⿇烦。
事实上,笔者这是在刁难各位同学,好让对⽅的惯性思维短路⼀下,但是惨遭⼝⽔攻击 ... ⾯对它,笔者宛如被甩的男⼈,对它⼜爱⼜恨。
不管怎么样,如今 I’ll be back,笔者再也不会重复⼀样的悲剧。
按键消抖说傻不傻说难不难。
所谓傻,它因为原理不仅简单(就是延迟⼏下下⽽已),⽽且顺序语⾔(C语⾔)也有⽆数不尽的例⼦。
所谓难,那是因为⼈们很难从单⽚机的思维跳出来 ... 此外,按键消抖也有许多细节未曾被⼈重视,真是让⼈伤⼼。
按键消抖⼀般有3段操作:l 检测电平变化;l 过滤抖动(延迟);l 产⽣有效按键。
假设C语⾔与单⽚机的组合想要检测电平变化,它们⼀般是利⽤if查询或者外部中断。
事后,如果这对组合想要过滤抖动,那么可以借⽤for 延迟的⼒量,⼜或者依赖定时中断产⽣精明的延迟效果。
反观有效案件的产⽣,这对组合视乎⽽外钟情“按下有效”似的 ... 不管怎么样,C语⾔与单⽚机这对组合在处理按键的时候,它们往往会错过⼀些黄⾦。
“黄⾦?”,读者震撼道。
所谓黄⾦时间就是电平发⽣变化那⼀瞬间,还有消抖(延迟)以后那⼀瞬间。
按键按下期间,按键的输⼊电平故会发⽣变化,如果使⽤if查询去检测,结果很容易浪费单⽚机的处理资源,因为单⽚机必须⼀直等待 ... 换之,如果反⽤外部中断,中断寻址也会耽误诺⼲时间。
假设C语⾔与单⽚机这对组合挨过电平检测这起难关,余下的困难却是消抖动作。
如果利⽤for循环实现去消抖,例如 Delay_ms(10) 之类的函数。
For循环不仅计数不紧密,⽽且还会⽩⽩浪费单⽚机的处理资源。
定时中断虽然计数紧密,但是中断触发依然也会产⽣诺⼲的寻址延迟。
补上,所谓寻址延迟是处理器处理中断触发的时候,它要事先保护现场之余,也要寻址中断处理⼊⼝,然后执⾏中断函数,完后回复现场,最后再返回当前的⼯作。
拨码开关控制实验电路图
拨码开关控制实验电路图流程图/* 基本开关控制实验 *///==宣告区=================================#include <reg51.h> //定义8051头文件,引入reg52.h#define SW P2//定义开关接至P2#define LED P1//定义LED接至P 1//==主程式=================================main()//主程序开始{ SW=0xff;//规划输入端口while(1)//无穷循环,程式一直跑LED=SW;//读取开关(P2)状态,输出到LED(P1)}//主程序结束思考一下!在本实验里,有没有“抖动”的困扰?若希望拨码开关中的S1、S3、S5三个开关都on,则前四个LED 亮;S2 或 S4 或 S6开关 on,则后四个LED 亮;S7及 S8 开关 on,则所有LED全亮,程序应如何编写?若将拨码开关换成一般家里墙壁上的开关,而LED换成继电器(RELAY),是否可作为家里的负载控制?按钮ON-OFF控制实验按钮ON-OFF 控制实验电路图流程图如下:/* 基本按钮ON-OFF控制实验*///==声明区======================================= #include<reg51.h>//定义8051头文件,引入reg52.h sbit PB1=P2^0;//声明按钮1接至P2.0sbit PB2=P2^1;//声明按钮2接至P2.1sbit LED=P1^0;//声明LED为P1.0//==主程式======================================= main()//主程序开始{ LED=1;//关闭LEDPB1=PB2=1;//规划输入端口while(1)//无穷循环,程式一直跑{if (PB2==0)LED=1;//若按下PB2,则关闭LEDelse if (PB1==0)LED=0;//若按下PB1,则点亮LED}//while循环结束}//结束程序思考一下!在本实验里,有没有“抖动”的困扰?若将按钮开关当成启动电机的ON-OFF开关,而LED换成继电器(RELAY),是否可作为电机控制?若同时按下PB1 与PB2按钮会怎样?按钮切换式控制实验按钮切换式控制实验电路图流程图实验代码:/* 按钮切换式控制实验*///==声明区===================================== #include<reg51.h>//定义8051头文件,引入reg52.h sbit PB1=P2^0;//声明PB1接至P2.0sbit LED=P1^0;//声明LED接至P1.0void debouncer(void);//声明防弹跳函数//==主程序===================================== main()//主程式开始{ LED=1;//关闭LEDPB1=1;//规划P2.0为输入埠while(1)//无穷循环,程序一直跑{ if (PB1==0)//若按下PB1{ debouncer();//呼叫防弹跳函数(按下时)LED=!LED;//切换LED为反相while(PB1 != 1);//若仍按住PB1,继续等debouncer();//呼叫防弹跳函数(放开时)}//if叙述结束}//while循环结束}//主程序结束//==子程序=====================================/* 防弹跳函数函数,延迟约20ms */void debouncer(void)//防弹跳函数开始{ int i;//声明整数变数ifor(i=0;i<2400;i++);//计数2400次,延迟约20ms}//防弹跳函数结束思考一下!在本实验里,改变debouncer函数的时间长短,看看有什么影响?若按住PB1不放会怎样?如何改善?按钮开关应用电路图流程图代码如下:/* 按钮开关应用(两按钮控制七段显示器上下数) *///==声明区==========================================#include<reg51.h>//定义8051头文件,引入reg52.h文件#define SEG P0//定义七节显示器接至P0端口/* 声明七节显示器驱动信号阵列(共阳) */char codeTAB[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x83,0xf8,0x80,0x98};//数字0-9sbit PB1=P2^0;//声明按钮1接至P2.0sbit PB2=P2^1;//声明按钮2接至P2.1void debouncer(void);//声明防弹跳函数//==主程式=================================main()//主程序开始{ unsigned char i=0;//声明变量i初值=0PB1=PB2=1;//规划输入端口SEG=TAB[i];//输出数字至七段显示器while(1)//无穷循环,程式一直跑{ if (PB1==0)//判断PB1是否按下{ debouncer();//呼叫防弹跳函数i= (i<9)? i+1:0;//若i<9则i=i+1,若i>=9清除为0SEG=TAB[i]; //输出数字至七段显示器while(PB1==0); //PB1是否按住?debouncer(); //呼叫防弹跳函数}//if叙述结束if (PB2==0)//判断PB2是否按下{ debouncer();//呼叫防弹跳函数i= (i>0)? i-1:9;//若i>0则i=i-1,i<=0重设为9SEG=TAB[i];//输出数字至七段显示器while(PB2==0);//PB1是否按住?debouncer();//呼叫防弹跳函数}//if叙述结束}//while循环结束}//主程序结束//==子程序==================================/* 防弹跳函数函数,延迟约20ms */void debouncer(void)//防弹跳函数开始{ int i;//声明整数变量ifor(i=0;i<2400;i++);//计数2400次,延迟约20ms}//防弹跳函数结束思考一下!在本实验里,若按钮按住不放,会怎样?如何改善?在本实验里,若PB1与PB2两个按钮同时按,会怎样?BCD数字型拨码开关实验BCD数字型拨码开关实验电路图流程图实验代码:/* BCD数字型指拨开关实验*///==声明区======================================#include<reg51.h>//定义8051头文件,引入reg52.h文件#define SEG P0//定义七节显示器接至P0#define SW P2//定义开关接至P2/* 声明七节显示器驱动信号阵列(共阳) */char codeTAB[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x83,0xf8,0x80,0x98};//数字0-9#define SW_H() SW&0x0f//读取开关值(P2清除高4bits)//==主程序======================================main()//主程序开始{ SW=0xff;//规划输入埠while(1)//无穷循环,程序一直跑SEG=TAB[SW_H()];//读取开关值,输出至七节显示器(P0)}//主程序结束思考一下!在本实验里,有没有“抖动”的困扰?若把本单元的BCD数字型拨码开关,改为16进位数字型拨码开关,程序应如何修改?多重按钮开关实验多重按钮开关实验电路图流程图实验中的自编库函数/* myio.h自己写的程序库*///==声明区============================== #define LED P1//定义LED接至P1void debouncer(void);//声明防弹跳函数void delay10ms(int);//声明10毫秒延迟函数void alter(int);//声明交互闪烁函数void left(int);//声明单灯左移函数void right(int);//声明单灯右移函数void pili(int); //声明霹雳灯函数void flash(int);//声明闪烁函数//==自己写的子程序========================/* 防弹跳函数函数,延迟约20ms */void debouncer(void)//防弹跳函数开始{ delay10ms(2);//延迟约20ms}//防弹跳函数结束/* 延迟函数开始,延迟约x 10ms */void delay10ms(int x)//延迟函数开始{ int i,j;//声明整数变量i,jfor (i=0;i<x;i++)//计数x次,延迟约x 10msfor (j=0;j<1200;j++);//计数1200次,延迟约10ms }//延迟函数结束/* 高低位元交互闪烁函数,执行x次*/void alter(int x)//高低位元交互闪烁函数开始{ int i;//声明变量iLED=0x0f;//初始状态(高位元亮,低位元灭)for(i=0;i<2*x-1;i++)//i变量for循环执行2x-1次{ delay10ms(50);//延迟50*10m=0.5sLED=~LED;//LED反相输出}//i变量for循环结束delay10ms(50);//延迟50 10m=0.5s}//高低位元交互闪烁函数结束/* 全灯闪烁函数,执行x次*/void flash(int x)//全灯闪烁函数开始{ int i;//声明变量iLED=0x00;//初始状态(全亮)for(i=0;i<2*x-1;i++)//i变量for循环执行2x-1次{ delay10ms(50);//延迟50 10m=0.5sLED=~LED;//P0反相输出}//i变量for循环结束delay10ms(50);//延迟50 10m=0.5s}//全灯闪烁函数结束/* 单灯左移函数,执行x圈*/void left(int x)//单灯左移函数开始{ int i, j;//声明变量i,jfor(i=0;i<x;i++)//i循环,执行x圈{ LED=0xfe;//初始状态=1111 1110for(j=0;j<7;j++)//j循环,左移7次{ delay10ms(25);//延迟25 10m=0.25sLED=(LED<<1)|0x01;//左移1位後,LSB设为1 }//j循环结束delay10ms(25);//延迟25 10m=0.25s}//i循环结束*/}//单灯左移函数结束/* 单灯右移函数,执行x圈*/void right(int x)//单灯右移函数开始{ int i, j;//声明变量i,jfor(i=0;i<x;i++)//i循环,执行x圈{ LED=0X7f;//初始状态=0111 1111for(j=0;j<7;j++)//j循环,右移7次{ delay10ms(25);//延迟25 10m=0.25sLED=(LED>>1)|0x80;//左移1位後,MSB设为1 }//j循环结束delay10ms(25);//延迟25 10m=0.25s}//i循环结束}//单灯左移函数结束/* 霹雳灯函数,执行x圈*/void pili(int x)//霹雳灯函数开始{ int i;//声明变量ifor(i=0;i<x;i++)//i循环,执行x圈{ left(1);//单灯左移一圈right(1);//单灯左移一圈}//i循环结束}//霹雳灯函数结束多重按钮开关实验之一:代码/* 多重按钮开关实验之1 *///==声明区================================#include<reg52.h>//定义8051头文件,引入reg52.h文件#include"myio.h"//自己写的I/O程序库sbit PB1=P2^0;//声明PB1=P2.0sbit PB2=P2^1;//声明PB2=P2.1sbit PB3=P2^2;//声明PB3=P2.2sbit PB4=P2^3;//声明PB4=P2.3//==主程序================================ main()//主程序开始{ LED=0xff;//初始状态(LED全灭)P2=0xff;//规划P2输入端口while(1)//无穷循环,程序一直跑{ if (PB1==0)//如果按下PB1{ debouncer();//防弹跳alter(3);//高低位元交互闪烁三次flash(3);}//全灯闪烁三次else if (PB2==0)//如果按下PB2{ debouncer();//防弹跳left(3);//单灯左移三圈flash(3);}//全灯闪烁三次else if (PB3==0)//如果按下PB3{ debouncer();//防弹跳right(3);//单灯右移三圈flash(3);}//全灯闪烁三次else if (PB4==0)//如果按下PB4{ debouncer();//防弹跳pili(3);//霹雳灯三圈flash(3);}//全灯闪烁三次}//while循环结束}//主程序结束思考一下!在本实验里,若同时按下多个按钮会如何?在本实验里,若按住按钮不放会如何?在本实验里,其中debouncer函数是个延迟20毫秒的函数,而delay10ms函数是个延迟10毫秒的函数,可否使用delay10ms 函数取代debouncer函数?如何修改?在本实验里,其中alter函数是个高四位与低四位交替闪烁的函数,而flash函数是个8灯闪烁的函数,其不同在于其初始值。
消抖电路
原因分析
绝大多数按键都是机械式开关结构, 绝大多数按键都是机械式开关结构,由于机械式开关的核心 部件为弹性金属簧片, 部件为弹性金属簧片,因而在开关切换的瞬间会在接触点出现 来回弹跳的现象。虽然只是进行了一次按键, 来回弹跳的现象。虽然只是进行了一次按键,结果在按键信号 稳定的前后出现了多个脉冲,如图1所示 所示。 稳定的前后出现了多个脉冲,如图 所示。如果将这样的信号直 接送给微处理器扫描采集的话, 接送给微处理器扫描采集的话,将可能把按键稳定前后出现的 脉冲信号当作按键信号, 脉冲信号当作按键信号,这就出现人为的一次按键但微处理器 以为多次按键现象。为了确保按键识别的准确性, 以为多次按键现象。为了确保按键识别的准确性,在按键信号 抖动的情况下不能进入状态输入, 抖动的情况下不能进入状态输入,为此就必须对按键进行消抖 处理,消除抖动时不稳定、随机的电压信号。 处理,消除抖动时不稳定、随机的电压信号。机械式按键的抖 动次数、抖动时间、抖动波形都是随机的。 动次数、抖动时间、抖动波形都是随机的。不同类型的按键其 最长抖动时间也有差别, 最长抖动时间也有差别,抖动时间的长短和按键的机械特性有 一般为5~ 关,一般为 ~10 ms,但是,有些按键的抖动时间可达到 ,但是,有些按键的抖动时间可达到20 ms,甚至更长。所以,在具体设计中要具体分析,根据实际情 ,甚至更长。所以,在具体设计中要具体分析, 况来调整设计。 况来调资料)
FPGA中用到的消抖(参考课本)
vhdl中的按键消抖电路设计原理
•
按键消抖的关键是提取稳定的低电平(或高电平)状态, 滤除按键稳定前后的抖动脉冲。在用基于VHDL语言的时 序逻辑电路设计按键消抖电路时,可以用一个时钟脉冲信 号对按键状态进行取样,当第一次采样到低电平时,启动 延时电路,延时结束后,再对按键信号进行连续三次取样, 如果三次取样都为低电平,则可以认为按键已经处在稳定 状态,这时输出一个低电平的按键确认信号,如果连续三 次的取样中,至少有一次是高电平,则认为按键仍处在抖 动状态,此时不进行按键确认,按键输出信号为高电平。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验报告课程名称:_____FPGA实验______指导老师:__竺红卫/陈宏__成绩:__________________实验名称:____拨动开关的消抖电路的设计___实验类型:_FPGA实验_同组学生姓名:__一、实验目的和要求(必填)1. 熟悉软件对于消抖的实现原理;2. 熟悉实验板拨动开关的工作方法。
二、实验内容和原理(必填)实验板具有4个滑动开关,当开关关上或上拉时,FPGA的管脚连接3.3V电源,即逻辑高电平。
断开或下拉时,FPGA管脚接地,逻辑低电平。
一般开关的机械闭合时间为2ms,这里没有使用活动的回弹线路,尽管这种线路可以很容易地加到FPGA上。
实验需要实现的功能是:当RESET为低电平,不论SW为低电平或高电平,LED保持全灭;当RESET 为高电平,LED全亮;当RESET保持高电平时,每次SW由高电平变为低电平,对应的LED状态改变,而当SW由低电平变为高电平,对应的LED状态保持不变。
对LED引脚输出高电平时,LED点亮,,反之LED灭。
三、主要仪器设备(必填)1. 电脑一台;2. 实验板一块,Xilinx Spartan-3E;3. 实验板电源一只;4. 实验板连接电脑的下载线一根。
四、操作方法和实验步骤对于程序的各个步骤,如新建项目、新建Verilog HDL、新建.ucf文件、Synthesize、Implement Design、Generate Programming File、Configure Target Device等等,在实验一中已经展示过,每一次实验的基本操作步骤都是差不多的,故这里不再重复阐述。
本次实验共有5个源代码需要编写、运行并解释:1)未加debounce电路的源代码;2)加了debounce电路的源代码;3)由未加debounce电路的源代码出发,只添加锁存器的源代码;4)由未加debounce电路的源代码出发,只添加滤波器的源代码;5)加了debounce电路,并且一个开关控制3个灯,向上拨动开关时灭,向下亮的源代码。
前四种情况的.ucf文件如下:NET "CLK" LOC="C9";NET "led_d3" LOC="C11";NET "led_d4" LOC="F11";NET "led_d5" LOC="E11";NET "RST_N" LOC="L13";NET "sw1" LOC="L14";NET "sw2" LOC="H18";NET "sw3" LOC="N17";最后一种情况的.ucf文件如下:NET "CLK" LOC="C9";NET "led_d3" LOC="C11";NET "led_d4" LOC="F11";NET "led_d5" LOC="E11";NET "RST_N" LOC="L13";NET "sw1" LOC="L14";对于最后一种情况,只使用sw1同时控制板上的LD2、LD3、LD4。
五、实验源代码、现象和解释1)未加debounce电路源代码:`timescale 1ns/1nsmodule sw_led(clk, rst_n, sw1, sw2, sw3, led_d3, led_d4, led_d5);input clk;input rst_n;input sw1,sw2,sw3; //低电平有效output led_d3;output led_d4;output led_d5;reg d1,d2,d3;always @ (posedge clk or negedge rst_n)if ( !rst_n )begin d1 <= 1'b0;d2 <= 1'b0;d3 <= 1'b0;endelsebeginif ( !sw1 ) d1 <= ~d1;if ( !sw2 ) d2 <= ~d2;if ( !sw3 ) d3 <= ~d3;endassign led_d5 = d1 ? 1'b1 : 1'b0;assign led_d3 = d2 ? 1'b1 : 1'b0;assign led_d4 = d3 ? 1'b1 : 1'b0;endmodule实验现象:当RESET关闭,不论SW状态如何,LED始终保持灭。
当RESET打开,LED立即全亮,此时再拨动SW,当SW向下拨,LED半亮,当SW向上拨,LED为全亮或全灭,出现两种状态的概率大致相同。
解释:当SW为低电平时,LED在以50MHz的频率闪烁,故表现为半亮;当SW向上拨,LED跟随拨动动作立即停止翻转,故LED为全亮或全灭,且两种状态概率相等。
2)加了debounce电路源代码:`timescale 1ns/1nsmodule sw_debounce(clk, rst_n, sw1, sw2, sw3, led_d3, led_d4, led_d5);input clk;input rst_n;input sw1,sw2,sw3; //低电平有效output led_d3;output led_d4;output led_d5;// ---------------------------------------------------------------------------// 通过降采样对sw1~sw3的输入做低通滤波,将其高频分量滤除,得到low_sw值// ---------------------------------------------------------------------------reg [19:0] cnt;always @ (posedge clk or negedge rst_n)if (!rst_n)cnt <= 20'd0;elsecnt <= cnt + 1'b1;reg [2:0] low_sw;always @(posedge clk or negedge rst_n)if (!rst_n)low_sw <= 3'b111;else if (cnt == 20'hfffff)low_sw <= {sw3,sw2,sw1};// ---------------------------------------------------------------------------// 以下的语句描述的是锁存器部分,将按键输入锁存一个周期后再与原输入信号进//行组合逻辑运算得到新的输入信号// ---------------------------------------------------------------------------reg [2:0] low_sw_r;always @ ( posedge clk or negedge rst_n )if (!rst_n)low_sw_r <= 3'b111;elselow_sw_r <= low_sw;wire [2:0] led_ctrl = low_sw_r[2:0] & ( ~low_sw[2:0]); //这里捕获的是下降沿!reg d1;reg d2;reg d3;always @ (posedge clk or negedge rst_n)if (!rst_n)begind1 <= 1'b0;d2 <= 1'b0;d3 <= 1'b0;endelsebeginif ( led_ctrl[0] ) d1 <= ~d1;if ( led_ctrl[1] ) d2 <= ~d2;if ( led_ctrl[2] ) d3 <= ~d3;endassign led_d5 = d1 ? 1'b1 : 1'b0;assign led_d3 = d2 ? 1'b1 : 1'b0;assign led_d4 = d3 ? 1'b1 : 1'b0;endmodule实验现象:能够完整实现要求的实验功能。
当RESET为低电平,不论SW为低电平或高电平,LED保持全灭;当RESET为高电平,LED全亮;当RESET保持高电平时,每次SW由高电平变为低电平,对应的LED 状态改变,而当SW由低电平变为高电平,对应的LED状态保持不变。
解释:加滤波器实现的功能是消除高频按键抖动对LED控制的影响;加锁存器实现的功能是使LED在SW 信号遇到下降沿时翻转。
3)由未加debounce电路的源代码出发,只添加锁存器源代码:`timescale 1ns/1nsmodule sw_debounce(clk, rst_n, sw1, sw2, sw3, led_d3, led_d4, led_d5);input clk;input rst_n;input sw1,sw2,sw3; //低电平有效output led_d3;output led_d4;output led_d5;reg [2:0] low_sw;always @(posedge clk or negedge rst_n)if (!rst_n)low_sw <= 3'b111;elselow_sw <= {sw3,sw2,sw1};// ---------------------------------------------------------------------------// 以下的语句描述的是锁存器部分,将按键输入锁存一个周期后再与原输入信号进//行组合逻辑运算得到新的输入信号// ---------------------------------------------------------------------------reg [2:0] low_sw_r;always @ ( posedge clk or negedge rst_n )if (!rst_n)low_sw_r <= 3'b111;elselow_sw_r <= low_sw;wire [2:0] led_ctrl = low_sw_r[2:0] & ( ~low_sw[2:0]); //这里捕获的是下降沿!reg d1;reg d2;reg d3;always @ (posedge clk or negedge rst_n)if (!rst_n)begind1 <= 1'b0;d2 <= 1'b0;d3 <= 1'b0;endelsebeginif ( led_ctrl[0] ) d1 <= ~d1;if ( led_ctrl[1] ) d2 <= ~d2;if ( led_ctrl[2] ) d3 <= ~d3;endassign led_d5 = d1 ? 1'b1 : 1'b0;assign led_d3 = d2 ? 1'b1 : 1'b0;assign led_d4 = d3 ? 1'b1 : 1'b0;endmodule实验现象:当RESET关闭时,LED始终全灭。