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',计数器状态保持。显见计数器处于状态0,人工不按键,则计数器保持状态0。
下图是N为7的波形仿真图。在计数器状态为0时,key_in有按键操作,计数器开始连续计数直到计数器状态为0;计数器状态为1-7时,key_in任何操作对计数器工作无影响,计数器在状态为1时,输出一个单脉冲,脉冲宽度为1个时钟周期。
该设计方法的特点是能很好消除按键抖动产生的连续脉冲,对按键时间没有要求,缺点是在计数器状态为0时,遇到干扰、噪音等时会有输出,从而产生误操作。
状态机型消抖电路
状态机型消抖电路采用有限状态机的设计方法来描述与实现,状态机有S0,S1,S2三种状态,在S0状态下key_out输出为低电平,并以clk时钟信号的频率采样按键输入信号,如果key_in='0',则保持在S0状态,并继续采样按键输入信号的状态,如果key_in='1',则转入S1状态;在S1状态下key_out输出仍为低电平,继续采样按键输入信号的状态,如果key_in='1',则转入S2状态,如果key_in='0'则转入S0状态;在S2状态下继续采样按键输入信号的状态,如果key_in='1',则保持在S2状态,key_out输出正脉冲,如果key_in='0',则转入S0状态,key_out输出低电平。
下图为状态机型消抖电路波形仿真图
硬件原理图
实验代码
计数器型消抖电路(一)程序:
/********************************版权声明************************************** ** 大西瓜团队 ** **----------------------------文件信息-------------------------- ** 文件名称: key.v ** 创建日期: ** 功能描述:按键控制led的亮灭 ** 硬件平台:大西瓜第三代开发板,http://daxiguafpga.taobao.com ** 版权声明:本代码属个人知识产权,本代码仅供交流学习. **---------------------------修改文件的相关信息---------------- ** 修改人: ** 修改日期: ** 修改内容: *******************************************************************************/ module key(clk,key,led); input clk,key;//按键与时钟输入 output led;
wire clk,key;
reg led; reg [2:0] clk_counter;//时钟计数 reg [14:0] div_counter;//分频计数 reg key_out; reg clk_div; always @(posedge clk) begin if(div_counter==15'd25000) begin clk_div<=~clk_div; div_counter<=15'd0; end else div_counter<=div_counter+15'd1; end
always @(posedge clk_div ) begin if(key==1'b0)//判断按键是否按下 begin if(clk_counter==3'b111)//计数到7 begin clk_counter<=3'b000; key_out<=1'b1; end else begin clk_counter<=clk_counter+1'b1; if(clk_counter==3'b110)//判断是否计到6 key_out<=1'b0; else key_out<=1'b1; end end else clk_counter<=3'b000; end always @(negedge key_out)//对消抖后的按键信号进行判断 begin if(!key_out)//判断按键是否按下 begin led<=~led;//led灯状态反转 end else led<=led; end endmodule |
状态机型消抖电路程序:
/********************************版权声明************************************** ** 大西瓜团队 ** **----------------------------文件信息-------------------------- ** 文件名称: key.v ** 创建日期: ** 功能描述:按键控制led的亮灭 ** 硬件平台:大西瓜第三代开发板,http://daxiguafpga.taobao.com ** 版权声明:本代码属个人知识产权,本代码仅供交流学习. **---------------------------修改文件的相关信息---------------- ** 修改人: ** 修改日期: ** 修改内容: *******************************************************************************/ module key(clk,led,key); input clk,key; output [7:0] led;
wire clk; wire key;
reg [7:0] led_temp; reg key_out; parameter s0=2'b00,s1=2'b01,s2=2'b10,s3=2'b11; reg [1:0] state;
always @(posedge clk) begin case (state) s0: begin key_out<=1'b1; if(key==1'b0) state<=s1; else state<=s0; end s1: begin if(key==1'b0) state<=s2; else state<=s0; end s2: begin if(key==1'b0) state<=s3; else state<=s0; end s3: begin if(key==1'b0) begin key_out<=1'b0; state<=s3; end else begin key_out<=1'b1; state<=s0; end end default: state<=s0; endcase end
always @(negedge key_out) begin if(!key_out)//判断按键是否按下 begin if(led_temp==8'b1111_1111) led_temp<=8'b0; else led_temp<=led_temp+1'b1; end end assign led=~led_temp; endmodule |
实验操作
实验效果
大西瓜FPGA-->https://daxiguafpga.taobao.com
配套开发板:https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-24211932856.3.489d7241aCjspB&id=633897209972
博客资料、代码、图片、文字等属大西瓜FPGA所有,切勿用于商业! 若引用资料、代码、图片、文字等等请注明出处,谢谢!
每日推送不同科技解读,原创深耕解读当下科技,敬请关注微信公众号"科乎"。