基于FPGA的4x4矩阵键盘驱动设计---第一版
欢迎各位朋友关注“郝旭帅电子设计团队”,本篇为各位朋友介绍基于FPGA的4x4矩阵键盘驱动设计---第一版
功能说明:
1. 驱动4x4矩阵键盘:按下任意一个按键,解析出对应按键信息,并给出标志
使用平台:纯代码形式
使用语言:Verilog HDL
作者QQ:746833924
说明:本篇设计中不涉及到IP和原语,代码在其他平台依然可以适用;当其他板卡电路不同时,会导致不同的现象出现,如有需要修改代码请联系作者;如需作者使用的板卡,请联系作者;
4x4矩阵键盘实物图如下:
电路原理图如下:
注:此电路设计按照四角按键设计,按键按下时,对角导通;按键释放时,对角不导通。
矩阵键盘驱动检测原理:
根据矩阵键盘排布的方式可以看到:对外引出了四根行线,四根列线;当有按键闭合时,所在的行线和列线就会导通。
主控芯片控制输出列线,然后检测行线(也可以反过来控制和检测)。
每次按键按下只有一个按键按下。
控制最后一列为低电平,其他列为高电平;如果此时最后一列有按键按下,那么对应的行线将会检测到低电平;此时根据最后一列和检测到行线的情况即可推断出对应的按键。如果最后一列没有按键按下,那么此时行线全部为高电平。
最后一列检测完毕后,可以控制倒数第二列为电平,方式同上。
四列全部检测完毕即可检测出来按键闭合的位置,根据位置译码出对应的标志即可。
假设K1闭合;第四列为低电平,此时行线全部为高电平;第三列为低电平,此时行线全部为高电平;第二列为低电平,此时第一行线为电平,其他行线为高电平;此时即可得出第二列,第一行有按键闭合。
设计思想如下:
根据上述原理,我们增加一些设计考虑。
矩阵键盘并不是一直在使用,或者说使用的时间较少,因此不建议一直处于扫描状态(不断切换列为低电平)。带来的问题:功耗增加、增加CPU的运行负担(FPGA不增加负担)等等。解决方案:先给所有列为低电平,检测行线情况,如果有按键闭合,行线将会不全为高电平,此时进行扫描,并且扫描到就退出,等待下一次有按键闭合;如果没有按键闭合,行线一直都为高电平,则此时一直等待即可。
矩阵键盘的按键在闭合时会有一定的抖动,所以要增加按键消抖机制。
本设计利用状态机设计进行实现。共有八个状态。
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矩阵键盘驱动设计---第一版的更多相关文章
- 基于FPGA的4x4矩阵键盘驱动调试
好久不见,因为博主最近两个月有点事情,加上接着考试,考完试也有点事情要处理,最近才稍微闲了一些,这才赶紧记录分享一篇博文.FPGA驱动4x4矩阵键盘.这个其实原理是十分简单,但是由于博主做的时候遇到了 ...
- 基于 FPGA 的 PCIE 总线 Linux 驱动设计
硬件平台 Kintex ®-7 family of FPGAs Intel X86 软件平台 Linux 4.15.0-36-generic #39~16.04.1-Ubuntu Xilinx xap ...
- Win10 IoT C#开发 6 - 4x4矩阵键盘扫描
Windows 10 IoT Core 是微软针对物联网市场的一个重要产品,与以往的Windows版本不同,是为物联网设备专门设计的,硬件也不仅仅限于x86架构,同时可以在ARM架构上运行. 上一章我 ...
- 4x4矩阵键盘扫描
4x4矩阵键盘扫描 Windows 10 IoT Core 是微软针对物联网市场的一个重要产品,与以往的Windows版本不同,是为物联网设备专门设计的,硬件也不仅仅限于x86架构,同时可以在ARM架 ...
- 基于FPGA的VGA可移植模块终极设计【转】
本文转载自:http://www.cnblogs.com/lueguo/p/3373643.html 略过天涯 基于FPGA的VGA可移植模块终极设计 一.VGA的诱惑 首先,VGA的驱动,这事, ...
- 4X4矩阵键盘扫描程序
4X4矩阵键盘扫描: 1. 4根行线的GIO均设为Output,根列线的GIO均设为Input: 2. 4根行线的GIO分别置为0111.1011.1101.1110,读逐一读取列线GIO的值,可确定 ...
- MCU软件最佳实践——矩阵键盘驱动
1.矩阵键盘vs独立按键 在mcu应用开发过程中,独立按键比较常见,但是在需要的按键数比较多时,使用矩阵键盘则可以减少io占用,提高系统资源利用率.例如,某mcu项目要求有16个按钮,如果采用独立按键 ...
- 「雕爷学编程」Arduino动手做(26)——4X4矩阵键盘模块
37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里 ...
- [置顶]
基于FPGA的VGA简易显存设计&NIOS ii软核接入
项目简介 本项目基于Altera公司的Cyclone IV型芯片,利用NIOS II软核,2-port RAM与时序控制模块,实现64*48分辨率的显存(再大的显存板载资源m9k不够用) 实现效果如下 ...
- 基于FPGA的VGA可移植模块终极设计
一.VGA的诱惑 首先,VGA的驱动,这事,一般的单片机是办不到的:由于FPGA的速度,以及并行的优势,加上可现场配置的优势,VGA的配置,只有俺们FPGA可以胜任,也只有FPGA可以随心所欲地配置( ...
随机推荐
- C 语言中的 switch 语句和 while 循环详解
C 语言中的 switch 语句 替代多重 if..else 语句,可以使用 switch 语句.switch 语句用于选择多个代码块中的一个来执行 switch(表达式) { case x: // ...
- SQL PRIMARY KEY 约束- 唯一标识表中记录的关键约束
SQL NOT NULL 约束 SQL NOT NULL 约束用于强制确保列不接受 NULL 值.这意味着该字段始终包含一个值,而不允许插入新记录或更新记录时不提供此字段的值. 在 CREATE TA ...
- C#中操作Excel
在GIS数据处理中,经常遇到与Excel的交互,这里进行简单的总结. Excel行列号就像是编辑中的二维数据组,操作Excel相当于操作二维数组.遍历.循环.取值.赋值-- 1.添加引用 添加引用也有 ...
- Linux Ubuntu配置国内源
配置国内源 因为众所周知的原因,国外的很多网站在国内是访问不了或者访问极慢的,这其中就包括了Ubuntu的官方源. 所以,想要流畅的使用apt安装应用,就需要配置国内源的镜像. 市面上Ubuntu的国 ...
- 空间音频技术与生态发展高峰论坛成功举办,业界首个Audio Vivid创作工具花瓣三维声亮相
11月26日至27日,UWA世界超高清视频产业联盟(以下简称"UWA联盟").上海交通大学-南加州大学文化创意产业学院.华为联合举办了"互联智慧,共赢未来" 超 ...
- Ubuntu SVN 需要证书及密码验证问题
问题概览 问题一 Ubuntu 20.04 下使用 SVN ,会报错 SVN 的证书错误,无论是选择接受 t 还是永久接受 p,下次都会要求再次接受:在 kali 或者 Windows 上没有出现该问 ...
- 2024-04-13:用go语言,给定一个整数数组 `nums`, 请编写一个函数,返回一个新的数组 `counts`。 满足以下条件:对于每个 `nums[i]`, `counts[i]` 表示在
2024-04-13:用go语言,给定一个整数数组 nums, 请编写一个函数,返回一个新的数组 counts. 满足以下条件:对于每个 nums[i], counts[i] 表示在 nums[i] ...
- sql 语句系列(列举非索引外键)[八百章之第九章]
列举非索引外键 列举出那些外键没有添加索引. 目的: 1.减少锁. 2.外键添加索引,提示了查询性能,因为要与父表做连接查询做笛卡尔积. 下面只要会复制即可,没有会去从新写一遍的. select fk ...
- MMDeploy部署实战系列【第五章】:Windows下Release x64编译mmdeploy(C++),对TensorRT模型进行推理
MMDeploy部署实战系列[第五章]:Windows下Release x64编译mmdeploy(C++),对TensorRT模型进行推理 这个系列是一个随笔,是我走过的一些路,有些地方可能不太完善 ...
- 【c++】类valarray介绍
valarray类用于处理数组中的数值,如将所有元素相加,找出最大.最小值,数组长度. 如何使用valarray类: 1.首先需要声明头文件 #include<valarray&g ...