差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
后一修订版 两侧同时换到之后的修订记录
矩阵按键模块 [2017/05/24 17:24]
anran
矩阵按键模块 [2017/06/01 10:52]
anran [相关资料]
行 6: 行 6:
 ====硬件说明==== ====硬件说明====
 ------- -------
-STEP-MXO2 V2开发板虽然很小巧上面也集成外设,在本实验里我们就看看如何FPGA控制简单外设如何用按键或者开关控制LED+在键盘中按键数量较多时I/​O口的占用,通常将按键排列成矩阵形式,使行线和列线分别连接到按键开关的两端,这样我们就可以通过4根行线4根列线(共8个I/​O口)连接16个按键,而且按键数量越多优势越明显 
 + 
 +FPGA驱动矩阵按键模块,首先我们来了解矩阵按键的硬件连接:
 \\ \\
-{{ :led.png?600 |}}+{{ :矩阵按键.jpg?800 |}}
 \\ \\
-这是开发板上的8个红色LEDLED1~8信号连接到FPGA引脚作为FPGA输出信号控制当FPGA输出低电平LED变亮当FPGA输出电平时LED熄灭+图为4x4矩阵按键硬件电路图可以看到4根行线(ROW1、ROW2、ROW3、ROW4)和4根列线(COL1、COL2、COL3、COL4),同时列线通过上拉电阻连接到VCC电压(3.3V),对于矩阵按键来讲: 
 +  - 4根行线是输入的,是由FPGA控制拉高或拉低, 
 +  - 4根列线数输出的,是由4根行线的输入及按键的状态决定,输出给FPGA 
 +某一时刻,FPGA控制4根行线分别为ROW1=0、ROW2=1、ROW3=1、ROW4=1时, 
 +  *   ​对于K1、K2、K3、K4按键:按下时对应4根列线输出COL1=0、COL2=0、COL3=0、COL4=0,不按对应4根列线输出COL1=1、COL2=1、COL3=1、COL4=1 
 +  *   ​对于K5~~~K16之间的按键:无论按下与否,对应4根列线输出COL1=1、COL2=1、COL3=1、COL4=1, 
 +通过上面的描述:在这一时刻只有K1、K2、K3、K4按键被按下,才会导致4根列线输出COL1=0、COL2=0、COL3=0、COL4=0,否则COL1=1、COL2=1、COL3=1、COL4=1,反之当FPGA检测到列线(COL1、COL2、COL3、COL4)中有低电平信号,对应的K1、K2、K3、K4按键应该是被按下了。 
 + 
 +按照扫描的方式,一共分为4个时刻,分别对应4根行线中的一根拉低,4个时刻依次循环,这样就完成了矩阵按键的全部扫描检测,我们在程序中以这4个时刻对应状态机的4个状态。 
 +至于循环的周期,根据我们基础教程里可知,按键抖动的不稳定时间在10ms以内,所以对同一个按键采样的周期大于10ms,这同样取20ms时间。20ms时间对应4个状态,每5分钟进行一次状态转换
 \\ \\
-{{ ::button.png?600 |}}+{{ :矩阵按键程序框图.jpg?800 |}}
 \\ \\
-这是开发板上4个按键和4个开关,Key1~4是按键控制信号,SW1~4是开关控制信号,都连接到FPGA的引脚,作为FPGA的输入信号。当按键断开时,FPGA输入为高电平,当按键按下时,FPGA输入为低电平;当开关断开(OFF)时,FPGA输入为低电平,当开关合上(ON)时,FPGA输入为高电平。 +{{ :矩阵按键扫描法原理.jpg |}}
-\\ +
-所以我们可以用开关或者按键来控制LED的亮灭。+
 \\ \\
 ====Verilog代码==== ====Verilog代码====
行 22: 行 31:
 <code verilog> <code verilog>
  
-// ********************************************************************+// --------------------------------------------------------------------
 // >>>>>>>>>>>>>>>>>>>>>>>>>​ COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<​ // >>>>>>>>>>>>>>>>>>>>>>>>>​ COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<​
-// ******************************************************************** +// -------------------------------------------------------------------- 
-// File name    ​LED.v +// ModuleArray_KeyBoard 
-// Module name  : LED +//  
-// Author ​      ​STEP +// Author: ​Step 
-// Description ​ : control LED +//  
-// Web          ​www.stepfpga.com+// DescriptionArray_KeyBoard
 //  // 
 +// Web: www.stepfapga.com
 +//
 // -------------------------------------------------------------------- // --------------------------------------------------------------------
-// Code Revision History : +// Code Revision History :
 // -------------------------------------------------------------------- // --------------------------------------------------------------------
 // Version: |Mod. Date:   ​|Changes Made: // Version: |Mod. Date:   ​|Changes Made:
-// V1.0     |2017/03/02   |Initial ver+// V1.0     |2015/11/11   |Initial ver
 // -------------------------------------------------------------------- // --------------------------------------------------------------------
