矩阵键盘实验

  电路原理图如下:其中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    = 3‘d0;
 19 localparam                SCAN_JITTER1 = 3‘d1;
 20 localparam                SCAN_COL1    = 3‘d2;
 21 localparam                SCAN_COL2    = 3‘d3;
 22 localparam                SCAN_COL3    = 3‘d4;
 23 localparam                SCAN_COL4    = 3‘d5;
 24 localparam                SCAN_READ    = 3‘d6;
 25 localparam                SCAN_JITTER2 = 3‘d7;
 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 - 1‘b1)
 36         delay_cnt <= delay_cnt + 1‘b1;
 37     else
 38         delay_cnt <= 0;
 39 end
 40 wire delay_done = (delay_cnt == DELAY_TOP - 1‘b1) ? 1‘b1 : 1‘b0;
 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 != 4‘b1111)        next_state = SCAN_JITTER1;
 64         else                                 next_state = SCAN_IDLE;
 65     SCAN_JITTER1 :
 66         if(row_data != 4‘b1111)        next_state = SCAN_COL1;
 67         else                                 next_state = SCAN_IDLE;
 68     SCAN_COL1 :
 69         if(row_data != 4‘b1111)        next_state = SCAN_READ;
 70         else                                 next_state = SCAN_COL2;
 71     SCAN_COL2 :
 72         if(row_data != 4‘b1111)        next_state = SCAN_READ;
 73         else                                 next_state = SCAN_COL3;
 74     SCAN_COL3 :
 75         if(row_data != 4‘b1111)        next_state = SCAN_READ;
 76         else                                 next_state = SCAN_COL4;
 77     SCAN_COL4 :
 78         if(row_data != 4‘b1111)        next_state = SCAN_READ;
 79         else                                 next_state = SCAN_IDLE;
 80     SCAN_READ :
 81         if(row_data != 4‘b1111)        next_state = SCAN_JITTER2;
 82         else                                 next_state = SCAN_IDLE;
 83     SCAN_JITTER2 :
 84         if(row_data != 4‘b1111)        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   <= 4‘b0000;
 98         col_data_r <= 4‘b0000;
 99         row_data_r <= 4‘b0000;
