差别
这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
矩阵键盘键入系统设计 [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。 |