Advanced Item (11) matrix keyboard programming to explain

EDITORIAL words

When using keys, if the keys much, we can directly buttons and FPGA connected, but if the keys more time, if it continues to be used directly to make buttons and FPGA connected to the case, will be a substantial increase in consumption of FPGA ports in order to reduce the consumption of FPGA port, we can key designed in the form of a matrix. Next, the dream-wing brothers and everyone will learn the principles and the drive scanning circuit mode the keyboard.

Project requirements

Design 4 * 4 matrix keyboard key scanning module , the correct parse key value .

Principle matrix keyboard

Can be known from the figure, the matrix rows of the keyboard row (row) and col (column) of intersection are connected by a key. The traditional method of a port of a button, to achieve the 16 keys, you need 16 ports, and now this matrix design of the keyboard, 16 keys, requires only eight ports, 16 ports to do if you use a keyboard matrix, then , 64 keys can be identified, port utilization is much better than traditional designs, if so desired small button, you can select a traditional button design, if desired, then more keys, the keyboard can be employed such a matrix design. And we are now in a scanning method as an example to introduce the principle of matrix keyboard.

First col (column) to an FPGA matrix keyboard scanning signal output, the row (row) matrix keyboard is fed back to the FPGA input signal, for detecting which key is pressed, a schematic diagram is as follows:

 As shown, FPGA given scan signal COL [3: 0], COL = 4'b0111, wait for the next clock cycle COL = 4'b1011, and then wait for the next clock cycle COL = 4'b1101, and then the next and so on clock cycle COL = 4'b1110, and then wait for the next clock cycle COL = 4'b0111, COL is such a continuous cycle, to a matrix keyboard scanning signal is active low, when the FPGA to a matrix keyboard scanning signal is simultaneously COL, FPGA also a feedback signal ROW to the FPGA in a detection matrix of the keyboard, for example, if the matrix 9 keyboard keys are pressed:

When COL = 4'b0111, ROW = 4'b1111;

When COL = 4'b1011, ROW = 4'b1111;

When COL = 4'b1101, ROW = 4'b1011;

When COL = 4'b1110, ROW = 4'b1111;

Someone asked, why, when COL = 4'b1101 time, ROW = 4'b1011 it? We are now in a matrix keyboard circuitry to analyze this reason, as shown above:

9 when key is pressed, the key circuit 9 will be turned on, COL scanning circuit starts scanning when the scanning COL [. 1], because of the key 9, the circuit is turned on, COL [ voltage 1] is equal to the ROW [2] of the voltage, so there will be time when COL = 4'b1101 ROW = 4'b1011 (frequency sweep signal is probably about 1K).

Typically the key switch is a mechanical switch elasticity, when the mechanical contacts open, is closed, since the spring action of a mechanical contact, a key switch is not turned on immediately stably when closed, will not look upon opening son off. Thus at the moment and closed off all accompanied by a series of shake measures in order not to produce this phenomenon do is key debounce.

Jitter is determined by the length of time the key mechanical properties, generally 5ms ~ 10ms. This is a very important time parameters should be used on many occasions. Closing the length of time the key is stabilization is determined by the key operation of an operator, typically a few tenths to a few seconds (usually the key press time is greater than 20ms) . Key jitter causes a key is misread many times. To ensure that the CPU primary key for closing only one process, the key must be removed jitter. Reads the status of the key when the key is closed stable, and must be stable before the release button is determined to be processed.

Then we can use these phenomena to identify key design a circuit.

Architecture design

According to the principle analysis, we design the architecture is as follows:

 

Module Features

Module name

Functional Description

key_scan

Detecting the key value

Port Description top module

Port Name

Port Description

clk

System clock input

rst_n

System reset

row

Matrix keyboard row line

data

Key value

flag

Key value is valid (spikes)

col

Matrix keyboard column lines

 

 Code explanation

Key_scan module code

/****************************************************          

 * Engineer:    Dream Brother Wing

 *   QQ             :   761664056

 Of The function Module1 * : detected values of the key matrix of the keyboard

*****************************************************/

000 module key_scan (

CLK 001 ,  // system clock input

Rst_n 002 ,  // system reset

Row 003 , // keyboard matrix row lines

In Flag 004 , // output value valid flag (spikes)

Data 005 , // key value

006 col // keyboard matrix column lines

007                 );

008 // system input

009      INPUT  CLK ; // system clock input

010      INPUT  RST_N ; // reset

011      INPUT  [ . 3 : 0 ]  Row ; // row line matrix keyboard

