ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

按键消抖实验

2022-04-20 20:34:54  阅读:223  来源: 互联网

标签:begin wire 消抖 spi 实验 cnt1 按键 rst reg


当按键被按下在到被释放,期间产生的输入信号会发生抖动,如果不进行消抖处理,直接使用可能就会误触发。

按键消抖实验设计思路,当按键被按下,隔20ms取数据,也就是说20ms的前后各取一次数据进行边沿检测:

(1)、需要一个计数器cnt,因为按键随时都可能会被按下,所以计数器需一直启动在计数,需一直在检测。

 1 always @(posedge clk or negedge rst_n)begin
 2     if(!rst_n)begin
 3         cnt <= 0;
 4     end
 5     else if(add_cnt)begin
 6         if(end_cnt)begin
 7             cnt <= 0;
 8         end
 9         else begin
10             cnt <= cnt + 1;
11         end
12     end
13 end
14 
15 assign add_cnt = 1;
16 assign end_cnt = add_cnt && cnt == T_20MS -1 || key_en;

(2)、需要一个边沿检测器,需要对输入pin 上的信号进行边沿检测,检测到下降沿之后,立刻马上将计数器cnt 清0 ,cnt从0开始计数,数到20ms 取一次数据

 1 always @(posedge clk or negedge rst_n)begin
 2     if(!rst_n)begin
 3         key_rst <= 1;
 4         key_rst_r <= 1;
 5     end
 6     else begin
 7         key_rst <= wr_en;
 8         key_rst_r <= key_rst;
 9     end
10 end
11 //当key_en = 1时,说明有检测到下降沿,但这个并不能当做一个真正有效的信号去启动cnt0,
12 //在按键按下到释放期间可能会多次产生key_en = 1
13 assign key_en = key_rst_r & (~key_rst); 
 1 //每隔20ms就取按键上的值    
 2 always @(posedge clk or negedge rst_n)begin
 3     if(!rst_n) begin
 4         pin_status <= 1;
 5     end
 6     else if(end_cnt) begin //隔20ms 取一次数据
 7         pin_status <= wr_en;
 8     end
 9 end
10 
11 always @(posedge clk or negedge rst_n)begin
12     if(!rst_n)begin 
13         pin_status_r <= 1;
14     end
15     else begin
16         pin_status_r <= pin_status;
17     end
18 end
19 
20 //前20MS的值与后20MS的值
21 assign pin_status_ctrl = pin_status_r & (~pin_status);//这个信号才比较稳定信号,可以当做启动计数器cnt0

完整代码:该代码是基于spi flash 一个读ID操作

  1 module spi_flash(
  2                     clk,
  3                     rst_n,
  4                     wr_en,
  5                     spi_miso,
  6                     
  7                     spi_sclk,
  8                     spi_mosi,
  9                     spi_cs,
 10                     rec_buf
 11 );
 12 parameter         SCLK_CLK = 3'd04;
 13 parameter         T_20MS      = 20'd1_000_000;
 14 parameter        CMD_ID     = 8'h9f;
 15 
 16 input            clk        ;
 17 input            rst_n    ;
 18 input            wr_en    ;
 19 input            spi_miso;
 20 
 21 output            spi_sclk;
 22 output            spi_mosi;
 23 output            spi_cs    ;
 24 output[24-1:0]    rec_buf    ;
 25 
 26 wire             add_cnt0;
 27 wire            end_cnt0;
 28 wire             add_cnt1;
 29 wire            end_cnt1;
 30 wire             add_cnt/*synthesis keep=1*/;
 31 wire            end_cnt/*synthesis keep=1*/;
 32 wire             key_en/*synthesis keep=1*/;
 33 
 34 wire            key_h_2_l;
 35 wire              pin_status_ctrl/*synthesis keep=1*/;
 36 
 37 reg[3-1:0]        cnt0;
 38 reg[6-1:0]        cnt1;
 39 reg[20-1:0]     cnt/*synthesis preserve=1*/;
 40 reg             wr_vld;
 41 reg             key_rst;
 42 reg             key_rst_r;
 43 reg             pin_status;
 44 reg             pin_status_r;
 45 
 46 
 47 /************************************************/
 48 //按键消抖动
 49 always @(posedge clk or negedge rst_n)begin
 50     if(!rst_n)begin
 51         key_rst <= 1;
 52         key_rst_r <= 1;
 53     end
 54     else begin
 55         key_rst <= wr_en;
 56         key_rst_r <= key_rst;
 57     end
 58 end
 59 
 60 assign key_en = key_rst_r & (~key_rst);
 61 
 62 //每隔20ms就取按键上的值    
 63 always @(posedge clk or negedge rst_n)begin
 64     if(!rst_n) begin
 65         pin_status <= 1;
 66     end
 67     else if(end_cnt) begin
 68         pin_status <= wr_en;
 69     end
 70 end
 71 
 72 always @(posedge clk or negedge rst_n)begin
 73     if(!rst_n)begin 
 74         pin_status_r <= 1;
 75     end
 76     else begin
 77         pin_status_r <= pin_status;
 78     end
 79 end
 80 
 81 //前20MS的值与后20MS的值
 82 assign pin_status_ctrl = pin_status_r & (~pin_status);
 83 
 84 always @(posedge clk or negedge rst_n)begin
 85     if(!rst_n)begin
 86         cnt <= 0;
 87     end
 88     else if(add_cnt)begin
 89         if(end_cnt)begin
 90             cnt <= 0;
 91         end
 92         else begin
 93             cnt <= cnt + 1;
 94         end
 95     end
 96 end
 97 
 98 assign add_cnt = 1;
 99 assign end_cnt = add_cnt && cnt == T_20MS -1 || key_en;
