4*4矩阵键盘原理分析以及代码展示

简单介绍下矩阵键盘的原理:

矩阵键盘4个输入端口ROW[3:0] 接收由FPGA产生的键盘扫描输入信号,而4个输出COL[3:0] 将按键操作的信息变化输入到FPGA扫描分析电路,进而得到按键的操作码。

输入端口分别接了4个上拉电阻,当4个输入端口输入若都为1时,则有无论按哪个按键,输出都为1,所以 若刚开始的时候对四个输入端口赋0,则只要按下任何一个按键,键盘上的4个输出则肯定有1变为0,而且能够判断到是哪一列,但是并不知道是哪一行,所以此时就要用到键盘扫描,何为键盘扫描,就是只要让输入端口的一行为0,其余三行全为1,轮流扫描一遍,便可以方便的确定按键按下的准确值。

又因为实际运用的时候按键按下会有抖动现象,所以要对其进行消抖处理,消抖模块可以有很多种方法,例如状态机的消抖方法以及打拍延时,然后相或,因为这个是键值输入,若要用到打拍延时的方法进行消抖处理的话,需要对其进行一些改动,相或改为两两相等并相与 以增加时钟时间。

以下给出矩阵键盘实现的两种代码,其中一种参照赵然的书籍中提到的夏宇闻老师提供的代码。 这里用到了状态机模块进行消抖。                     

`define OK 1‘b1
`define NO 1‘b0
`define NoKeyIsPressed 17    

module keyscan0(clk,rst_n,keyscan,keyin,real_number);
 input clk,rst_n;
 input [3:0]keyin;
 output [3:0] keyscan;
 output [4:0] real_number;
 reg [3:0] state;
 reg [3:0] four_state;
 reg [3:0] scancode,scan_state;
 reg [4:0] numberout,number_reg,number_reg1,number_reg2, real_number;
 reg AnyKeyPressed;

 assign keyscan = scancode;

 always @(posedge clk or negedge rst_n)
 if (!rst_n)
      begin
        scancode <=4‘b0000;
        scan_state<= 4‘b0000;
      end
 else
     if(AnyKeyPressed)
        case (scan_state)
            4‘b0000: begin scancode<=4‘b1110; scan_state<= 4‘b0001; end
            4‘b0001: begin  scancode <= {scancode[0],scancode[3:1]}; end
        endcase
     else
        begin
            scancode <=4‘b0000;
            scan_state<= 4‘b0000;
        end  

 always @(posedge clk )
 if( !(&keyin))
    begin
     AnyKeyPressed <= `OK ;
     four_state <= 4‘b0000;
    end
 else
    if(AnyKeyPressed)
       case(four_state)
         4‘b0000: begin  AnyKeyPressed <= `OK ;  four_state<=4‘b0001; end
         4‘b0001: begin  AnyKeyPressed <= `OK ;  four_state<=4‘b0010; end
         4‘b0010: begin  AnyKeyPressed <= `OK ;  four_state<=4‘b0100; end
         4‘b0100: begin  AnyKeyPressed <= `OK ;  four_state<=4‘b1000; end
         4‘b1000: begin  AnyKeyPressed <= `NO ;   end
         default: AnyKeyPressed <= `NO ;
       endcase
    else
         four_state <= 4‘b0000;

always @(posedge clk or negedge rst_n)
   if(!rst_n)
        numberout<=`NoKeyIsPressed;
    else
  casex({scancode,keyin})
    8‘b0111_1110: numberout <= 5‘d10;
    8‘b1011_1110: numberout <= 5‘d3;
    8‘b1101_1110: numberout <= 5‘d2;
    8‘b1110_1110: numberout <= 5‘d1; 

    8‘b0111_1101: numberout <= 5‘d11;
    8‘b1011_1101: numberout <= 5‘d6;
    8‘b1101_1101: numberout <= 5‘d5;
    8‘b1110_1101: numberout <= 5‘d4; 

    8‘b0111_1011: numberout <= 5‘d12;
    8‘b1011_1011: numberout <= 5‘d9;
    8‘b1101_1011: numberout <= 5‘d8;
    8‘b1110_1011: numberout <= 5‘d7; 

    8‘b0111_0111: numberout <= 5‘d13;
    8‘b1011_0111: numberout <= 5‘d15;
    8‘b1101_0111: numberout <= 5‘d14;
    8‘b1110_0111: numberout <= 5‘d0;
    default: numberout <=`NoKeyIsPressed;
   endcase

