矩阵键盘接口

矩阵键盘又叫行列式键盘。用带IO口的线组成行列结构,按键设置在行列的交点上。例如用4×4的行列式结构可以构成16个键的键盘。这样,当按键数量平方增长时,I/O口只是线性增长,这样就可以节省I/O口。矩阵键盘的原理图如图1.1所示:

        

                          图1.1 矩阵键盘的原理图

  按键设置在行列线交叉点,行列线分别连接到按键开关的两端。列线通过上拉电阻接3.3V电压,即列线的输出被钳位到高电平状态。
  判断键盘中有无按键按下式通过行线送入扫描线好然后从列线读取状态得到的。其方法是依次给行线送低电平,检查列线的输入。如果列线全是高电平,则代表低电平信号所在的行中无按键按下;如果列线有输入为低电平,则代表低电平信号所在的行和出现低电平的列的交点处有按键按下。
 
1.由于使用的外部时钟频率为50MHz,这个频率对扫描来说太高,所以这里需要一个分频器来分得适合键盘扫描使用的频率。可以看出,我们经过分频得到50HZ的时钟,是为下一模块键盘扫描提供的时钟,之所以是50HZ,而不是其他的数值,是因为,人在按键的时候,其停留时间大概是20ms左右,键盘扫描时,会发送固定的数值码,本例中是循环的发送4种数值,下面会提及到,50HZ转化为时间是0.02S=20ms。
 
 module scan_clk ( clkout ,clk ,rst );
     
 input rst ;
 input clk ;

 
 output clkout ;
 
 reg clkout_r ; 
 
 parameter  period= 200000;    

 reg [31:0] cnt;  
 
 always @( posedge clk or negedge rst)                  //分频50Hz
     begin 
         if ( !rst )
         begin
             cnt <= 32'b0; 
             clkout_r <= 0 ;    
             end        
         else begin 
             cnt<= cnt+1;
         if (cnt  == (period >> 1) - 1)                   //设定周期时间的一半
                 clkout_r <=1'b1;
         else if (cnt == period - 1)                    //设定的周期时间
             begin 
                 clkout_r <= 1'b0;
                  cnt <=  1'b0;      
             end

         end
      end
 assign clkout = clkout_r ;    
     
 endmodule
2.键盘扫描
  键盘扫描电路是用于产生keydrv3~ keydrv0 信号,其变化顺序是1110→1101→1011→0111→1110…周而复始地扫描。其停留时间大慨在20ms。更短的时间没有必要,因为人为按键的时间大慨为20ms,不可能产生有更快的动作;另外,更短的停留时间还容易采集到抖动信号,会干扰判断。而太长的时间容易丢失某些较快的按键动作
 
 module key_scan ( clk ,keydrv ,rst );
 
 input clk ;    
 input rst ;

 
 output [3:0] keydrv ;
  
 parameter s1 = 4'b1110;
 parameter s2 = 4'b1101;
 parameter s3 = 4'b1011;
 parameter s4 = 4'b0111;     
 
 reg [3:0]current_state;
 reg [3:0]next_state;
 
 always @ ( posedge clk or negedge rst )
     
     begin 
         if ( !rst )
             current_state <= s1    ;
         else    current_state <= next_state       ;
         end
         
 always      @ ( current_state )
     begin
         case  ( current_state )
             s1: next_state <=s2;     
             s2: next_state <=s3;
             s3: next_state <=s4;
             s4: next_state <=s1;
             default:  next_state <=s1;
     endcase
     end
     
 assign    keydrv =  current_state      ;
     
 endmodule
