欢迎各位朋友关注“郝旭帅电子设计团队”,本篇为各位朋友介绍基于FPGA的4x4矩阵键盘驱动设计---第一版

功能说明:

1. 驱动4x4矩阵键盘:按下任意一个按键,解析出对应按键信息,并给出标志

使用平台:纯代码形式

使用语言:Verilog HDL

作者QQ:746833924

说明:本篇设计中不涉及到IP和原语,代码在其他平台依然可以适用;当其他板卡电路不同时,会导致不同的现象出现,如有需要修改代码请联系作者;如需作者使用的板卡,请联系作者;

4x4矩阵键盘实物图如下:

电路原理图如下:

注:此电路设计按照四角按键设计,按键按下时,对角导通;按键释放时,对角不导通。

矩阵键盘驱动检测原理:

根据矩阵键盘排布的方式可以看到:对外引出了四根行线,四根列线;当有按键闭合时,所在的行线和列线就会导通。

主控芯片控制输出列线,然后检测行线(也可以反过来控制和检测)。

每次按键按下只有一个按键按下。

控制最后一列为低电平,其他列为高电平;如果此时最后一列有按键按下,那么对应的行线将会检测到低电平;此时根据最后一列和检测到行线的情况即可推断出对应的按键。如果最后一列没有按键按下,那么此时行线全部为高电平。

最后一列检测完毕后,可以控制倒数第二列为电平,方式同上。

四列全部检测完毕即可检测出来按键闭合的位置,根据位置译码出对应的标志即可。

假设K1闭合;第四列为低电平,此时行线全部为高电平;第三列为低电平,此时行线全部为高电平;第二列为低电平,此时第一行线为电平,其他行线为高电平;此时即可得出第二列,第一行有按键闭合。

设计思想如下:

根据上述原理,我们增加一些设计考虑。

  1. 矩阵键盘并不是一直在使用,或者说使用的时间较少,因此不建议一直处于扫描状态(不断切换列为低电平)。带来的问题:功耗增加、增加CPU的运行负担(FPGA不增加负担)等等。解决方案:先给所有列为低电平,检测行线情况,如果有按键闭合,行线将会不全为高电平,此时进行扫描,并且扫描到就退出,等待下一次有按键闭合;如果没有按键闭合,行线一直都为高电平,则此时一直等待即可。

  2. 矩阵键盘的按键在闭合时会有一定的抖动,所以要增加按键消抖机制。

本设计利用状态机设计进行实现。共有八个状态。

  
localparam          STATE_OFF             =   9'b00000_0001;  
localparam STATE_ON_SHAKE = 9'b00000_0010;
localparam STATE_OUT_SCAN = 9'b00000_0100;
localparam STATE_SCAN_WAIT0 = 9'b00000_1000;
localparam STATE_SCAN_WAIT1 = 9'b00001_0000;
localparam STATE_SCAN_WAIT2 = 9'b00010_0000;
localparam STATE_SCAN_WAIT3 = 9'b00100_0000;
localparam STATE_CHECK_PRESS = 9'b01000_0000;
localparam STATE_OFF_SHAKE = 9'b10000_0000;

复位结束后,在OFF状态。此时列全部为低电平,如果没有按键闭合,则行线一直全部为高电平,保持OFF状态;如果有按键闭合,则行线就不全为高电平,此时进入ON_SHAKE状态,在此状态中,列全部为低电平,检测行线是不是一直不全为高电平,如果按键有抖动,则行线会变为全部高电平,此时回到OFF状态;当行线一直不全为高电平保持10ms或者20ms,则认为按键无抖动,之后进入OUT_SCAN状态;

在OUT_SCAN状态输出单列为低电平,等待四个状态即等待四个时钟周期:用于输出行线的同步(STATE_SCAN_WAIT0、STATE_SCAN_WAIT1、STATE_SCAN_WAIT2、STATE_SCAN_WAIT3),在CHECK_PRESS状态监测行线,判断是否为全高,即监测此列是否有按键闭合。如果有按键闭合,则记录行列情况;如果没有按键按下,则返回OUT_SCAN状态,进行下一列监测。如果监测完四列没有发现有按键按下,则也跳出。