100 
101 
102 always @(posedge clk or negedge rst_n)begin
103     if(!rst_n)begin
104         wr_vld <= 0;
105     end
106     else if(pin_status_ctrl)begin
107         wr_vld <= 1;
108     end
109     else if(end_cnt1)begin
110         wr_vld <= 0;
111     end
112 end
113 
114 always @(posedge clk or negedge rst_n)begin
115     if(!rst_n)begin
116         cnt0 <= 0;
117     end
118     else if(add_cnt0)begin
119         if(end_cnt0)begin
120             cnt0 <= 0;
121         end
122         else begin
123             cnt0 <= cnt0 + 1;
124         end
125     end
126 end
127 
128 assign add_cnt0 = wr_vld;
129 assign end_cnt0 = add_cnt0 && cnt0 == SCLK_CLK -1;
130 
131 always @(posedge clk or negedge rst_n)begin
132     if(!rst_n)begin
133         cnt1 <= 0;
134     end
135     else if(add_cnt1)begin
136         if(end_cnt1)begin
137             cnt1 <= 0;
138         end
139         else begin
140             cnt1 <= cnt1 + 1;
141         end
142     end
143 end
144 
145 assign add_cnt1 = end_cnt0;
146 assign end_cnt1 = add_cnt1 && cnt1 == 33 -1;
147 
148 reg spi_sclk;
149 always @(posedge clk or negedge rst_n)begin
150     if(!rst_n)begin
151         spi_sclk <= 1;
152     end
153     else if(end_cnt0 && cnt1 != 32)begin
154         spi_sclk <= 0;
155     end
156     else if(add_cnt0 && cnt0 == ((SCLK_CLK>>1) -1))begin
157         spi_sclk <= 1;
158     end
159 end
160 
161 reg spi_cs;
162 always @(posedge clk or negedge rst_n)begin
163     if(!rst_n)begin
164         spi_cs <= 1;
165     end
166     else if(add_cnt0 && cnt0 == ((SCLK_CLK>>1) -1) && cnt1 == 0)begin
167         spi_cs <= 0;
168     end
169     else if(end_cnt1)begin
170         spi_cs <= 1;
171     end
172 end
173 
174 reg spi_mosi;
175 always @(posedge clk or negedge rst_n)begin
176     if(!rst_n)begin
177         spi_mosi <= 1;
178     end
179     else if(end_cnt0 && cnt1 >= 0 && cnt1 < 8)begin
180         spi_mosi <= CMD_ID[7-cnt1];
181     end
182 end
183 
184 reg[24-1:0] rec_buf_temp;
185 always @(posedge clk or negedge rst_n)begin
186     if(!rst_n)begin
187         rec_buf_temp <= 0;
188     end
189     else if(add_cnt0 && cnt0 == ((SCLK_CLK>>1)-1) && cnt1 >= 9 && cnt1 < 33)begin
190         rec_buf_temp[32-cnt1] <= spi_miso;
191     end
192 end
193 
194 reg dout_vld;
195 always @(posedge clk or negedge rst_n)begin
196     if(!rst_n)begin
197         dout_vld <= 0;
198     end
199     else begin
200         dout_vld <= end_cnt1;
201     end
202 end
203 
204 reg[24-1:0] rec_buf;
205 always @(posedge clk or negedge rst_n)begin
206     if(!rst_n)begin
207         rec_buf <= 0;
208     end
209     else if(end_cnt1)begin
210         rec_buf <= rec_buf_temp;
211     end
212 end
213 
214 endmodule 
View Code

用quartus II 的SignalTab抓取的波形:

 

如果pin_status_ctl 检测到多次,可以将间隔时间适当的加长点。一般的轻触按键20~50ms。

触发条件可以多开几个窗口进行捕获观察 。

 

标签:begin,wire,消抖,spi,实验,cnt1,按键,rst,reg
来源: https://www.cnblogs.com/wen2376/p/16171571.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有