矩阵键盘实验

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了矩阵键盘实验相关的知识,希望对你有一定的参考价值。

  电路原理图如下:其中ROW[3:0]为处理器输入,COL[3:0]为处理器输出

技术分享

 

  矩阵键盘实验代码一共包括四个部分:1.按键检测(matrix_key_scan) 2.读取数据(led_input_display) 3.74HC595显示(led_74595_driver) 4.顶层模块(KEY_Scan_Design)。整体RTL视图如下:

技术分享

  按键检测部分(matrix_key_scan)检测原理如下:

技术分享

  按键检测(matrix_key_scan)状态机如下:

技术分享

技术分享

技术分享
技术分享

  1 //=====================================================================================================================================================================================
  2 `timescale 1ns/1ns
  3 module matrix_key_scan
  4 (
  5     //global clk
  6     input                        clk,
  7     input                        rst_n,
  8 
  9     //matrix keyboard interface
 10     input            [3:0]        row_data,
 11     output reg    [3:0]        col_data,
 12 
 13     //user interface
 14     output reg                key_flag,
 15     output reg    [3:0]        key_value
 16 );
 17 
 18 localparam                SCAN_IDLE    = 3d0;
 19 localparam                SCAN_JITTER1 = 3d1;
 20 localparam                SCAN_COL1    = 3d2;
 21 localparam                SCAN_COL2    = 3d3;
 22 localparam                SCAN_COL3    = 3d4;
 23 localparam                SCAN_COL4    = 3d5;
 24 localparam                SCAN_READ    = 3d6;
 25 localparam                SCAN_JITTER2 = 3d7;
 26 
 27 //-------------------------------------------------
 28 //delay for 20ms
 29 localparam                DELAY_TOP    = 1000_000;
 30 reg         [19:0]        delay_cnt;
 31 always@(posedge clk or negedge rst_n)
 32 begin
 33     if(!rst_n)
 34         delay_cnt <= 0;
 35     else if(delay_cnt < DELAY_TOP - 1b1)
 36         delay_cnt <= delay_cnt + 1b1;
 37     else 
 38         delay_cnt <= 0;
 39 end 
 40 wire delay_done = (delay_cnt == DELAY_TOP - 1b1) ? 1b1 : 1b0;
 41 
 42 //-----------------------------------------------------
 43 //FSM always1
 44 reg        [2:0]            current_state;
 45 reg        [2:0]            next_state;
 46 always@(posedge clk or negedge rst_n)
 47 begin
 48     if(!rst_n)
 49         current_state <= SCAN_IDLE;
 50     else if(delay_done)
 51         current_state <= next_state;
 52     else
 53         current_state <= current_state;
 54 end 
 55 
 56 //---------------------------------------------------
 57 //FSM always2
 58 always@(*)
 59 begin
 60     next_state = SCAN_IDLE; //state initialization
 61     case(current_state)
 62     SCAN_IDLE    :
 63         if(row_data != 4b1111)        next_state = SCAN_JITTER1;
 64         else                                 next_state = SCAN_IDLE;
 65     SCAN_JITTER1 :
 66         if(row_data != 4b1111)        next_state = SCAN_COL1;
 67         else                                 next_state = SCAN_IDLE;
 68     SCAN_COL1 :
 69         if(row_data != 4b1111)        next_state = SCAN_READ;
 70         else                                 next_state = SCAN_COL2;
 71     SCAN_COL2 :
 72         if(row_data != 4b1111)        next_state = SCAN_READ;
 73         else                                 next_state = SCAN_COL3;
 74     SCAN_COL3 :
 75         if(row_data != 4b1111)        next_state = SCAN_READ;
 76         else                                 next_state = SCAN_COL4;
 77     SCAN_COL4 :
 78         if(row_data != 4b1111)        next_state = SCAN_READ;
 79         else                                 next_state = SCAN_IDLE;
 80     SCAN_READ :
 81         if(row_data != 4b1111)        next_state = SCAN_JITTER2;
 82         else                                 next_state = SCAN_IDLE;
 83     SCAN_JITTER2 :
 84         if(row_data != 4b1111)        next_state = SCAN_JITTER2;
 85         else                                 next_state = SCAN_IDLE;
 86     endcase 
 87 end
 88 
 89 //------------------------------------------------
 90 //FSM always3
 91 reg [3:0] col_data_r;
 92 reg [3:0] row_data_r;
 93 always@(posedge clk or negedge rst_n)
 94 begin
 95     if(!rst_n)
 96         begin 
 97         col_data   <= 4b0000;
 98         col_data_r <= 4b0000;
 99         row_data_r <= 4b0000;
100         end
101     else if(delay_done)
102         begin
103         case(next_state)
104         SCAN_IDLE    :
105             begin 
106                 col_data   <= 4b0000;
107                 col_data_r <= col_data_r;
108                 row_data_r <= row_data_r;
109             end
110         //SCAN_JITTER1 : 
111         SCAN_COL1    : col_data <= 4b0111;
112         SCAN_COL2    : col_data <= 4b1011;
113         SCAN_COL3    : col_data <= 4b1101;
114         SCAN_COL4    : col_data <= 4b1110;
115         SCAN_READ    : begin
116                             col_data_r <= col_data;
117                             row_data_r <= row_data;
118                             end
119                             
120         //SCAN_JITTER2 :
121         default      : ;
122         endcase
123         end 
124     else
125         begin
126             col_data   <= col_data;
127             col_data_r <= col_data_r;
128             row_data_r <= row_data_r;
129         end
130 end 
131 
132 //-------------------------------------
133 wire key_trigger = (current_state == SCAN_JITTER2 && next_state == SCAN_IDLE && delay_done == 1b1) ? 1b1 : 1b0;
134 //-------------------------------------
135 //decode the matrix keyboard
136 always@(posedge clk or negedge rst_n)
137 begin
138     if(!rst_n)
139         key_value <= 0;
140     else if(key_trigger == 1b1)
141         begin
142         case({row_data,col_data})
143             8b0111_0111 : key_value <= 4h0;
144             8b0111_1011 : key_value <= 4h1;
145             8b0111_1101 : key_value <= 4h2;
146             8b0111_1110 : key_value <= 4h3;
147             
148             8b1011_0111 : key_value <= 4h4;
149             8b1011_1011 : key_value <= 4h5;
150             8b1011_1101 : key_value <= 4h6;
151             8b1011_1110 : key_value <= 4h7;
152             
153             8b1101_0111 : key_value <= 4h8;
154             8b1101_1011 : key_value <= 4h9;
155             8b1101_1101 : key_value <= 4ha;
156             8b1101_1110 : key_value <= 4hb;
157             
158             8b1110_0111 : key_value <= 4hc;
159             8b1110_1011 : key_value <= 4hd;
160             8b1110_1101 : key_value <= 4he;
161             8b1110_1110 : key_value <= 4hf;
162             default      : key_value <= key_value;
163             endcase
164         end
165     else
166         key_value <= key_value;
167 end
168 
169 //-----------------------------------------
170 //read enable
171 always@(posedge clk or negedge rst_n)
172 begin
173     if(!rst_n)
174         key_flag <= 0;
175     else 
176         key_flag <= key_trigger;
177 end
178 
179 endmodule
180 //=========================================================================================================================================================================================
181 `timescale 1ns/1ns
182 module led_input_display
183 #(
184     parameter    LED_WIDTH = 8
185 )
186 (
187     input                                        clk,
188     input                                     rst_n,
189     input                                        led_en,
190     input                [LED_WIDTH-1:0]    led_value,
191 
192     output    reg    [LED_WIDTH-1:0]    led_data
193 
194 );
195 //-----------------------------
196 //led input with enable signal
197 always@(posedge clk or negedge rst_n)
198 begin
199     if(!rst_n)
200         led_data <= {LED_WIDTH{1b0}};
201     else if (led_en)
202         led_data <= led_value;
203     else 
204         led_data <= led_data;
205 end 
206 endmodule        
207 //=====================================================================================================================================================================================================
208 `timescale 1ns/1ns
209 module led_74595_driver
210 (
211     //global clock
212     input                clk,//50MHz
213     input             rst_n,
214     
215     //user led output
216     input    [7:0]    led_data,
217     
218     output            led595_clk,
219     output            led595_dout,
220     output            led595_latch
221 );
222 //-----------------------------
223 //update display when led_data is update
224 //generate led_data_r and  update_flag
225 reg        [7:0]            led_data_r;
226 reg                        update_flag;
227 always@(posedge clk or negedge rst_n)
228 begin
229     if(!rst_n)
230         begin
231             led_data_r  <= 0;
232             update_flag <= 1;
233         end 
234     else
235         begin 
236             led_data_r  <= led_data;
237             update_flag <= (led_data_r == led_data)?1b1:1b0;
238         end 
239 end 
240 //------------------------------
241 //74HC595 clk delay for enough setup time
242 // generate shift_flag and shift_clk
243 localparam                 DELAY_CNT = 3d7;
244 reg                        shift_state;
245 reg        [2:0]            delay_cnt;
246 always@(posedge clk or negedge rst_n)
247 begin
248     if(!rst_n)
249             delay_cnt <= 0;
250     else if(shift_state == 1b1) 
251             delay_cnt <= (delay_cnt < DELAY_CNT) ? (delay_cnt+1b1):3d0;
252     else 
253             delay_cnt <= 0;
254 end 
255 wire shift_clk  = (delay_cnt  > DELAY_CNT/2) ? 1b1 : 1b0;
256 wire shift_flag = (delay_cnt == DELAY_CNT)   ? 1b1 : 1b0;
257 //----------------------------------------
258 //74HC595 shift data output state
259 reg [3:0] led_cnt;
260 always@(posedge clk or negedge rst_n)
261 begin
262     if(!rst_n)
263         begin 
264             shift_state <= 0;
265             led_cnt <= 0;
266         end 
267     else
268         begin 
269             case(shift_state)
270             0:        begin
271                         led_cnt <= 0;
272                         if(update_flag)
273                             shift_state <= 1b1;
274                         else
275                             shift_state <= 0;
276                     end 
277             1:        begin
278                         if(shift_flag)
279                             begin
280                                 if(led_cnt < 4d8)
281                                     begin 
282                                     led_cnt <= led_cnt + 1b1;
283                                     shift_state <= 1d1;
284                                     end 
285                                 else
286                                     begin 
287                                     led_cnt <= 0;
288                                     shift_state <= 0;
289                                     end 
290                                 end
291                             else
292                                 begin 
293                                 led_cnt <= led_cnt;
294                                 shift_state <= shift_state;
295                                 end
296                     end
297             endcase 
298         end 
299 end 
300 assign led595_dout  = (led_cnt < 4d8&&shift_state == 1b1) ? led_data[3d7-led_cnt]: 1b0;
301 assign led595_clk   = (led_cnt < 4d8&&shift_state == 1b1) ? shift_clk : 1b0;
302 assign led595_latch = (led_cnt ==4d8&&shift_state == 1b1) ? 1b1 : 1b0;
303 
304 
305 endmodule
306 //====================================================================================================================================================================================================
307 `timescale 1ns/1ns
308 module KEY_Scan_Design
309 (
310     input                 clk,
311     input                    rst_n,
312     
313     //matrix keyboard interface
314     input            [3:0]        row_data,
315     output     [3:0]        col_data,
316     
317     output                 led595_clk,
318     output                led595_dout,
319     output                led595_latch
320 );
321 
322 //-------------------------------------
323 wire                        key_flag;
324 wire     [3:0]                key_value;
325  matrix_key_scan        u_matrix_key_scan
326 (
327     //global clk
328     .clk(clk),
329     .rst_n(rst_n),
330 
331     //matrix keyboard interface
332     .row_data(row_data),
333     .col_data(col_data),
334 
335     //user interface
336     .key_flag(key_flag),
337     .key_value(key_value)
338 );
339 
340 //------------------------------------------
341 wire         [7:0]            led_data;
342 led_input_display
343 #(
344     .LED_WIDTH (8)
345 )
346 u_led_input_display
347 (
348     .clk                    (clk), 
349     .rst_n                (rst_n),
350     .led_en                (key_flag),
351     
352     .led_value            ({4d0,key_value}),
353     
354     .led_data            (led_data)
355 );
356 
357 //-------------------------------------------
358 led_74595_driver    u_led_74595_driver
359 (
360     //global clock
361     .clk                    (clk),//50MHz
362     .rst_n                (rst_n),
363     
364     //user led output
365     .led_data            (led_data),
366     
367     .led595_clk            (led595_clk),
368     .led595_dout        (led595_dout),
369     .led595_latch        (led595_latch)
370 );
371 
372 endmodule

 

以上是关于矩阵键盘实验的主要内容,如果未能解决你的问题,请参考以下文章

「雕爷学编程」Arduino动手做(26)——4X4矩阵键盘模块

5152单片机使用矩阵键盘

单片机综合实验 - 04 | 键盘数码管与点阵管实验

扫描中矩阵需要多少

单片机实验3提示

单片机实验3提示