在OFF_SHAKE状态,是检测按键放开的抖动,原理和检测按下的抖动类似。

    always @ * begin
case (c_state)
STATE_OFF : n_state = (row_rr == 4'hf) ? STATE_OFF : STATE_ON_SHAKE;
STATE_ON_SHAKE : n_state = (row_rr == 4'hf) ? STATE_OFF : (cnt_10ms < T_10ms - 1'b1) ? STATE_ON_SHAKE : STATE_OUT_SCAN;
STATE_OUT_SCAN : n_state = STATE_SCAN_WAIT0;
STATE_SCAN_WAIT0 : n_state = STATE_SCAN_WAIT1;
STATE_SCAN_WAIT1 : n_state = STATE_SCAN_WAIT2;
STATE_SCAN_WAIT2 : n_state = STATE_SCAN_WAIT3;
STATE_SCAN_WAIT3 : n_state = STATE_CHECK_PRESS;
STATE_CHECK_PRESS : n_state = (row_rr == 4'hf) ? (keyboard4x4_col == 4'b0111) ? STATE_OFF : STATE_OUT_SCAN : STATE_OFF_SHAKE;
STATE_OFF_SHAKE : n_state = (row_rr == 4'hf && cnt_10ms == T_10ms - 1'b1) ? STATE_OFF : STATE_OFF_SHAKE;
default : n_state = STATE_OFF;
endcase
end

根据上述的状态机,我们就可以找出来对应的行列位置。

  always @ (posedge clk) begin
if (rst_n == 1'b0)
row_col <= 8'd0;
else
if (c_state == STATE_CHECK_PRESS && row_rr != 4'hf)
row_col <= {row_rr, keyboard4x4_col};
else
row_col <= row_col;
end
 

然后根据行列位置进行译码出对应的按键值。

  always @ (posedge clk) begin
if (rst_n == 1'b0)
key_num <= 4'd0;
else
case (row_col)
8'b1110_1110 : key_num <= 4'd0;
8'b1110_1101 : key_num <= 4'd1;
8'b1110_1011 : key_num <= 4'd2;
8'b1110_0111 : key_num <= 4'd3; 8'b1101_1110 : key_num <= 4'd4;
8'b1101_1101 : key_num <= 4'd5;
8'b1101_1011 : key_num <= 4'd6;
8'b1101_0111 : key_num <= 4'd7; 8'b1011_1110 : key_num <= 4'd8;
8'b1011_1101 : key_num <= 4'd9;
8'b1011_1011 : key_num <= 4'd10;
8'b1011_0111 : key_num <= 4'd11; 8'b0111_1110 : key_num <= 4'd12;
8'b0111_1101 : key_num <= 4'd13;
8'b0111_1011 : key_num <= 4'd14;
8'b0111_0111 : key_num <= 4'd15; default : key_num <= 4'd0;
endcase
end
 

使用时,根据标志是否为高以及对应的数值即可知道是是否有按键按下,并且知道是那个按键按下。

此项仿真较难,由于输入和输出有一定的相关关系,所以在仿真时,需要设计矩阵键盘的仿真模型keyboard4x4(下面链接会提供源码)。

  keyboard4x4_drive keyboard4x4_drive_inst(

      .clk                          (clk            ),        //  100MHz
.rst_n (rst_n ), .keyboard4x4_row (keyboard4x4_row),
.keyboard4x4_col (keyboard4x4_col), .key_num (key_num ),
.flag_key (flag_key )
); keyboard4x4 keyboard4x4_inst( .press_num (press_num ), .keyboard4x4_col (keyboard4x4_col),
.keyboard4x4_row (keyboard4x4_row)
);

利用task语句模拟按键的抖动和按下。
initial begin
rst_n = 1'b0;
press_num = 5'd16;
# 1001
rst_n = 1'b1; # 2000;
press_data(5'd15);
press_data(5'd14);
press_data(5'd13);
press_data(5'd12);
press_data(5'd11);
press_data(5'd10);
press_data(5'd9);
press_data(5'd8);
press_data(5'd7);
press_data(5'd6);
press_data(5'd5);
press_data(5'd4);
press_data(5'd3);
press_data(5'd2);
press_data(5'd1);
press_data(5'd0); $stop;
end task press_data;
input [4:0] data; begin
repeat (5) begin
press_num = data;
# 10000;
press_num = 5'd16;
# 10000;
end press_num = data;
# 15_000_000; repeat (5) begin
press_num = data;
# 10000;
press_num = 5'd16;
# 10000;
end press_num = 5'd16;
# 30_000_000; end
endtask
 

在press_num给16,即表示按键的释放。通过快速释放和按下,模拟的抖动。

通过仿真图可以看出来,我们检测出来了正确的结果。

下板测试的话,我们可以将矩阵键盘与FPGA连接好,然后将检测出来的值放到数码管或者led上,用于显示数值,在此我选择led(因为懒的写数码管了)。

按下按键K6后,四个led呈现灭亮亮灭;led的驱动原理为高电平点亮,低电平熄灭;故而此时为0110,即为数字6。

按下其他的按键也可以正确显示,故而验证设计正确。

文章同款矩阵键盘购买链接:

https://item.taobao.com/item.htm?abbucket=10&id=796054801643&ns=1&priceTId=215044ff17157343140338659e0404&spm=a21n57.1.item.14.1d4a523cRO1waY

讲解和演示视频链接如下:
https://www.bilibili.com/video/BV1YH4y1u7ye/?vd_source=b5405faeab8632f02533bcbfc5e52e55

本设计所有内容(设计代码、设计工程)链接为:

链接:https://pan.baidu.com/s/1x9pP6Z0gGkR77XG8kFXvRA

提取码:mroh

本篇内容中有部分资源来源于网络,如有侵权,请联系作者。

如果您觉得本公众号还不错的话,可以推给身边的朋友们,感谢并祝好!

基于FPGA的4x4矩阵键盘驱动设计---第一版的更多相关文章

  1. 基于FPGA的4x4矩阵键盘驱动调试

    好久不见,因为博主最近两个月有点事情,加上接着考试,考完试也有点事情要处理,最近才稍微闲了一些,这才赶紧记录分享一篇博文.FPGA驱动4x4矩阵键盘.这个其实原理是十分简单,但是由于博主做的时候遇到了 ...

  2. 基于 FPGA 的 PCIE 总线 Linux 驱动设计

    硬件平台 Kintex ®-7 family of FPGAs Intel X86 软件平台 Linux 4.15.0-36-generic #39~16.04.1-Ubuntu Xilinx xap ...

  3. Win10 IoT C#开发 6 - 4x4矩阵键盘扫描

    Windows 10 IoT Core 是微软针对物联网市场的一个重要产品,与以往的Windows版本不同,是为物联网设备专门设计的,硬件也不仅仅限于x86架构,同时可以在ARM架构上运行. 上一章我 ...

  4. 4x4矩阵键盘扫描

    4x4矩阵键盘扫描 Windows 10 IoT Core 是微软针对物联网市场的一个重要产品,与以往的Windows版本不同,是为物联网设备专门设计的,硬件也不仅仅限于x86架构,同时可以在ARM架 ...

  5. 基于FPGA的VGA可移植模块终极设计【转】

    本文转载自:http://www.cnblogs.com/lueguo/p/3373643.html 略过天涯   基于FPGA的VGA可移植模块终极设计 一.VGA的诱惑 首先,VGA的驱动,这事, ...

  6. 4X4矩阵键盘扫描程序

    4X4矩阵键盘扫描: 1. 4根行线的GIO均设为Output,根列线的GIO均设为Input: 2. 4根行线的GIO分别置为0111.1011.1101.1110,读逐一读取列线GIO的值,可确定 ...

  7. MCU软件最佳实践——矩阵键盘驱动

    1.矩阵键盘vs独立按键 在mcu应用开发过程中,独立按键比较常见,但是在需要的按键数比较多时,使用矩阵键盘则可以减少io占用,提高系统资源利用率.例如,某mcu项目要求有16个按钮,如果采用独立按键 ...

  8. 「雕爷学编程」Arduino动手做(26)——4X4矩阵键盘模块

    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里 ...

  9. [置顶] 基于FPGA的VGA简易显存设计&NIOS ii软核接入

    项目简介 本项目基于Altera公司的Cyclone IV型芯片,利用NIOS II软核,2-port RAM与时序控制模块,实现64*48分辨率的显存(再大的显存板载资源m9k不够用) 实现效果如下 ...

  10. 基于FPGA的VGA可移植模块终极设计

    一.VGA的诱惑 首先,VGA的驱动,这事,一般的单片机是办不到的:由于FPGA的速度,以及并行的优势,加上可现场配置的优势,VGA的配置,只有俺们FPGA可以胜任,也只有FPGA可以随心所欲地配置( ...

随机推荐

  1. Stable diffusion 初学者指南

    1. Stable diffusion 初学者指南 想掌握Stable Diffusion AI技术吗? 这份初学者指南专为完全没接触过Stable Diffusion或任何AI图像生成器的新手设计. ...

  2. 照骗qsnctfwp

    题目附件 使用 010 Editor 等工具打开发现 flag.txt 字样 将图片保存至 Kali 使用工具 foremost,通过命令foremost 3.png即可分离处图片所含隐写文件 打开发 ...

  3. 重学c#系列——什么是性能[外篇性能篇一]

    前言 简单写一下性能的简介. 正文 什么是性能,很多时候有一个问题,那就很多人喜欢说.这个服务有很多访问,我们需要这样设计. 这是一个无法验证的指标,访问次数是多少? 响应时间是多少. 我把这归纳为自 ...

  4. css 如何绘制正方形

    前言 如何绘制正方形的问题呢,在这里我先只写一种方式,后续补齐. 正文 写正方形有一个很特殊的地方就在于我们在写html的时候,宽是一定固定的,因为不可能溢出去,但是高就不固定了,因为可能要滑动. 问 ...

  5. c# TryParse

    c# tryparse和parse对比,大体内容是一致的. parse 会返回异常,主要表现为三种. 第一种ArgumentNullException,这里面表示,为空. 第二种formatexcep ...

  6. native react 代码智能提示

    背景 在vscode 中,虽然有插件可以达到代码提示的效果但是不是很嗨. 所以加上这些: 全局安装typings: npm install typings -g 1 安装react和react-nat ...

  7. ES6中Module以及使用场景

    一.介绍 模块,(Module),是能够单独命名并独立地完成一定功能的程序语句的集合(即程序代码和数据结构的集合体). 两个基本的特征:外部特征和内部特征 外部特征是指模块跟外部环境联系的接口(即其他 ...

  8. axios请求时获取不到错误提示问题。

    前端方面使用axios请求,由于新增时,有的条件格式填写错误.后端返回412状态码. ,axios可能封装不完善,他获取数据使状态码为4开头的统统不暴露出去,导致请求时,412这样的状态码,获取不到里 ...

  9. idea引用lombok一直不成功

    idea引用lombok一直不成功 比如想使用lombok的@data注解一直报错,尽管已经声明了import lombok.Data,且在pom里面也增加了lombok依赖,但是就是不成功的时候 建 ...

  10. 力扣430(java)-扁平化多级双向链表(中等)

    题目: 你会得到一个双链表,其中包含的节点有一个下一个指针.一个前一个指针和一个额外的 子指针 .这个子指针可能指向一个单独的双向链表,也包含这些特殊的节点.这些子列表可以有一个或多个自己的子列表,以 ...