实际上本来不想写这个代码的,但是因为商家的代码摸不着头脑,所以只好自己重新实现了一番,一个基本的按键消抖程序,为了达到较好的标准效果还是折腾了很久的(几个小时,边看电影边写的🐸),最后效果还不错!
实际上看得懂按键消抖的基本原理,加上比较熟悉FPGA的编程语言Vrrilog HDL的语法结构之类的等,是很容易调试出来的,但是自己的实验过程中还是遇见了不少的小问题
实际上只要跳过前面的抖动部分,读取实际的电平即可(H/L),按键按下时这样实现,按键松开时也是一样的操作,目的就是确保电平的准确性,而“跳过”实际上就是检测一定延时后的电平状态
实际上说FPGA坑也不完全对,毕竟在时序这一块,它(非人!!!)有着极其严格的要求,时序对不上就极有可能结果出不来,所以有时候就需要Modelsim仿真
但是,在Quartus里面,使用Verilog HDL开发FPGA的话,一种实时捕捉机制(暂且可以这么说),对延时也好,电平检测也好,还是其他一些情况,相比于之前用的ARM(利用定时器实现延时)还是比较方便的
always@(posedge clk or negedge rst or ...)
begin
...
...
end
可以根据某一电平的变化(外部输入也好,变量赋值也好,模块调用输出也好等等),进行相应的响应,这一点至少我个人还是挺觉得不错的,在本次的按键消抖程序里面,多亏了这种方式(实际上ARM实现也挺方便,用定时器!!!)
now1_state <= keyio; if(now1_state==1'b0) begin posedge_true <= 1'b1; end else begin posedge_true <= 1'b0; end if(posedge_true==1'b1) begin if(time_cnt1==32'd150_0) begin time_cnt1 <= 32'd0; next1_state <= keyio; if(next1_state==1'b0) begin //logis = 1'b1; posedge_true_t <= 1'b1; end else begin //logis = 1'b0; end end else begin time_cnt1 = time_cnt1 + 32'd1; end end else begin time_cnt1 <= 32'd0; end
此段代码的逻辑设计,实际上已经很好的体现了,利用延时避开按键里面的抖动部分,而最后输出变量可供后续程序调用,进一步确定按键不但按下了,而且是按了一次(即按下后又松开,记为一次),不消抖的话单纯的检测电平跳变很可能将一次误认为多次,所以为何需要消抖就是这个原因
代码在上面(全部代码,但不是工程文件),有兴趣的话可以参考参考!!!
额,我这里的确认一次按下的检测方式应该是自创的了(滑稽),我的脑洞也许博友们不一定能理解,实际上之前说了,弄懂原理,完全可以自己实现
always@(posedge logis) begin /*** if(logis==1'b1) LED_0 <= 4'b1111; else LED_0 <= 4'b0000; ***/ if(cnt==4'd4) begin cnt = 4'd1; end else begin cnt = cnt + 4'd1; end case(cnt) 4'd1: LED_0 <= 4'b0001; 4'd2: LED_0 <= 4'b0010; 4'd3: LED_0 <= 4'b0100; 4'd4: LED_0 <= 4'b1000; default: LED_0 <= 4'b0000; endcase end
这里的电平检测方式,可以说是,非常好的,能够标准的,检测出,按键不断地按下的过程中的电平变化!!!稳定!稳定!真的稳定!
实际上在这之前,也就是实现要求的功能前,一步一步搭建底层的过程中,还是有不少意外的收获的,比如验证按键按下消抖程序的逻辑是完全正确的,进行过一些突发奇想的测试,方式都是自创的!🐸
if(time_cnt1==32'd150_0)
可以尝试修改后续常量,就会有以外的收获了🐸,可以验证按下的检测是否在朝自己的逻辑方向在跑,不需要仿真,能够直接从实物的情况下看出来!嗯,留待博友们自己思考了,代码放在我的Github端,有兴趣的可以下载看看
具体的实验现象可以点击下方的视频链接查看
https://www.bilibili.com/video/av69517493
推荐一款软件“FiF口语训练”
这款软件还是当初本科的时候纬纬老师推荐的,可惜,并没有发挥它的该有的口语训练作用,额,研究生又需要用得到了,缘分呐,真的是一种回忆!
好好学习,努力奋斗吧,骚年!!!