差别

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

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
矩阵键盘键入系统设计 [2018/10/22 11:11]
anran [实验原理]
矩阵键盘键入系统设计 [2018/10/22 11:20] (当前版本)
anran [实验现象]
行 55: 行 55:
 通过上节的描述,大家对于矩阵键盘工作的原理应该都没有问题了,那么我们怎么编程实现矩阵键盘驱动设计呢?我们将矩阵键盘的扫描周期分为4个时刻,对应4个状态,使得状态机在4个状态上循环跳转,最终通过扫描的方式获取矩阵键盘的操作状态。 通过上节的描述,大家对于矩阵键盘工作的原理应该都没有问题了,那么我们怎么编程实现矩阵键盘驱动设计呢?我们将矩阵键盘的扫描周期分为4个时刻,对应4个状态,使得状态机在4个状态上循环跳转,最终通过扫描的方式获取矩阵键盘的操作状态。
  
-{{:​矩阵按键扫描法原理.jpg?​600|状态机各状态逻辑}}+{{:​矩阵按键扫描法原理.jpg?​800|状态机各状态逻辑}}
  
 状态机程序实现如下: 状态机程序实现如下:
行 80: 行 80:
 至于状态机循环的周期,根据我们基础教程里可知,按键抖动的不稳定时间在10ms以内,所以对同一个按键采样的周期大于10ms,这里同样取20ms时间。20ms时间对应4个状态,每5分钟进行一次状态转换。所以我们在状态机之前先增加分频模块,得到200Hz的分频时钟,然后状态机按照200Hz分频时钟的节拍做状态跳转和键盘采样。 至于状态机循环的周期,根据我们基础教程里可知,按键抖动的不稳定时间在10ms以内,所以对同一个按键采样的周期大于10ms,这里同样取20ms时间。20ms时间对应4个状态,每5分钟进行一次状态转换。所以我们在状态机之前先增加分频模块,得到200Hz的分频时钟,然后状态机按照200Hz分频时钟的节拍做状态跳转和键盘采样。
  
-{{:​矩阵按键程序框图.jpg?​500|状态转移图}}+{{:​矩阵按键程序框图.jpg?​600|状态转移图}}
  
 状态机程序实现如下: 状态机程序实现如下:
行 128: 行 128:
 对于大多数需要循环扫描的硬件来说,程序写到这里应该就完成了,但是大家想想我们之前基础数字电路实验关于按键消抖部分的内容,因为我们是在对按键采样,按键是会抖动的,所以我们还要想办法对采集回来的数据做一些判定,怎么判定呢? 这就得回到矩阵键盘工作原理上来了。 对于大多数需要循环扫描的硬件来说,程序写到这里应该就完成了,但是大家想想我们之前基础数字电路实验关于按键消抖部分的内容,因为我们是在对按键采样,按键是会抖动的,所以我们还要想办法对采集回来的数据做一些判定,怎么判定呢? 这就得回到矩阵键盘工作原理上来了。
  
-{{:​抖动原理.png?​500|按键抖动示意}}+{{:​抖动原理.png?​800|按键抖动示意}}
  
 上图是市面上常见按键抖动的模型,有三个参数,按下抖动10ms以内,松开抖动10ms以内,按键周期数百ms;前面说过键盘的采样周期为20ms,可以得到以下结论: 上图是市面上常见按键抖动的模型,有三个参数,按下抖动10ms以内,松开抖动10ms以内,按键周期数百ms;前面说过键盘的采样周期为20ms,可以得到以下结论:
行 162: 行 162:
 经过上面程序的处理,我们就得到了16位脉冲信号,平时为低电平,当按键被按下时刻key_pulse产生一个高脉冲,脉冲的宽度为模块系统时钟clk_in的一个周期。 经过上面程序的处理,我们就得到了16位脉冲信号,平时为低电平,当按键被按下时刻key_pulse产生一个高脉冲,脉冲的宽度为模块系统时钟clk_in的一个周期。
  
-{{:​2-状态机状态转移图.png?​600|状态机状态转移图}}+{{:​2-状态机状态转移图.png?​800|状态机状态转移图}}
  
 ===系统总体实现=== ===系统总体实现===
  
 +在基础数字电路实验部分我们已经掌握了FPGA驱动独立显示数码管的原理及方法, 模块通过一个4位的输入传递要显示的数值,通过9位的输出控制数码管显示该数值,这里我们不再重复。
 +矩阵键盘驱动模块输出的是脉冲信号,后面数码管驱动模块输入的是用4位位宽表示的数据,所以中两个实例之间就需要一个编码的功能块,主要功能是根据矩阵键盘的脉冲输出(key_pulse)判定键盘的操作,通过编码对应提供按键的键值数据(seg_data),最后通过连线将键值数据连接到数码管模块的输入端口。
  
 +键值显示转码程序实现
 +<code verilog>
 +//key_pulse transfer to seg_data
 +always@(posedge clk or negedge rst_n) begin
 + if(!rst_n) begin
 + seg_data <= 8'h00;
 + end else begin
 + case(key_pulse) ​ //​key_pulse脉宽等于clk_in的周期
 + 16'​h0001:​ seg_data <= 8'​h01; ​ //编码
 + 16'​h0002:​ seg_data <= 8'h02;
 + 16'​h0004:​ seg_data <= 8'h03;
 + 16'​h0008:​ seg_data <= 8'h04;
 + 16'​h0010:​ seg_data <= 8'h05;
 + 16'​h0020:​ seg_data <= 8'h06;
 + 16'​h0040:​ seg_data <= 8'h07;
 + 16'​h0080:​ seg_data <= 8'h08;
 + 16'​h0100:​ seg_data <= 8'h09;
 + 16'​h0200:​ seg_data <= 8'h10;
 + 16'​h0400:​ seg_data <= 8'h11;
 + 16'​h0800:​ seg_data <= 8'h12;
 + 16'​h1000:​ seg_data <= 8'h13;
 + 16'​h2000:​ seg_data <= 8'h14;
 + 16'​h4000:​ seg_data <= 8'h15;
 + 16'​h8000:​ seg_data <= 8'h16;
 + default: ​ seg_data <= seg_data; ​  //​无按键按下时保持
 + endcase
 + end
 +end
 +</​code>​
 +
 +综合后的设计框图如下:
 +
 +{{:​2-rtl设计框图.png?​800|rtl设计框图}}
 ====实验步骤==== ====实验步骤====
   - 双击打开Quartus Prime工具软件;   - 双击打开Quartus Prime工具软件;
行 179: 行 214:
  
 ====实验现象==== ====实验现象====
 +
 +按动矩阵键盘上的按键,核心板独立显示数码管会更新显示对应键值。例如上电默认显示00,按动K8按键,数码管显示08,再按动K16按键,数码管显示16。