接收矩阵键盘数据(FPGA)

本文介绍了如何在FPGA中使用矩阵键盘,通过列扫描法检测按键状态。详细阐述了检测思路,包括将COL0设为输出并检测ROW线电平来判断按键按下。还讨论了简易版和进阶版的控制代码实现,适用于不同场景。建议读者通过仿真验证波形以深入理解。
摘要由CSDN通过智能技术生成

一、矩阵键盘

由于最早的 MCU(即单片机) 其 IO 口相对较少,而且用到按键过多的话,就会占用过多的 IO。人们为了解决这个问题就引入了“矩阵键盘”。在矩阵键盘中,每条行线和列线在交叉处都不是直接连同,而是通过一个按键直接相连,这样以来一个 4×4 的矩阵键盘只需要 8 根控制线就可以完成16 个按键的控制。
在这里插入图片描述

二、矩阵键盘使用思路

1.检测思路:如,将COL0作为FPGA的输出管脚,当COL0输出低电平时,只需检测ROW0~4是否为低电平即可判断按键 0~4是否被按下。

1.COL = 1110,读ROW,可以确定知道第一列的4个按键是否有一个或多个被按下(0,4,8,C)。
2.COL = 1101,读ROW,可以确定知道第二列的4个按键是否有一个或多个被按下(1,5,9,D)。
……

2.按键扫描方案

通常我们检测矩阵键盘中某一按键是否被按下,采用的方法是列扫描法。图中一共有 8条控制线,4 条行控制线(ROW),4 条列控制线(COL),4 根行控制线(ROW)被通过上拉电阻拉到了高电平,因此,如果没有按键被按下的情况下,使用 FPGA 的 IO 坚持 ROW 信号上的电平,应该默认都是高电平。那我们如何去检测某一个按键被按下,并且还能找到其具体的位置呢?思路其实并不复杂,假如我们让 COL0=0,然后去读取 ROW 的值,如果 4 个 ROW信号的电平全部为高,则表明当前列并无按键按下,则切换到扫描下一列,再去读取 4 个 ROW信号的值,根据读到的 ROW 值判断当前是哪一个按键被按下。例如当扫描第三列的时候,即 COL=4’b1011 时,检测到 ROW=4’b1011,则说明“A”被按下。
这个思路看起来简单,实际上要用到的状态机数目可不少。

三、矩阵键盘控制代码

1.简易版

一次只能按下一个按键,若同时按下两个按键,则随机取其中一个按键的值。

module Matrix_Keyboard(
	input				Clk,
	input				Rst_n,
	input		[3:0]	Row,
	output	reg	[3:0]	Col,
	output	reg [3:0]	key_num
);
	reg	[3:0]	Row_r [2:0];//定义3个4位宽的寄存器
	reg	[4:0]	state;
	reg	[7:0]	key_value_r;
	reg	[19:0]	cnt;
	reg			delay_cnt_en;

	localparam	SC_C 		 = 5'b00001,
				RD_R		 = 5'b00010,
				FILTER0 	 = 5'b00100,
				WAIT_RELEASE = 5'b01000,
				FILTER1		 = 5'b10000,
				T20MS		 = 20'd999_999;

	//消除亚稳态,寄存两拍后再使用
	always@(posedge Clk)begin
		Row_r[2][3:0] <= Row_r[1][3:0];
		Row_r[1][3:0] <= Row_r[0][3:0];
		Row_r[0][3:0] <= Row;
	end

	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		Col <= 4'b1110;
		state <= SC_C;
		key_value_r <= 0;
	end
	else begin
		case(state)
		 	//扫描COL0~4
			SC_C:
				begin
					state <= RD_R;
					Col <= {
   Col[2:0],Col[3]};	//循环左移扫描
				end
			//读ROW的状态
			RD_R:
				if(Row_r[2][3:0] != 4'b1111)begin	//读取到的如果不是1111,则说明此刻某个按键正在被按下,进入消抖程序
					delay_cnt_en <= 1'b1;	//计时20ms使能
					state <= FILTER0;
				end
				else 								//读取到的ROW值如果是1111,则该列没有按键按下,回到扫描状态,继续进行下一列的扫描
					state <= SC_C;
			FILTER0:
				if(cnt >= T20MS)begin
					if(Row_r[2][3:0] != 4'b1111)begin	//延时20ms后,如果读到的ROW不是1111,说明按键已被稳定按下
						key_value_r <= {
   Col,Row_r[
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值