012 // system output

013      Output  REG  In Flag ; // output value valid flag (spikes)

014      Output  REG  [ . 3 : 0 ]  Data ; // key value

015     output reg [3:0] col;//矩阵键盘的列线

016

017     reg clk_1K;//1K的时钟

018     reg [20:0] count;//计数器

019     

020     always @ (posedge clk or negedge rst_n)

021         begin

022             if (!rst_n)

023                 begin

024                     clk_1K <= 1;

025                     count <= 0;

026                 end

027             else

028                 if (count < 24999) // 50000分频,得出1K的时钟

029                     count <= count + 1;

030                 else

031                     begin

032                         count <= 0;

033                         clk_1K <= ~clk_1K;

034                     end

035         end

036         

037     reg [4:0] cnt_time;//按键按下的时间

038     reg [1:0] state;//状态寄存器

039     reg [7:0] row_col;//按键对应的行列值

040     

041     always @ (posedge clk_1K or negedge rst_n)

042         begin

043             if (!rst_n)//复位时,将中间寄存器和输出置0

044                 begin

045                     flag <= 0;

046                     state <= 0;

047                     cnt_time <= 0;

048                     row_col <= 0;

049                     col <= 4'b0000;

050                 end

051             else

052                 begin

053                     case (state)

054                     0 : begin

