完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
//说明:按键消抖实验
//当三个独立按键的某一位被按下后,相应的Led被点亮; //再次按下后,LED熄灭,按键控制LED亮灭;// // module key_handle( clk_20M,rst_n, sw1_n,sw2_n,sw3_n, led_d1,led_d2,led_d3 ); input clk_20M; //主时钟信号,20MHz input rst_n;//复位信号,低电平有效 input sw1_n,sw2_n,sw3_n;// 三个独立按键,低表示被按下 output led_d1,led_d2,led_d3;//发光二极管,分别由按键控制 //------------------------NOTE:两个寄存器不要放在一个always语句里面--------------------------------------- reg[2:0] key_rst; //对后面20ms计数器的一个复位的操作 always @(posedge clk_20M 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; //每个时钟周期的上升沿将上次锁存的按键值key_rst锁存到key_rst_r中 always @(posedge clk_20M 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; assign key_an = key_rst_r & (~key_rst); //边沿检测技术 /*下面表示的一个按键的状态 key_rst 1 1 1 0 0 1 //按键从1变为0 ~key_rst 0 0 0 1 1 0 key_rst_r 1 1 1 0 0 1 key_an 0 0 1 0 0 //key_an会变为1,且高电平保持一个时钟周期 */ //------------------------------------------------------- reg [19:0] cnt;//cnt用来计数20ms 2^20~=20ms;按键按下的时间差不多为20ms always @(posedge clk_20M or negedge rst_n) if(!rst_n) cnt <= 20'd0; else if(key_an) cnt <= 20'd0;//如果检测到有键按下,那么就将计数器清0,从新开始计数 else cnt <= cnt + 1'b1; reg[2:0] low_sw; always @(posedge clk_20M or negedge rst_n) if(!rst_n) low_sw <= 3'b111; else if (cnt == 20'hfffff) // 每20ms将按键值锁存到寄存器low_sw中 low_sw <= {sw3_n,sw2_n,sw1_n}; //这里存的值是稳定的(下一个脉冲的某一个时刻) //这个值是滤除抖动后的稳定值 //----------------------------------------------------------- reg [2:0] low_sw_r; always @(posedge clk_20M or negedge rst_n) if(!rst_n) low_sw_r <= 3'b111; else low_sw_r <= low_sw; //每一个时钟采集一次low_sw的状态值 //每个时钟周期的上升沿将low_sw信号锁存到low_sw_r中 /*low_sw 111 111 111 110 110 110 ~low_sw 000 000 000 001 001 001 low_sw_r 111 111 111 110 110 110 led_sw_r 000 000 001 000 000 */ // 当寄存器low_sw由1变为0时,led_ctrl的值变为高,维持一个时钟周期 wire[2:0] led_ctrl = low_sw_r[2:0] & (~low_sw[2:0]); // -------------------------------------------------------- reg d1; reg d2; reg d3; always @(posedge clk_20M or negedge rst_n) if(!rst_n) begin d1 <= 1'b0; d2 <= 1'b0; d3 <= 1'b0; end else begin ////某个按键值变化时,LED将做亮灭翻转 if(led_ctrl[0]) d1<=~d1; if(led_ctrl[1]) d2<=~d2; if(led_ctrl[2]) d3<=~d3; end assign led_d3 = d1 ? 1'b1:1'b0; //LED翻转输出 assign led_d2 = d2 ? 1'b1:1'b0; assign led_d1 = d3 ? 1'b1:1'b0; endmodule 这是特权同学的程序代码,基本上我都能搞清楚是什么意思,low_sw是存放按键稳定后的按键值;心里老感觉模模糊糊的;就我自己理解的,首先用key_an来标志是否有键按下。有键按下,cnt计数器清零,这个键不管是正常按下还是抖动,计数20ms以后都应该是稳定的值low_sw;我不理解的地方就是第二个边沿检测是用来做什么的;按键消抖从软件上实现应该就是检测到按键按下后,一段时间20ms后再检测应该是稳定的;也就实现了这个功能,大家觉得我理解的对不对? |
|
相关推荐
9个回答
|
|
是的,可以这样理解~
|
|
|
|
|
|
|
|
|
|
|
|
最讨厌看那些没有一点注释的程序。。。。。。
|
|
|
|
|
|
|
|
|
|
|
|
来确认按下之后是稳定的状态啊
|
|
|
|
你觉得如果是理想的按键(也就是完全没有抖动),你要不要做边沿检测?要吧,第二个边沿检测就是用来干这个的。
|
|
|
|
第一个应该是分频,第二个是双寄存器防亚稳态
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
764 浏览 0 评论
矩阵4x4个按键,如何把识别结果按编号01-16(十进制)显示在两个七段数码管上?
974 浏览 0 评论
863 浏览 0 评论
1849 浏览 0 评论
474 浏览 0 评论
1275 浏览 28 评论
5465 浏览 113 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-8 19:33 , Processed in 0.739339 second(s), Total 86, Slave 69 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号