3.键译码转换。键盘译码电路是从keydrv3~keydrv0和keyin3~keyin0信号中译码出按键值的电路。clk是全局时钟,由外部晶振提供。clk在系统的频率是最高的,其他的时钟由分频产生。Keydrv表示键盘扫描信号,keyin为键盘输入信号,keyvalue为键值
     
 module top ( KEYO ,KEYI ,clk ,Y , rst);
 
 input    [3:0]    KEYO ;               //与原理图一致,是键盘输出端口给FPGA
 input            clk ;
 input            rst ;
 
 output    [3:0]    KEYI ;                //与原理图一致,是FPGA输出给 键盘    
 output    [7:0]    Y ;
 
     
 reg        [7:0]    temp_r ;
 reg        [7:0]    Y_r;   
 reg        [4:0]    keyvalue ; 
     
 reg        [3:0]    scankey_o;    
 reg        [3:0]    scankey_i;
 reg                dis_pre;    
 
 assign dis = &KEYO ;
 
 scan_clk key_clk(      
     .clk ( clk),
     .clkout ( scanclk) ,
     .rst ( rst )
     ); 
 
 key_scan key_scan( 
     .clk ( scanclk ) ,
     .keydrv (keydrv) ,
     .rst ( rst )
     );
 
 always @ ( posedge clk or negedge rst ) begin
     if ( rst==1'b0 ) begin
         scankey_o <= 4'b0 ; 
         scankey_i <= 4'b0 ;
         dis_pre <= dis;
     end else if ( clk ==1'b1 ) begin 
         dis_pre <= dis;
         if ( (dis == 1'b0)&&(dis_pre==1'b1) )  begin
             scankey_o <= keydrv    ;  
             scankey_i <= KEYO ;
         end    
     end
 end
 
 assign  KEYI = keydrv;
 
 assign temp = {scankey_o,scankey_i};
 
 always @ ( posedge clk or negedge rst ) begin  
     if ( rst==1'b0 ) begin 
         temp_r <= 8'b0; 
     end else if ( clk == 1'b1 )
         temp_r <= temp ;
 end    
     
 always @( temp_r or rst ) begin  
     if ( rst==1'b0 ) begin                //译码输出
         keyvalue <= 5'b0; 
     end else
         case ( temp_r )    
             8'b0111_0111 :  keyvalue <= 5'hb;        //无用,仅作为复位
             8'b1110_1110 :  keyvalue <= 5'h7;                
             8'b1110_1101 :  keyvalue <= 5'h8;                 
             8'b1110_1011 :  keyvalue <= 5'h9;                
             8'b1101_1110 :  keyvalue <= 5'h4;                
             8'b1101_1101 :  keyvalue <= 5'h5;                
             8'b1101_1011 :  keyvalue <= 5'h6;                
             8'b1011_1110 :  keyvalue <= 5'h1;                
             8'b1011_1101 :  keyvalue <= 5'h2;                
             8'b1011_1011 :  keyvalue <= 5'h3;                
             8'b0111_1101 :  keyvalue <= 5'h0;                                 
             8'b0111_1011 :  keyvalue <= 5'b1_0001;    //小数点
             default:        keyvalue <= 5'h0;             
         endcase    
 end     
 
 always @(keyvalue or rst ) begin  
     if ( rst==1'b0 )            //译码输出
         Y_r <= 8'b0000_0000;    
     else begin
         Y_r =8'b0000_0000;
         case (keyvalue )
                 5'h0: Y_r = 8'b0011_1111;         // 0
                 5'h1: Y_r = 8'b0000_0110;         // 1
                 5'h2: Y_r = 8'b0101_1011;         // 2
                 5'h3: Y_r = 8'b0100_1111;         // 3
                 5'h4: Y_r = 8'b0110_0110;         // 4
                 5'h5: Y_r = 8'b0110_1101;         // 5
                 5'h6: Y_r = 8'b0111_1101;         // 6
                 5'h7: Y_r = 8'b0000_0111;         // 7
                 5'h8: Y_r = 8'b0111_1111;         // 8
                 5'h9: Y_r = 8'b0110_1111;         // 9
                 5'b1_0001: Y_r = 8'b1000_0000;     //.
                 default: Y_r = 8'b0000_0000;
         endcase
     end
 end
 
 assign Y =~Y_r;
 
 endmodule
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值