-// Module Function:用按键和开关的状态来控制LED灯亮灭。+module Array_KeyBoard # 
 +
 + parameter NUM_FOR_200HZ = 60000 //定义计数器cnt的计数范围,例化时可更改 
 +
 +
 + input clk_in,​ //​系统时钟 
 + input rst_n_in,​ //​系统复位,低有效 
 + input [3:0] col,​ //​矩阵按键列接口 
 + output reg [3:​0] row,​ //​矩阵按键行接口 
 + output reg [15:​0] key_out //​消抖后的信号 
 +); 
 +/* 
 +因使4x4矩阵按键,通过扫描方法实现,所以这里使用状态机实现,共分为4种状态 
 +在其中某一状态时间里,对应4个按键相当于独立按键,可按独立按键的周期采样法采样 
 +周期采样时每隔20ms采样一次,对应这里状态机每隔20ms循环一次,每个状态对应5ms时间 
 +对矩阵按键实现原理不明白的,请去了解矩阵按键实现原理 
 +*/  
 + localparam STATE0 = 2'​b00;​ 
 + localparam STATE1 = 2'​b01;​ 
 + localparam STATE2 = 2'​b10;​ 
 + localparam STATE3 = 2'b11;
  
-module LED (key,sw,led);+ //​计数器计数分频实现5ms周期信号clk_200hz 
 + reg [15:​0] cnt;​ 
 + reg clk_200hz;​ 
 + always@(posedge clk_in or negedge rst_n_inbegin 
 + if(!rst_n_in) begin //​复位时计数器cnt清零,clk_200hz信号起始电平为低电平 
 + cnt <= 16'​d0;​ 
 + clk_200hz <= 1'​b0;​ 
 + end else begin 
 + if(cnt >= ((NUM_FOR_200HZ>>​1) - 1)) begin //​数字逻辑中右移1位相当于除2 
 + cnt <= 16'​d0;​ 
 + clk_200hz <= ~clk_200hz;​ //​clk_200hz信号取反 
 + end else begin 
 + cnt <= cnt + 1'​b1;​ 
 + clk_200hz <= clk_200hz; 
 + end 
 + end 
 + end
  
- input [3:0] key; //按键输入信号 + reg [1:0] c_state; 
- input [3:0] sw; //​开关输入信号 + //状态机根据clk_200hz信号在4个状态间循环,每个状态对矩阵按键的行接口单行有效 
- output [7:0] led; //输出信号到LED + always@(posedge clk_200hz or negedge rst_n_in) begin 
-  + if(!rst_n_in) begin 
- assign led {key,sw}                                         //​assign连续赋值。大括号是拼接符,表示把key和sw拼接组成一个新的8位数赋值给led+ c_state <= STATE0
 + row <= 4'​b1110;​ 
 + end else begin 
 + case(c_state) 
 + STATE0begin c_state <= STATE1row <= 4'​b1101;​ end //状态c_state跳转及对应状态下矩阵按键的row输出 
 + STATE1: begin c_state <= STATE2; row <= 4'​b1011;​ end 
 + STATE2: begin c_state <STATE3row <= 4'​b0111;​ end 
 + STATE3: begin c_state <= STATE0; row <= 4'​b1110;​ end 
 + default:​begin c_state <= STATE0; row <= 4'​b1110;​ end 
 + endcase 
 + end 
 + end
   
 + //​因为每个状态中单行有效,通过对列接口的电平状态采样得到对应4个按键的状态,依次循环
 + always@(negedge clk_200hz or negedge rst_n_in) begin
 + if(!rst_n_in) begin
 + key_out <= 16'​hffff;​
 + end else begin
 + case(c_state)
 + STATE0:​key_out[3:​0] <= col;​ //​采集当前状态的列数据赋值给对应的寄存器位
 + STATE1:​key_out[7:​4] <= col;
 + STATE2:​key_out[11:​8] <= col;
 + STATE3:​key_out[15:​12] <= col;
 + default:​key_out <= 16'​hffff;​
 + endcase
 + end
 + end
 +
 endmodule endmodule
  
行 53: 行 126:
 \\  ​ \\  ​
 \\  ​ \\  ​
-====引脚分配==== +
-------- +
-综合(synthesize)完成之后一定要配置FPGA的引脚到相应的外设,这样下载FPGA程序后才能达到我们想要的效果。 +
-\\ +
-{{led1.png?​300|}} ​ {{button1.png?​300|}} +
-\\+
  
 ====小结==== ====小结====
 ------ ------
-下载完程序后就可以实现按键开关控制LED灯亮灭。了解小脚丫STEP-MXO2 V2上的外LED、按键和开关使用。如果你对Diamond软件的使用不了解,请参考这里:[[lattice_diamond的使用|Diamond的使用]]。 +本节主要为大家讲解了矩阵按键的工作原理及软件计,需要大家掌握同时自己创建工程,通过整个设计流程,生成FPGA配置文件加载测试 
- +\\ 
 +如果你对Diamond软件的使用不了解,请参考这里:[[lattice_diamond的使用|Diamond的使用]]。
  
 +====相关资料====
 +------
 +\\
 +使用[[STEP-MXO2第二代]]的矩阵按键程序: ​ 后续会有下载连接 ​ 待更新
 +\\
 +使用[[STEP-MAX10]]的矩阵按键程序: ​ 后续会有下载连接 ​ 待更新
 +\\