|
FPGA学习真在进行中,有很多值得分享的东西!
按键的检测与消抖是处理非编码键盘必须考虑的一部分。
在单片机中主要通过延时来消抖,通过while循环不断读
端口,确保键盘被松开。但是这样会影响系统的效率。
在FPGA中键盘的消抖与检测主要通过“脉冲边缘检测法”
进行消抖和读数据。
具体原理如下:不停的读取端口,假设读取的序列为:按下表示为0,没有按下就是1。
将数据存入另一个寄存器。根据数电知识,存入数据会存在一个时钟的移动。
原寄存器: 1111 1111 1111 1110 1110 1110 1111 1111
新存入寄存器: 1111 1111 1111 1110 1110 1110 1111 1111
对原寄存器取反:0000 0000 0000 0001 0001 0001 0000 0000
将新寄存器与取反以后的寄存器进行按位与:
0000 0000 0001 0000 0000 0000 0000
1就说明了有按键按下,在检测是还可以用于判断哪个键被按下。
这样按键的检测到的时间是一按下就会检测到,而不是松开时。同时不会出现松开过程的干扰。
这样就会看见这样在按键以后存在一个脉冲,也就是1,那个1可以表示有按键被按下,而且是在按下的瞬间就能检测到。
这样延时20ms左右再次用同样的方法检测确定那个键被按下。
这样也就实现了键盘的消抖和检测,不会每次都检测,只有有检测到有按键按下的脉冲才会判断哪个键被按下。
注意的是:新存入寄存器的数据是原寄存器上个时钟的数值(寄存器的基本原理)
取反电路时组合电路,不会出现时延:因此出现上面的序列表。即取反的值与原寄存器值对齐。
具体的Veilog HDL实现有:
reg [3:0] key_press;
//用于存放和读取按键的值,设置为reg可以写又可以读。key_press相当于原寄存器
always@(posedge clk or negedge rst_n)
if(!rst_n)
key_press <= 4'b1111;//复位
else
key_press <={sw4_n,sw3_n,sw2_n,sw1_n};
reg[3:0] key_press_r;
//每个时钟周期的上升沿将low_sw信号锁存到low_press_r中,low_press_r相当于新寄存器
always@(posedge clk or negedge rst_n)
if(!rst_n)
low_press_r <= 4'b1111;
else
key_press_r <= key_press;
wire[3:0] key_pressed = key_press_r & (~key_press);//实现检测是否有键按下,同时可以实现哪个键被按下。
最后一句代码,关键要注意两个寄存其中的时序关系。
但是这个方法,只能检测对于按下为低电平的电路,对于按下为高电平的,不能实现,因为只能在松开过程检测到有按键按下。
|
|