100         end
101     else if(delay_done)
102         begin
103         case(next_state)
104         SCAN_IDLE    :
105             begin
106                 col_data   <= 4‘b0000;
107                 col_data_r <= col_data_r;
108                 row_data_r <= row_data_r;
109             end
110         //SCAN_JITTER1 :
111         SCAN_COL1    : col_data <= 4‘b0111;
112         SCAN_COL2    : col_data <= 4‘b1011;
113         SCAN_COL3    : col_data <= 4‘b1101;
114         SCAN_COL4    : col_data <= 4‘b1110;
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 == 1‘b1) ? 1‘b1 : 1‘b0;
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 == 1‘b1)
141         begin
142         case({row_data,col_data})
143             8‘b0111_0111 : key_value <= 4‘h0;
144             8‘b0111_1011 : key_value <= 4‘h1;
145             8‘b0111_1101 : key_value <= 4‘h2;
146             8‘b0111_1110 : key_value <= 4‘h3;
147
148             8‘b1011_0111 : key_value <= 4‘h4;
149             8‘b1011_1011 : key_value <= 4‘h5;
150             8‘b1011_1101 : key_value <= 4‘h6;
151             8‘b1011_1110 : key_value <= 4‘h7;
152
153             8‘b1101_0111 : key_value <= 4‘h8;
154             8‘b1101_1011 : key_value <= 4‘h9;
155             8‘b1101_1101 : key_value <= 4‘ha;
156             8‘b1101_1110 : key_value <= 4‘hb;
157
158             8‘b1110_0111 : key_value <= 4‘hc;
159             8‘b1110_1011 : key_value <= 4‘hd;
160             8‘b1110_1101 : key_value <= 4‘he;
161             8‘b1110_1110 : key_value <= 4‘hf;
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{1‘b0}};
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)?1‘b1:1‘b0;
238         end
239 end
240 //------------------------------
241 //74HC595 clk delay for enough setup time
242 // generate shift_flag and shift_clk
243 localparam                 DELAY_CNT = 3‘d7;
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 == 1‘b1)
251             delay_cnt <= (delay_cnt < DELAY_CNT) ? (delay_cnt+1‘b1):3‘d0;
252     else
253             delay_cnt <= 0;
254 end
255 wire shift_clk  = (delay_cnt  > DELAY_CNT/2) ? 1‘b1 : 1‘b0;
256 wire shift_flag = (delay_cnt == DELAY_CNT)   ? 1‘b1 : 1‘b0;
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 <= 1‘b1;
274                         else
275                             shift_state <= 0;
276                     end
277             1:        begin
278                         if(shift_flag)
279                             begin
280                                 if(led_cnt < 4‘d8)
281                                     begin
282                                     led_cnt <= led_cnt + 1‘b1;
283                                     shift_state <= 1‘d1;
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 < 4‘d8&&shift_state == 1‘b1) ? led_data[3‘d7-led_cnt]: 1‘b0;
301 assign led595_clk   = (led_cnt < 4‘d8&&shift_state == 1‘b1) ? shift_clk : 1‘b0;
302 assign led595_latch = (led_cnt ==4‘d8&&shift_state == 1‘b1) ? 1‘b1 : 1‘b0;
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            ({4‘d0,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
时间: 2024-10-03 00:01:41

矩阵键盘实验的相关文章

51单片机第四弹---矩阵键盘

原理图: 原理: 和独立键盘相似 /******************************************************************************* * 实 验 名 : 矩阵键盘实验 * 使用的IO : 数码管使用P0 矩阵键盘使用P3 * 实验效果 : 显示独立键盘的按键值 * 注 意 : *******************************************************************************/

4x4矩阵键盘扫描

4x4矩阵键盘扫描 Windows 10 IoT Core 是微软针对物联网市场的一个重要产品,与以往的Windows版本不同,是为物联网设备专门设计的,硬件也不仅仅限于x86架构,同时可以在ARM架构上运行. 上一章我们讲了 Win10 IoT 如何对本地 IoT 设备内嵌 SQLite 数据库进行 CURD 操作 ,这章我们来学习如何使用 GPIO Pin 扫描4x4矩阵键盘按键状态.如果对安装部署过程还不熟悉可以参考前几篇文章,Raspberry安装 IoT系统及搭建开发环境(http:/

Win10 IoT C#开发 6 - 4x4矩阵键盘扫描

Windows 10 IoT Core 是微软针对物联网市场的一个重要产品,与以往的Windows版本不同,是为物联网设备专门设计的,硬件也不仅仅限于x86架构,同时可以在ARM架构上运行. 上一章我们讲了 Win10 IoT 如何对本地 IoT 设备内嵌 SQLite 数据库进行 CURD 操作 ,这章我们来学习如何使用 GPIO Pin 扫描4x4矩阵键盘按键状态.如果对安装部署过程还不熟悉可以参考前几篇文章,Raspberry安装 IoT系统及搭建开发环境(http://www.cnblo

51、52单片机使用矩阵键盘

为了学习矩阵键盘,先做个小小的实验目标 : 按下矩阵键盘后 ,数码管显示按下的是第几键. 我的矩阵键盘是4X4的,操作原理是先检测按下的键是哪行.再确定是哪列.这样就能识别是按的哪个键了. 首先看电路图,确定键盘是连CPU的哪个针.我的开发板上是连接的P1,具体是P10~P17,八个针对应逻辑的8位. (此处省略,直接贴代码) #include<reg52.h>void delay(int n);void juzhen(void); char duanxuan[16]={0x3f,0x06,0

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

37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手试试做实验,不管成功与否,都会记录下来---小小的进步或是搞不定的问题,希望能够抛砖引玉. [Arduino]108种传感器模块系列实验(资料+代码+图形+仿真) 实验二十六:4X4矩阵键盘模块(轻触式按键) 矩阵键盘 是单片机外部设备中所使用的排布类似于矩阵的键盘组.矩阵式结构的键盘显

STM32 4x4矩阵键盘

可同时识别两个键值,并分别显示,用了自己的12864显示,有些注释的地方有乱码请忽略.基于STM32f103vct6. 主函数: #include "Rect_key.h" #include "12864.h" int main() { u16 keynum=0; delay_init(); lcd_gpio_init(); lcd_init(); Rect_key_Init(); lcd_6x8(0,0,"STM32 4x4 KEY Test :&quo

疑问----单片机矩阵键盘行列反转扫描法

学到矩阵键盘这一块对网上别人写的C代码有些疑问,希望有能看到的大牛帮助解答. 矩阵键盘和独立键盘原理图: 原理:对于图右侧的矩阵键盘,把P3口的低四位(P3.0 ~ P3.3)和高四位(P3.4 ~ P3.7)分别置1,只要有按键被按下,那么与之对应的P3口某一位将由高电平被拉低,两次分别测得了行值和列值即确定了哪一个按键被按下了. 比如:先把低四位赋高电平即 P3 = 0000_1111 假如 S15 被按下了,那么 P3.2 就被拉成低电平即 P3 = 0000_1011 ,此时再把高四位赋

矩阵键盘 数码管

开始时数码管不显示,顺序按下矩阵键盘后,在数码管上依次显示0~F,6个数码管同时静态显示. 数码管和矩阵键盘 首先关闭所有的数码管的段选不让数码管显示任何数字,然后位选中所有的数码管,接下来只需要选中所有的数码管,以后的操作的只需要送段选数据就行了,接着进入while()大循环不停的扫描键盘是否有被按下 #include<reg52.h> #define uchar unsigned char #define uint unsigned int sbit dula=P2^6; sbit wel

单片机入门-矩阵键盘控制数码管显示

任务简述:通过按下4X4矩阵键盘实现数码管对应显示数字 实现方式:通过行列分接法,可以节省使用单片机的I/O口,扫描矩阵键盘是否有按下,判断P2端口得到的值. protues 硬件系统 单片机晶振复位电路: 锁存器.上拉电阻: 4x4矩阵键盘: 代码实现: void key44scan(void)//键盘扫描函数 { uint t; P2=0xfe; t=P2; t=t&0xf0; if(t!=0xf0) { delay(); t=P2; switch(t) { case 0xee:keynum