always @(posedge clk or negedge rst_n)
begin
    if (!rst_n)
    begin
      number_reg <= 0;
    end
    else
        if( numberout<=5‘d15 && numberout>=5‘d0)
            begin
                 number_reg <= numberout;
            end
        else
            begin
                if(AnyKeyPressed == `NO)
                    number_reg <= `NoKeyIsPressed;
            end

 end

always @(posedge clk or negedge rst_n)
 if (!rst_n)
    state <= 4‘b0000;
 else
    case (state)
4‘d0: begin
            number_reg1 <= number_reg;
            state <=4‘d1;
        end
4‘d1: begin
            if(number_reg == number_reg1)
                state <= 4‘d2;
            else
                state <= 4‘d0;
        end
4‘d2: begin
            if (number_reg == number_reg1)
                state <= 4‘d3;
            else
                state <= 4‘d0;
        end
4‘d3: begin
            if (number_reg == number_reg1)
                state <= 4‘d4;
            else
                state <= 4‘d0;
        end
4‘d4: begin
             if(number_reg == number_reg1)
                state <=4‘d5;
             else
                state <= 4‘d0;
        end
4‘d5: begin
            if(number_reg == number_reg1)
                state <= 4‘d6;
            else
                state <= 4‘d0;
        end
4‘d6: begin
            if (number_reg == number_reg1)
                state <= 4‘d7;
            else
                state <= 4‘d0;
        end
4‘d7: begin
            if (number_reg == number_reg1)
                  state <= 4‘d8;
            else
                  state <= 4‘d0;
        end
4‘d8: begin
            if (number_reg == number_reg1)
                  state <=4‘d9;
            else
                  state <= 4‘d0;
        end
4‘d9: begin
            if(number_reg == number_reg1)
                  state <= 4‘d10;
            else
                  state <= 4‘d0;
        end
4‘d10: begin
            if (number_reg == number_reg1)
                  state <= 4‘d11;
            else
                 state <= 4‘d0;
        end
4‘d11: begin
            if (number_reg == number_reg1)
                 state <= 4‘d12;
            else
                 state <= 4‘d0;
        end
4‘d12: begin
            if(number_reg == number_reg1)
              state <= 4‘d13;
            else
              state <= 4‘d0;
        end
4‘d13: begin
            if (number_reg == number_reg1)
                  state <= 4‘d14;
            else
                 state <= 4‘d0;
        end
4‘d14: begin
            if (number_reg == number_reg1)
             state <= 4‘d15;
            else
             state <= 4‘d0;
        end
4‘d15: begin
            if (number_reg == number_reg1 )
                begin
                    state <= 4‘d0;
                    real_number <=number_reg;
                end
            else
                         state <= 4‘b0000;
        end
  default:   state <= 4‘b0000;
  endcase
endmodule

另一种:

module key_bd(
input CLK_1K,
input RSTN,
input [3:0]ROW,
output reg[3:0]COL,
output [3:0]real_num,
output flag_pos
//output reg[3:0]key_value,

//output reg[23:0]num_out
);

reg [3:0]state;
reg [3:0]four_state;
reg [3:0]key_value;
reg flag;

parameter NO = 6‘b000_001;
parameter S0 = 6‘b000_010;
parameter S1 = 6‘b000_100;
parameter S2 = 6‘b001_000;
parameter S3 = 6‘b010_000;
parameter YES= 6‘b100_000;

reg [5:0]CS,NS;
always@(posedge CLK_1K or negedge RSTN)
begin
if(~RSTN)
    CS <= NO;
else
    CS <= NS;
end

always@(*)
    case(CS)
    NO:if(ROW != 4‘hF)
            NS <= S0;
        else
            NS <= NO;
    S0:if(ROW != 4‘hF)
            NS <= YES;
        else
            NS <= S1;
    S1:if(ROW != 4‘hF)
            NS <= YES;
        else
            NS <= S2;
    S2:if(ROW != 4‘hF)
            NS <= YES;
        else
            NS <= S3;
    S3:if(ROW != 4‘hF)
            NS <= YES;
        else
            NS <= NO;
    YES:if(ROW != 4‘hF)
            NS <= YES;
        else
            NS <= NO;
    endcase

reg [3:0]ROW_val,COL_val;

always@(posedge CLK_1K or negedge RSTN)
begin
if(!RSTN)
    begin
    COL <= 0;
    flag <= 0;
    end
else
        case(NS)
            NO:begin
                COL <= 0;
                flag <= 0;
                end
            S0:begin
                COL <= 4‘b1110;
                end
            S1:begin
                COL <= 4‘b1101;
                end
            S2:begin
                COL <= 4‘b1011;
                end
            S3:begin
                COL <= 4‘b0111;
                end
            YES:begin
                COL_val <= COL;
                ROW_val <= ROW;
                flag <= 1;
                end
        endcase
end
/////////////////////////////////////////////////////////
reg flag_pre;
always@(posedge CLK_1K or negedge RSTN)
begin
    if(~RSTN)
        flag_pre <= 0;
    else
        flag_pre <= flag;
end

//assign flag_pos = (~flag_pre)&flag;
assign flag_pos = flag_pre & (~flag);
/////////////////////////////////////////////////////////
always@(posedge CLK_1K or negedge RSTN)
begin
    if(~RSTN)
        key_value <= 0;
    else
        if(flag)
        case({ROW_val,COL_val})
        8‘b1110_1110: key_value <= 4‘h1;
        8‘b1110_1101: key_value <= 4‘h2;
        8‘b1110_1011: key_value <= 4‘h3;
        8‘b1110_0111: key_value <= 4‘ha;

        8‘b1101_1110: key_value <= 4‘h4;
        8‘b1101_1101: key_value <= 4‘h5;
        8‘b1101_1011: key_value <= 4‘h6;
        8‘b1101_0111: key_value <= 4‘hb;

        8‘b1011_1110: key_value <= 4‘h7;
        8‘b1011_1101: key_value <= 4‘h8;
      8‘b1011_1011: key_value <= 4‘h9;
        8‘b1011_0111: key_value <= 4‘hc;

        8‘b0111_1110: key_value <= 4‘h0;
        8‘b0111_1101: key_value <= 4‘he;
        8‘b0111_1011: key_value <= 4‘hf;
        8‘b0111_0111: key_value <= 4‘hd;
        endcase
end

key_esk #(4) K1(
.CLK_1K(CLK_1K),
.key_in(key_value),
.key_out(real_num)
);

