西南交通大学计算机组成原理实验——实验二4*4矩阵键盘

本实验加了简单的防抖功能,模块功能注释写得很详尽

关于防抖,因为我在设计的时候是一直在扫描,如果没有键被按下,就一直输出无效信号。        每次按下键盘按钮后,由于存在抖动,会连续输出多个有效信号,之后又会一直输出无效信号。 寄存器num[4..0]为5’b1_0000时信号无效,为了达到防抖效果,这里对无效信号出现的次数进行计数,注意之所以防抖是因为按下一次会出现多次有效信号,但是这些信号的间隔很短,我们只要第一次出现的有效信号,那么当有效信号间隔很短的时候我们就把他丢掉。即两次有效信号之间的无效信号次数过少时丢掉它。

补充:之所以count_num从1开始计数是为了防止间隔时间过长count_num位数不够又变成0

//Key_module(clk,KEY_R,KEY_C,out,rst);
/*
该模块的功能为:从4*4矩阵键盘输入数值
输出一个32位的数
代替用key拨动开关置数,引脚数不够时很好用
*/
module Key_module(
	input clk,
	input rst,
	//这里加了复位信号,如果不需要复位信号删掉即可
	input [3:0] KEY_R,
	output reg[3:0] KEY_C = 4'b0111,
	output reg[31:0] out= 32'h0000_0000
	//注:这里的输出是三十二位的,对应led模块最多可以显示三十二位的二进制数。共八个示数,每个示数四位
	//如需要非三十二位的输出,即需要其他位宽的输出,只需要在这里将out的位宽改掉即可,其他部分均不需要改动
	//例如需要八位的输出,则需要改为output reg[7:0] out= 8'h00
);
	reg[4:0]num = 5'b1_0000;
	reg [31:0]count_num = 32'b1;
	reg [1:0] cnt = 2'b0;
	
