键盘矩阵对外8个实信号都接在调控模块的引脚上,因为博主近些日子八个月有一些工作

  版权申明:本文为博主窗户(Colin Cai)原创,欢迎转帖。如要转贴,必须注明原文网址

  http://www.cnblogs.com/Colin-Cai/p/8185972.html 

  作者:窗户

  QQ:6679072

  E-mail:6679072@qq.com

好久不见,因为博主这两天七个月有一些专门的工作,加上接着考试,考完试也可以有一点事情要管理,前段时间才多少闲了有个别,那才赶紧记录分享一篇博文。FPGA驱动4×4矩阵键盘。这些实际原理是不行简练,可是由于博主做的时候蒙受了一些风趣的场合,所以本人个人认为值得记录分享一下。

  首先,不要误会,作者那边的总括器是指硬件的总结器,至于纯软件的图谋程序,以至有高端效用的,比方能够求解方程乃至可编制程序之类,作者后来找个日子以来讲。这两日看到有人在博问里问类似的主题材料,原问是想设计一个装有数码管、有着4×4键盘的硬件里的主次,不知晓他具体想做哪些,只是给了一部分提出。联想到还只怕有总结器这几个东西,这应当很轻便作为电子工程大概微电子专门的学问的四个学业的格局出现。从前小编招实习生的时候,就像是也早就叫其得以实现过总括器。这里给出一点方案,以供参谋。

先是找了本书看了下矩阵键盘的驱动原理,一般的话4×4矩阵键盘的规律图如下,有四根行线和四根列线,行选通和列选通能够规定键盘上的叁个任务。从常理图上看看,在未曾操作的事态下,行线上接了二个10K的上拉电阻接vcc,那使得键盘在尚未按下时,四根行线始终是高电平。

 

图片 1

  硬件

列线是由Computer输入给矩阵键盘,空闲状态下保持为0。也便是行空闲时输出给Computer为八个1,列空闲时由计算机输入给多个0。

     
 图片 2

当按下开关时,比方第一行第一个按键,对应的那一行导通输出为0,即row_data
= 0111,此时由微型Computer逐步输入列扫描时限信号由col_data =
0111——1110,当所按下开关为对应的那一系列的开关,矩阵键盘的行才会导通输出为0,否则会再次回到1111。别的开关类似,正是利用这些原理来驱动矩阵键盘。

  框图如上,首要有4大模块,电源、调节、按钮矩阵、数码管。

图片 3

  电源有八种方案,轻便点能够用电瓶或许usb,这里不作详细座谈。

最后FPGA部分模块引脚设计如图,大家必要对开关举行消抖,和一般开关一样,选用20ms的延时对开关进行消抖,分为按下消抖和松开消抖,中间的处境转移,因为列复信号供给输出判定行能量信号的生成,所以状态机状态转移用三个种类石英钟周期跳转。接纳状态机实行描述,状态转移图如下。

  数码管选择共阴或共阳,每一个人四个片选,选个6位的,一共14个引脚,都接在调整模块IO引脚上,注意调整数字信号电平,供给的时候阳级接上拉电阻。

图片 4

图片 5

图片 6

  键盘矩阵则是以下电路那样的事物,由一批开关组成,键盘矩阵对外8个实信号都接在调整模块的引脚上。别的,即使料定模块的引脚无法安排上拉或下拉电阻,那么PD0/PD1/PD2/PD3依旧PD4/PD4/PD6/PD7/PD8就要接上拉电阻,那关系到键盘矩阵的质量评定原理。

代码如下:(点击阅读原版的书文查看博客)

  图片 7