endmodule 
时间: 2024-10-03 20:32:50

4*4矩阵键盘原理分析以及代码展示的相关文章

朴素贝叶斯分类算法原理分析与代码实现

前言 本文介绍机器学习分类算法中的朴素贝叶斯分类算法并给出伪代码,Python代码实现. 词向量 朴素贝叶斯分类算法常常用于文档的分类,而且实践证明效果是挺不错的. 在说明原理之前,先介绍一个叫词向量的概念. --- 它一般是一个布尔类型的集合,该集合中每个元素都表示其对应的单词是否在文档中出现. 对应关系和词汇表一一对应. 比如说,词汇表只有三个单词:'apple', 'orange', 'melo',某文档中,apple和melo出现过,那么其对应的词向量就是 {1, 0, 1}. 这种模型

第五篇:朴素贝叶斯分类算法原理分析与代码实现

前言 本文介绍机器学习分类算法中的朴素贝叶斯分类算法并给出伪代码,Python代码实现. 词向量 朴素贝叶斯分类算法常常用于文档的分类,而且实践证明效果挺不错的. 在说明原理之前,先介绍一个叫词向量的概念. --- 它一般是一个布尔类型的集合,该集合中每个元素都表示其对应的单词是否在文档中出现. 比如说,词汇表只有三个单词:'apple', 'orange', 'melo',某文档中,apple和melo出现过,那么其对应的词向量就是 {1, 0, 1}. 这种模型通常称为词集模型,如果词向量元