055                        if (row != 4'b1111)//当有按键按下时,开始计数,只有

056                             begin    //一直按下20ms才会被当做有效的按键

057                                 if (cnt_time < 19)

058                                     cnt_time <= cnt_time + 1;

059                                 else

060                                      begin

061                                          cnt_time <= 0;

062                                          state <= 1;

063                                           col <= 4'b1110;//扫描的初始值

064                                       end

065                                     end

066                                 else

067                                     cnt_time <= 0;

068                             end

069                         

070                         1 : begin

071                                 if (row!=4'b1111)

072                                     begin

073                                         row_col <= {row,col};//当检测出来时,把行列线的值存起来

074                                         flag <= 1;  //拉高有效标志

075                                         state <= 2;

076                                         col <= 4'b0000;//用于判断按键是否抬起来

077                                     end

078                                 else

079                                     begin

080                                         col <= {col[2:0],col[3]};//没有检测出来时,换成下一列

081                                     end                              //扫描

082                             end

083                             

084                         2 : begin

085                                 if (row == 4'b1111)//当按键释放20ms以后才会被当做释放

086                                     begin  //跳转到0状态进行新的按键值的检测

087                                         if (cnt_time < 19)

088                                             begin

089                                                 cnt_time <= cnt_time + 1;

090                                                 flag <= 0;

091                                             end

092                                         else

093                                             begin

094                                                 cnt_time <= 0;

095                                                 state <= 0;

096                                                 col <= 4'b0000;

097                                             end

098                                     end

099                                 else

100                                     begin

101                                         cnt_time <= 0;

102                                         flag <= 0;

103                                     end

104                             end

105                             

106                         default : state <= 0;

107                     endcase 

108                 end

109         end

110

111     always @ (*)

112         begin

113             if(!rst_n)

114                 begin

115                     data =0;

116                 end

117             else

118                 begin

119                     case(row_col)

120                         8'b1110_1110: data =0; 

121                         8'b1110_1101: data =1; //每一个按键的位置被行线和列线唯一确定

122                         8'b1110_1011: data =2; //根据行线和列线的值给出对应的按键值

123                         8'b1110_0111: data =3; 

124                         8'b1101_1110: data =4; 

125                         8'b1101_1101: data =5; 

126                         8'b1101_1011: data =6; 

127                         8'b1101_0111: data =7; 

128                         8'b1011_1110: data =8; 

129                         8'b1011_1101: data =9; 

130                         8'b1011_1011: data =10;

131                         8'b1011_0111: data =11;

132                         8'b0111_1110: data =12;

133                         8'b0111_1101: data =13;

134                         8'b0111_1011: data =14;

135                         8'b0111_0111: data =15;

136                         default : data = 0;             

137                     endcase

138                 end

139         end 

140         

141 endmodule 

 

测试代码

/****************************************************          

 *   Engineer      :   梦翼师兄

 *   QQ             :   761664056

 *   The module function:矩阵键盘测试代码

*****************************************************/

000 `timescale 1ns/1ps

001

002 module key_scan_tb;

003 //系统输入

004 reg clk;//系统时钟输入

005 reg rst_n;//系统复位

006 reg [3:0] row;//矩阵键盘的行线

007 //系统输出

008 wire flag;//输出值有效标志(尖峰脉冲)

009 wire [3:0] data;//按键值

010 wire [3:0] col;//矩阵键盘的列线

011

012 initial

013 begin

014 clk=0;

015 rst_n=0;

016 # 1000.1 rst_n=1;

017 end

018

019 always #10 clk=~clk;//50M的时钟

020

021 reg [4:0] pnumber;//按键值

022

023 initial

024 begin

025 pnumber=16;//无按键按下

026 # 6000000 pnumber=1;

027 # 3000000 pnumber=16;

028 # 6000000 pnumber=1;

029 # 3000000 pnumber=16;

030 # 6000000 pnumber=1;//模仿了一段抖动

031 # 3000000 pnumber=16;

032 # 6000000 pnumber=1;

033 # 3000000 pnumber=16;

034 # 6000000 pnumber=1;

035 # 21000000

036  pnumber=1;//按键“1”按下了21ms

037 # 3000000 pnumber=16;

038 # 6000000 pnumber=1;

039 # 3000000 pnumber=16;

040 # 6000000 pnumber=1;//模仿释放时的抖动

041 # 3000000 pnumber=16;

042 # 6000000 pnumber=1;

043 # 3000000 pnumber=16;

044 # 6000000 pnumber=1;

045 # 3000000 pnumber=16;

046 # 60000000 

047  pnumber=2;

048 # 3000000 pnumber=16;

049 # 6000000 pnumber=2;

050 # 3000000 pnumber=16;

051 # 6000000 pnumber=2;

052 # 3000000 pnumber=16;//按下时的抖动

053 # 6000000 pnumber=2;

054 # 21000000

055  pnumber=2;//按下21ms

056 # 3000000 pnumber=16;

057 # 6000000 pnumber=2;

058 # 3000000 pnumber=16;

059 # 6000000 pnumber=2;

060 # 3000000 pnumber=16;//释放时的抖动

061 # 6000000 pnumber=2;

062 # 3000000 pnumber=16;

063 # 6000000 pnumber=2;

064 # 3000000 pnumber=16;

065 end

066

067 //当有按键按下时,行线和列线的变化

068 always @(*)

069 case (pnumber)

070 0:    row = {1'b1,1'b1,1'b1,col[0]};  

071 1:    row = {1'b1,1'b1,1'b1,col[1]};

072 2:    row = {1'b1,1'b1,1'b1,col[2]};

073 3:    row = {1'b1,1'b1,1'b1,col[3]};

074 4:    row = {1'b1,1'b1,col[0],1'b1}; 

075 5:    row = {1'b1,1'b1,col[1],1'b1};

076 6:    row = {1'b1,1'b1,col[2],1'b1};

077 7:    row = {1'b1,1'b1,col[3],1'b1};

078 8:    row = {1'b1,col[0],1'b1,1'b1}; 

079 9:    row = {1'b1,col[1],1'b1,1'b1};

080 10:   row = {1'b1,col[2],1'b1,1'b1};

081 11:   row = {1'b1,col[3],1'b1,1'b1};

082 12:   row = {col[0],1'b1,1'b1,1'b1}; 

083 13:   row = {col[1],1'b1,1'b1,1'b1};

084 14:   row = {col[2],1'b1,1'b1,1'b1};

085 15:   row = {col[3],1'b1,1'b1,1'b1}; 

086 16:   row = 4'b1111;

087    default:   row = 4'b1111;

088    endcase

089

090 //实例化key_scan模块

091  key_scan key_scan (

092 .clk(clk), //系统时钟输入

093 .rst_n(rst_n), //系统复位

094 .row(row),//矩阵键盘的行线

095 .flag(flag),//输出值有效标志(尖峰脉冲)

096 .data(data),//按键值

097 .col(col)//矩阵键盘的列线

098 );

099

100 endmodule

在测试模块的中的68行至88行,描述了矩阵键盘的响应方式。假如:“5”被按下,“5”处在row[1]col[1]的位置,只有当col[1]低电平时,row[1]才能检测到低电平,并且row=4’b1101唯一确定了按键的位置。

在测试中,模拟了数字“1”以及数字“2”按下以及释放时的抖动。

仿真分析

从波形中,我们可以看出:按键稳定前,pnumber有一段抖动,稳定之后,data变成了按键值,释放时pnumber又有一段抖动,两段抖动data都没有发生改变。

 

 

 

Guess you like

Origin www.cnblogs.com/mengyi1989/p/11521086.html