图片 8图片 9

  调整模块,就看想用什么编制程序了,即使想用单片机,能够选用卓绝的51单片机、AV君越单片机、PIC单片机都足以,STM32本来能够,只是ARM能够做远比那一个纷纭的政工,没须要杀鸡用牛刀。当然,想学学ARM极度是STM32的编制程序,能够用STM32。PIC单片机和51单片机本人只玩过汇编,可是将来单片机帮忙C语言都协理的蛮不错,提议还是C语言编制程序。

  1 `timescale      1ns/1ps  2 // *********************************************************************************  3 // Project Name :         4 // Author       : NingHeChuan  5 // Email        : ninghechuan@foxmail.com  6 // Blogs        : http://www.cnblogs.com/ninghechuan/  7 // File Name    : Matrix_Key_Scan.v  8 // Module Name  :  9 // Called By    :  10  11 // Abstract     : 12 // 13 // CopyRight 2018, NingHeChuan Studio..  14 // All Rights Reserved 15 // 16 // ********************************************************************************* 17 // Modification History: 18 // Date         By              Version                 Change Description 19 // ----------------------------------------------------------------------- 20 // 2018/7/28    NingHeChuan       1.0                     Original 21 //   22 // ********************************************************************************* 23  24 module Matrix_Key_Scan( 25     input                   clk,    //50Mhz 26     input                   rst_n, 27     input           [3:0]   row_data, 28     output                  key_flag, 29     output      reg [3:0]   key_value, 30     output      reg [3:0]   col_data 31 ); 32  33 //FSM state 34 parameter       SCAN_IDLE       =   8'b0000_0001; 35 parameter       SCAN_JITTER1    =   8'b0000_0010; 36 parameter       SCAN_COL1       =   8'b0000_0100; 37 parameter       SCAN_COL2       =   8'b0000_1000; 38 parameter       SCAN_COL3       =   8'b0001_0000; 39 parameter       SCAN_COL4       =   8'b0010_0000; 40 parameter       SCAN_READ       =   8'b0100_0000; 41 parameter       SCAN_JITTER2    =   8'b1000_0000; 42 // 43 parameter       DELAY_TRAN      =   2; 44 parameter       DELAY_20MS      =   1000_000; 45 //parameter       DELAY_20MS      =   100;//just test 46 reg     [20:0]  delay_cnt; 47 wire            delay_done; 48 // 49 reg     [7:0]   pre_state; 50 reg     [7:0]   next_state; 51 reg     [20:0]   tran_cnt; 52 wire            tran_flag; 53 // 54 reg     [3:0]   row_data_r; 55 reg     [3:0]   col_data_r; 56 // 57  58 //------------------------------------------------------- 59 //delay 20ms 60 always  @(posedge clk or negedge rst_n)begin 61     if(rst_n == 1'b0)begin 62         delay_cnt   <= 'd0; 63     end 64     else if(delay_cnt == DELAY_20MS) 65         delay_cnt <= 'd0; 66     else if(next_state == SCAN_JITTER1 | next_state == SCAN_JITTER2) begin 67         delay_cnt <= delay_cnt + 1'b1; 68     end 69     else  70         delay_cnt <= 'd0; 71 end 72  73 assign  delay_done = (delay_cnt == DELAY_20MS - 1'b1)? 1'b1: 1'b0; 74  75  76 //------------------------------------------------------- 77 //delay 2clk 78 always  @(posedge clk or negedge rst_n)begin 79     if(rst_n == 1'b0)begin 80         tran_cnt <= 'd0; 81     end 82     else if(tran_cnt == DELAY_TRAN)begin 83         tran_cnt <= 'd0; 84     end 85     else  86         tran_cnt <= tran_cnt + 1'b1; 87 end 88  89 assign    tran_flag = (tran_cnt == DELAY_TRAN)? 1'b1: 1'b0; 90  91  92 //------------------------------------------------------- 93 //FSM step1 94 always  @(posedge clk or negedge rst_n)begin 95     if(rst_n == 1'b0)begin 96         pre_state <= SCAN_IDLE; 97     end 98     else if(tran_flag)begin 99         pre_state <= next_state;100     end101     else pre_state <= pre_state;102 end103 104 //FSM step2105 always  @begin106     next_state = SCAN_IDLE;107     case(pre_state)108     SCAN_IDLE:109         if(row_data != 4'b1111)110             next_state = SCAN_JITTER1;111         else 112             next_state = SCAN_IDLE;113     SCAN_JITTER1:114         if(row_data != 4'b1111 && delay_done == 1'b1)115             next_state = SCAN_COL1;116         else 117             next_state = SCAN_JITTER1;118     SCAN_COL1:119         if(row_data != 4'b1111)//如果row_data是全1,说明不是列扫描没有对应到该行120             next_state = SCAN_READ;121         else 122             next_state = SCAN_COL2;123     SCAN_COL2:124         if(row_data != 4'b1111)125             next_state = SCAN_READ;126         else 127             next_state = SCAN_COL3;128     SCAN_COL3:129         if(row_data != 4'b1111)130             next_state = SCAN_READ;131         else 132             next_state = SCAN_COL4;133     SCAN_COL4:134         if(row_data != 4'b1111)135             next_state = SCAN_READ;136         else 137             next_state = SCAN_IDLE;138     SCAN_READ:139         if(row_data != 4'b1111)140             next_state = SCAN_JITTER2;141         else 142             next_state = SCAN_IDLE;143     SCAN_JITTER2:144         if(row_data == 4'b1111 && delay_done == 1'b1)145             next_state = SCAN_IDLE;146         else147             next_state = SCAN_JITTER2;148     default:next_state = SCAN_IDLE;149     endcase150 end151 152 //FSM step3153 always  @(posedge clk or negedge rst_n)begin154     if(rst_n == 1'b0)begin155         col_data <= 4'b0000;156         row_data_r <= 4'b0000;157         col_data_r <= 4'b0000;158     end159     else if(tran_flag) begin160         case(next_state)161         SCAN_COL1:col_data <= 4'b0111;162         SCAN_COL2:col_data <= 4'b1011;163         SCAN_COL3:col_data <= 4'b1101;164         SCAN_COL4:col_data <= 4'b1110;165         SCAN_READ:begin166             col_data <= col_data;167             row_data_r <= row_data;168             col_data_r <= col_data;169         end170         default: col_data <= 4'b0000;171         endcase172     end173     else begin174         col_data <= col_data;175         row_data_r <= row_data_r;176         col_data_r <= col_data_r;177     end178 end179 180 //这个状态表明是扫开消完抖动的那一瞬间181 assign key_flag = (next_state == SCAN_IDLE && pre_state == SCAN_JITTER2 && tran_flag)? 1'b1: 1'b0;182 183 //-------------------------------------------------------184 //decode key_value185 always  @(posedge clk or negedge rst_n)begin186     if(rst_n == 1'b0)begin187         key_value <= 'd0; 188     end189     else if(key_flag == 1'b1)begin190         case({row_data_r, col_data_r})191         8'b0111_0111: key_value <= 4'h1;  192         8'b0111_1011: key_value <= 4'h2;193         8'b0111_1101: key_value <= 4'h3;194         8'b0111_1110: key_value <= 4'ha;195         8'b1011_0111: key_value <= 4'h4;196         8'b1011_1011: key_value <= 4'h5;197         8'b1011_1101: key_value <= 4'h6;198         8'b1011_1110: key_value <= 4'hb;199         8'b1101_0111: key_value <= 4'h7;200         8'b1101_1011: key_value <= 4'h8;201         8'b1101_1101: key_value <= 4'h9;202         8'b1101_1110: key_value <= 4'hc;203         8'b1110_0111: key_value <= 4'hf;204         8'b1110_1011: key_value <= 4'h0;205         8'b1110_1101: key_value <= 4'he;206         8'b1110_1110: key_value <= 4'hd;207         default     : key_value <= key_value;208         endcase209     end210     else 211         key_value <= key_value;212 end213 214 215 endmodule

  当然,也是有想娱乐数字设计的,那么cpld对于那几个需假诺恰到好处的,没须要上FPGA,可以用很早以前的,价格也会有助于。对于能源多少并未有握住的话,你也能够先做数字设计,再来选器件。

Matrix_Key_Scan

 

代码部分其实没啥好说的,风趣的是博主连接硬件做调节和测量试验的时候,博主的矩阵键盘模块如图,薄膜键盘。某宝客服连原理图都没有,有一家给的本人原理图依旧错的。难题在于代码第一次下载到板子上的时候,没有出结果,不明了是代码难题要么硬件电路连接难题,作者也是试了持久才猜出来准确的接连各种。

  固件

图片 10

  硬件设计好了后头,必要统一计划固件。

图片 11

  如若调整模块采纳的是单片机,那么大家一般是在裸机下编制程序,对于这两款单片机作者就如只玩过汇编,但未来都21世纪了,作者想起码也理应用C语言来娱乐。

那是,某宝客服给的错的法规图,先拿那个看一下,和这一个矩阵键盘的结构大概,从图中得以观望那一个图和文章开端的准绳图中少了点什么,上拉电阻。这里相比较吸引的是,若无上拉电阻,在闲暇状态下,row_data怎么能维系出口高电平呢。问了多少个客服,有说不懂的有说不要加多拉电阻的。

  我们首先要清楚数码管和键盘矩阵的规律:

  小编一向上板调节和测验,在键盘的底子上加了个数码管呈现按下的数值。按下时意识是足以显得正确的数字的,可是奇异的是过一会儿数码管展现会清零。最起头以为是代码的标题,检查后从仿真和逻辑看,按钮后译码的数值其实是直接保持不改变的,未有操作是不会爆发变化的,但实在意况不太适合。

图片 12

  那样意外的景观产生,那年大家要相信科学。这种虚伪发掘不了难点,但实际上运营却又bug,这些没有办法猜出来。在线逻辑分析仪就足以见到您的代码在开荒板上运维的情况,这里引出Xilinx的Chipscope,用在线逻辑深入分析仪大约能够抓到你的代码内部的具备时限信号,那一年抓到的是你的电路实际运作的境况,配置流程如下。

  数码管相对轻松一些,一般的话,数码管每一人展现的数字都差别。如小编图中的共阴6位数码管,当要显得某位的时候,片选非随机信号选用是拉低,其余片选拉高,然后再把要体现的数字所要点亮的管的引脚拉高,那样,要出示的那一个人就展现出了数字,而其余的三人未有其余展现。然后不慢切换,每一人都显得该显示的数字,那么遵照视觉暂留,大家就观望了完全的彰显。

图片 13

图片 14

新建New source分界面,选取如图Chipscope,next。

  键盘矩阵大概要复杂那么部分。首先,我们只要我们那边PD5、PD6、PD7、PD8都被大家接了上拉电阻,何况IO都为高阻接收状态,而不出口。大家这里只思考三个键的鉴定区别,其实键盘矩阵也得以辨认多少个键。大家想一想,假诺某些键按下去,譬如左上角的S3按下之后,会时有发生什么。在按下去此前,PD1、PD2、PD3、PD4和PD5、PD6、PD7、PD8之内并不联通。但当S3按下去,PD1和PD4连在了共同。倘使调控模块把PD4的出口射为高阻状态,那么一旦PD0输入低电平,那么PD4读抽出来的应有为低电平,否则为高电平。于是我们把PD1、PD2、PD3、PD4那4个引脚每一次只中间多个出口低电平,别的多个出口高阻状态,每一遍都去读取PD5、PD6、PD7、PD8,那么就足以依附数值来判定毕竟是哪些按钮被按下。注意,此处PD1、PD2、PD3、PD4这4个引脚每一趟只中间一个输出低电平的时候,其余四个无法出口高电平,而相应是高阻,不然,假如有八个开关被按下,则为封堵状态!

图片 15

  其余要思虑按钮的振荡难点,有多样消除措施,例如能够在认清到三次开关按下之后0.3秒内不重复推断开关被按下。

下一场会自动生成二个后缀为.cdc的文件,双击展开。

  既然数码管的来得必要按时去切换展现位,而键盘矩阵也须要定期去切换输入,那么大家就能够安装三个定时器,把那三个硬件的管理都挂在同二个按时中断例程上作为驱动层,其逻辑使用上述的规律来完成,能够每便中断给二个循环计数作为气象,做叁个moore机老妪能解,至于0.3秒内不重复在相互里显示就能够。程序中达成驱动层和应用层的等级次序分离,无论从调节和测量试验硬件依然设计固件来讲都以必备的,当然你也可以分的更加细,比如HAL层。当然,非要在那边把富有的全部糅合在协同也是能够最后化解的,但档案的次序感差非常多,并且一个初大家真的设计倒霉二个大的状态机。

图片 16

  设计有个别全局变量用来应用层和驱动层交互显示数据和所按开关。

这一步点击next

  unsigned char
num[6] ;//应用层写,驱动层读,用于6位数据的显得

图片 17

  unsigned char
flag;//flag=0的时候,驱动层能够安装key,并把flag设为1;flag=1的时候,应用层能够读取key,并把flag设置为0

同样next

  unsigned char
key;//以象征是哪个键按下,分别给0、1、2、3、4、5、6、7、8、9、+、-、*、/、=、退格编码为0~15

图片 18

  以上数占有冗余,在RAM极端受限的状态下,能够裁剪数据。

此地选取,触发频限信号的多少和位宽,笔者这里选拔了四个触发随机信号,五个位宽为4,对应矩阵键盘的行和列,三个位宽为1,为重新载入参数复信号。末了面包车型地铁滚轮下拉能够观望整个频域信号。

  而关于总计器所要实现的参天6位加减乘除,很轻易完毕,根本没有供给运气总结,结合突显和按钮,构成应用层程序,想想三个计算器的遵守,你应当很轻松的画出流程图,不是吧?

图片 19

  假诺作为学生,你采用的是cpld/fpga,作者也支持你,我以为两个方可本人单身做出来的学习者应该照旧不错的,但也和事先处理器的程序达成类似:分别布置键盘驱动模块、数码管驱动模块、计算模块,最终中间有六此中央模块以四个情况机格局存在,与别的多少个模块都每每。当然,种种模块内部也足以分小模块,比如数码管模块里面最佳把解码器单独落成一个小模块,而计量模块里加减乘除都以单身的小模块。

此地安装抓取的随机信号深度,选取上涨沿采集样品时限信号。完成后点击next

  图片 20

图片 21

 

这里选拔石英钟功率信号clk

自己的博客将在搬运贰只至Tencent云+社区,约请大家一起入驻:https://cloud.tencent.com/developer/support-plan

图片 22

分选后点击make connection,OK。

图片 23

同样的抉择其余接触随机信号,参加行和列和复位信号。

图片 24

丰盛完结OK

图片 25

点击完结退出。

图片 26

保存

图片 27

这里点击这里就能够运营Chipscope了,那个时候板子就足以上电了。

图片 28

点击链接板子

图片 29

照图点击下载板子。

图片 30

图片 31

图片 32

图片 33

图片 34

安顿相关文书

图片 35

下一场会弹出这些窗口,这里能够安装触发类型和接触格局,加多的复信号都会显得出来

图片 36

设置触发格局为M2,即复位时域信号。

图片 37

点击上边的开关初步运维,重新恢复设置键释放,就足以抓取到一些确定性信号了。

图片 38

按下三个按钮会看到相应的类别转变。

这是Chipscope的调用流程,通过在线逻辑深入分析仪,博主开采了难题,在空闲无操作时,触发复位抓取复信号,抓到的row_data偶尔候是1111。有时候是0000或任何,可是理论上矩阵键盘在无操作下应该直接row_data输出1111。正是那个意外的主题材料导致的不当。我们要相信科学。应该是硬件电路的难点,检查了与开拓板连接的Dupont线没难题后,应该正是矩阵键盘自个儿的主题材料,上拉电阻那块的法规,笔者所使用的矩阵键盘未有上拉电阻,可是事实上那样的驱动,借使row_data线上未曾上拉电阻,它很难维持为高电平,而这一个地点加不加其实和驱动开荒板的布局有关,据自己询问,某个单片机的I/O引脚会内置上拉电阻,暗中同意情状下是高电平,所以用这几个单片机驱动是不供给加上拉电阻的。

自己这里运用FPGA驱动,FPGA的引脚性子来讲,依然须求加的,使矩阵键盘的能量信号输出稳固,对于Xilinx
FPGA来讲风趣的是,通过综合工具增添引脚约束能够运营一样的机能,比如在ucf文件的引脚电平约束中增加pullup就足以了。

图片 39

出于自个儿动用的Spartan-3E连串的开荒板,从它手册上得以拿走。在引脚约束在电平为3.3v时加上pull
up,可以等下出相当于10.8k欧姆的电阻那和矩阵键盘的驱动原理是全然吻合。

图片 40

那篇博文重要分享的是硬件的二个调节和测验进程,Chipscope依旧很好用的。对于硬件来讲,你不可能鲜明他的情事,所以利用工具抓取他的实际信号,扶助大家越来越好调节和测量检验。

图片 41

转发请注脚出处:NingHeChuan

村办微信订阅号:开源FPGA

如若您想立马收到个人写作的博文推送,能够扫描左侧二维码(或然长按识别二维码)关怀个体微信订阅号

知乎ID:NingHeChuan

微博ID:NingHeChuan

初稿地址:https://www.cnblogs.com/ninghechuan/p/9401744.html

相关文章