=====按键消抖=====
====硬件平台====
------
- [[STEP-MXO2第一代]]
====设计要求====
------
- 掌握FPGA边沿检测的设计
- 掌握按键消抖的原理
- 基于小脚丫[[STEP-MXO2第一代]]开发平台实现按键消抖的功能,实现脉冲和状态翻转输出。
====工作原理====
------
{{ :抖动原理.png |抖动原理}}
按键抖动的原理
- 抖动的产生 :通常的按键所用的开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖。
- 消除抖动的措施:在按键按下的时刻,会出现波形的抖动,在之后的一段时间内,才会出现平稳的波形。我们舍弃了刚刚检测到按键按下的时刻,读取这一时刻之后20ms左右的按键信息,这样可以防止一次按键被误读多次。
根据上面的原理描述,我们可以对按键的输入管脚进行边沿检测,当检测到输入信号变化后计数清零并开始计数,计数到20ms时进行采样,然后再对每次采样的值进行下降沿检测,检测的结果作为按键消抖的脉冲输出,然后每次检测到下降沿时让状态输出进行翻转并输出。
====硬件连接====
------
为了方便我们在硬件平台上更直观的观察,我们使用25MHz时钟晶振分频产生1Hz的信号作为序列检测的时钟,按键信号作为按键消抖的信号输入,LED灯LD1和LD2分别作为按键消抖的脉冲和状态输出指示。
{{ :按键硬件图.jpg |按键硬件图}}
{{ :led电路连接.jpg |LED电路连接}}
====代码设计====
----
{{ :按键消抖程序设计.jpg |按键消抖程序设计}}
如上图所示,我们首先进行边沿检测,边沿检测的方法是定义一个寄存器对输入信号进行锁存,然后将寄存器的数据与下一个时刻的输入信号做对比,如果两者不相等则认为输入信号在这个时间段发生了变化,产生了边沿,key_an产生高电平的脉冲。
reg key_rst;
//Register key_rst, lock key1_n to next clk
always @(posedge clk or negedge rst_n)
if (!rst_n) key_rst <= 1'b1;
else key_rst <=key1_n;
//Detect the edge of key1_n
wire key_an = (key_rst==key1_n)? 0:1;
当key_an产生脉冲时,计数器cnt清零并计数,因为我们要采集输入信号变化后20ms的状态值,系统时钟25MHz,计数器终值 = 25MHz/50 = 500000,所以计数器计数到500000时采样。
reg low_sw;
//Lock the status to register low_sw when cnt count to 19'd500000
always @(posedge clk or negedge rst_n)
if (!rst_n) low_sw <= 1'b1;
else if (cnt == 19'd500000)
low_sw <= key1_n;
然后对将采样寄存器low_sw的数据锁存至寄存器low_sw_r,然后检测下降沿(因为我们的硬件是按键时输出低电平,采用下降沿实时性更好一些)。
//Detect the negedge of low_sw, generate pulse
assign key_pulse= low_sw_r & ( ~low_sw);
引脚分配如下:
^ 管脚名称 | clk| rst_n | key_n | key_pulse |key_state |
^ FPGA管脚 | C1 | A2 | B7 | A3 |A7 |
====运行结果====
{{:img20160612165641.jpg?500 |按}}
{{:img20160612165704.jpg?500|再按}}
====资源报告====
^ 资源 | 数量 | 比例 | 说明 |
^ LUTs | 16 | 3% | |
^ 寄存器 | 23 | 1% | |
^ 存储器 | 0 | 0% | |
^ IO管脚 | 5 | | |
^ 时钟频率 | 25MHz | | |
====知识点====
* 按键消抖原理
* 边沿检测设计
====参考文档====
* [[点亮led灯]]
* {{:machxo2familydatasheet.pdf|Lattice MachXO2数据手册}}
====相关文档====
^ **文件名称** | **功能** |
^ **[[Debounce.v]]** | **按键消抖** |