//根据按钮的列扫描信号和行输入信号判断按钮是否被按下
always  @(posedge clk)
begin
	if(rst)
		out = 32'h0000_0000;
	else
		begin
			cnt = cnt + 1'b1;
			case (cnt)
				2'b00:	KEY_C <= 4'b1110;
				2'b01:	KEY_C <= 4'b1101;
				2'b10:	KEY_C <= 4'b1011;
				2'b11:	KEY_C <= 4'b0111;         
       			endcase
      //如果无按钮按下,定义num=16为无效状态
      if (KEY_R == 4'b1111)begin 
          num = 5'd16;       end   //无按键输入,输出16
             
      else begin 
           case ({KEY_R, KEY_C})
             
             8'b1011_1110: num = 5'd0;
             8'b0111_0111: num = 5'd1;
             8'b1011_0111: num = 5'd2;
             8'b1101_0111: num = 5'd3;
             
             8'b0111_1011: num = 5'd4;
             8'b1011_1011: num = 5'd5;
             8'b1101_1011: num = 5'd6;
             8'b0111_1101: num = 5'd7;  
             
             8'b1011_1101: num = 5'd8;
             8'b1101_1101: num = 5'd9;
             8'b1110_0111: num = 5'd10;
             8'b1110_1011: num = 5'd11;  
             
             8'b1110_1101: num = 5'd12;
             8'b1110_1110: num = 5'd13;
             8'b0111_1110: num = 5'd14;
             8'b1101_1110: num = 5'd15;  
           endcase
			  end
		begin
			if(num == 5'b1_0000)
				begin
					if(count_num == 32'b0)begin
						count_num = 32'd100001;end
					count_num = count_num + 1'b1;
				end
			else if(count_num > 32'd100000)
				begin
					count_num = 32'b1;
				
					//移位
					begin
					out = out << 4;
					out[3:0] = num[3:0];
					end
				end
			end					
		end
end
endmodule   

补充:仿真时将防抖的部分注释掉

这里给出仿真波形图:

 

 

  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实验矩阵键盘实验 一、实验内容 1、编写程序,做到在键盘上每按一个数字键(0-F)用发光极管将该代码显示出来 。按其它键退出。 2、加法设计计算器,实验板上有12个按键,编写程序,实现一位整数加法运算功能 。可定义"A"键为"+"键,"B"键为"="键。 实验目的 1. 学习独立式按键的查询识别方法。 2、 非编码矩阵键盘的行反转法识别方法。 三、实验说明 1、MCS51系列单片机的P0~P3口作为输入端口使用时必须先向端口写入"1"。 2、用查询方式检测按键时,要加入延时(通常采用软件延时10~20mS)以消除抖动。 3、识别键的闭合,通常采用行扫描法和行反转法。行扫描法是使键盘上某一行线为 低电平,而其余行接高电平,然后读取列值,如读列值中某位为低电平,表明有键按下 ,否则扫描下一行,直到扫完所有行。 行反转法识别闭合键时,要将行线接一并行口,先让它工作在输出方式,将列线也接 到一个并行口,先让它工作于输入方式,程序使CPU通过输出端口在各行线上全部送低电 平,然后读入列线值,如此时有某键被按下,则必定会使某一列线值为0。然后,程序对 两个并行端口进行方式设置,使行线工作于输入方式,列线工作于输出方式,并将刚才 读得的列线值从列线所接的并行端口输出,再读取行线上输入值,那么,在闭合键所在 行线上的值必定为0。这样,当一个键被接下时,必定可以读得一对唯一的行线值和列线 值。 由于51单片机的并口能够动态地改变输入输出方式,因此,矩阵键盘采用行反转法识 别最为简便。 行反转法识别按键的过程是:首先,将4个行线作为输出,将其全部置0,4个列线作 为输入,将其全部置1,也就是向P1口写入0xF0;假如此时没有人按键,从P1口读出的值 应仍为0xF0;假如此时1、4、7、0四个键中有一个键被按下,则P1.6被拉低,从P1口读 出的值为0xB0;为了确定是这四个键中哪一个被按下,可将刚才从P1口读出的数的低四 位置1后再写入P1口,即将0xBF写入P1口,使P1.6为低,其余均为高,若此时被按下的键 是"4",则P1.1被拉低,从P1口读出的值为0xBE;这样,当只有一个键被按下时,每一个 键只有唯一的反转码,事先为12个键的反转码建一个表,通过查表就可知道是哪个键被 按下了。 四、接线方法 键盘连接成4×4的矩阵形式,占用单片机P1口的8根线,行信号是P1.0- 1.3,列信号是P1.4-1.7。 五、实验电路 参考学习板说明书P14。 六、参考程序 "程序一: " " " "/***********************************************************" "**** " "功能:4*4矩阵键盘,LED显示所按的键 " "作者:txl " "时间:2009-04 " "版本:V1.0 " "************************************************************" "***/ " "#include<reg52.h> " "#define uint unsigned int " "#define uchar unsigned char " " " "sbit wei1=P2^0; " " " " " "uchar code table[]={0xC0,0xF9,0xA4,0xB0, " "0x99,0x92,0x82,0xF8, " "0x80,0x90,0x88,0x83, " "0xC6,0xA1,0x86,0x8E};//共阳数码管码表 " "//全局变量 " "uchar num,temp,num1; " "//函数声明 " "void delay(uint z); " "uchar keyscan(); " "void display(uchar aa); " " " "void main() " "{ " "num=1; " "wei1=0; " "P0=0xC0; " " " " " "while(1) " "{ " " " "display(keyscan()); " "} " "} " " " " " "void display(uchar aa) " "{ " "P0=table[aa-1]; " "} " " " " " " " "uchar keyscan() " "{ " "P1=0xfe; " "temp=P1; " "temp=temp&0xf0; " "while(temp!=0xf0) " "{ " "delay(5); " "temp=P1; " "temp=temp&0xf0; " "while(temp!=0xf0) " "{ " "temp=P1; " "switch(temp) " "{ "
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值