1. 程式人生 > 資訊 >OPPO K7x、Reno3 5G 開啟 ColorOS 12×Android 12 升級公測招募

OPPO K7x、Reno3 5G 開啟 ColorOS 12×Android 12 升級公測招募

當按鍵被按下在到被釋放,期間產生的輸入訊號會發生抖動,如果不進行消抖處理,直接使用可能就會誤觸發。

按鍵消抖實驗設計思路,當按鍵被按下,隔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。

觸發條件可以多開幾個視窗進行捕獲觀察 。