nio原理分析与代码实现

io共性:每个线程的处理流程大概都是读取数据.解码.计算处理.编码.发送响应. 标准的IO基于字节流和字符流进行操作的, 而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中. Java NIO的通道类似流,但又有些不同: 既可以从通道中读取数据,又可以写数据到通道.但流的读写通常是单向的. 通道可以异步地读写. 通道中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入. 当线程从通道读取数据到缓冲区时,

第十四篇:Apriori 关联分析算法原理分析与代码实现

前言 想必大家都听过数据挖掘领域那个经典的故事 - "啤酒与尿布" 的故事. 那么,具体是怎么从海量销售信息中挖掘出啤酒和尿布之间的关系呢? 这就是关联分析所要完成的任务了. 本文将讲解关联分析领域中最为经典的Apriori算法,并给出具体的代码实现. 关联分析领域的一些概念 1. 频繁项集: 数据集中经常出现在一起的物品的集合.例如 "啤酒和尿布" 2. 关联规则: 指两个物品集之间可能存在很强的关系.例如 "{啤酒} -> {尿布}"

Apriori 关联分析算法原理分析与代码实现

前言 想必大家都听过数据挖掘领域那个经典的故事 - "啤酒与尿布" 的故事. 那么,具体是怎么从海量销售信息中挖掘出啤酒和尿布之间的关系呢? 这就是关联分析所要完成的任务了. 本文将讲解关联分析领域中最为经典的Apriori算法,并给出具体的代码实现. 关联分析领域的一些概念 1. 频繁项集: 数据集中经常出现在一起的物品的集合.例如 "啤酒和尿布" 2. 关联规则: 指两个物品集之间可能存在很强的关系.例如 "{啤酒} -> {尿布}"

ThreadLocal原理分析与代码验证

ThreadLocal提供了线程安全的数据存储和访问方式,利用不带key的get和set方法,居然能做到线程之间隔离,非常神奇. 比如 ThreadLocal<String> threadLocal = new ThreadLocal<>(); in thread 1 //in thread1 treadLocal.set("value1"); ..... //value的值是value1 String value = threadLocal.get(); in

K-Means 聚类算法原理分析与代码实现

前言 在前面的文章中,涉及到的机器学习算法均为监督学习算法. 所谓监督学习,就是有训练过程的学习.再确切点,就是有 "分类标签集" 的学习. 现在开始,将进入到非监督学习领域.从经典的聚类问题展开讨论.所谓聚类,就是事先并不知道具体分类方案的分类 (允许知道分类个数). 本文将介绍一个最为经典的聚类算法 - K-Means 聚类算法以及它的两种实现. 现实中的聚类分析问题 - 总统大选 假设 M 国又开始全民选举总统了,目前 Mr.OBM 的投票率为48%(投票数占所有选民人数的百分比

lesson5:Condition的原理分析及demo展示

Condition 将 Object 监视器方法(wait,notify,和notifyAll)分解成截然不同的对象,以便通过将这些对象与任意Lock实现组合使用,为每个对象提供多个等待 set(wait-set).其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用.每个condition都是与一个锁关联的,一个锁可以创造一个或多个condition. 关于condition的描述,参考资料:http://downloa

进阶项目(11) 矩阵键盘程序设计讲解

写在前面的话 在使用按键的时候,如果按键不多的话,我们可以直接让按键与FPGA相连接,但是如果按键比较多的时候,如果还继续使用直接让按键与FPGA相连接的话,会大量增加FPGA端口的消耗,为了减少FPGA端口的消耗,我们可以把按键设计成矩阵的形式.接下来,梦翼师兄将和大家一起学习扫描键盘的电路原理以及驱动方式. 项目需求 设计4*4矩阵键盘按键扫描模块,正确解析按键值. 矩阵键盘的原理 由上图可以知道,矩阵键盘的行row(行)与col(列)的交点,都是通过一个按键相连接.传统的一个按键一个端口的