C51与4*4矩阵键盘

  之前做了个密码锁因为代码写的比较乱,现在想将各个部分的函数整理一下分别封装起来在主函数中直接调用,从而使代码更精简,也提高了程序的移植性。文章分享的内容是整理后的代码加上一些注释。

硬件部分键盘由16个按键组成,将每行4个的按键连在一起,再将每列4个的按键连在一起,就得到了8条支线分别将其接到单片机的io上。如下图

 电路搭建好了接下来就是代码部分了,这里我使用的是行列扫描法。

行列扫描法是先确定每行是否有按键被按下,再确定列是否有按键被按下。

行:先给P1端口的低四位(接行的io)高电平、高四位(接列的io)低电平。

当某个按键被按下时该按键所处的行为低电平,也就是接该行的io口为0。因为开始时我们已经给接列的io赋低电平相当于接地,在按键被按下时电路短接这时接行的io电平被拉低相当于接地,而我们可以通过读取P1端口的值,然后取出低四位来确定哪一行有按键被按下。

列:当确定被按下按键的行后,反过来给P1端口的低四位(接行的io)低电平、高四位(接列的io)高电平,再读取P1端口的值,然后取出高四位来确定哪一列有按键被按下。

当经过行列扫描后就会得到一个8位的二进制数解读一下就可以得到一个唯一得坐标了。

代码部分如下

键盘的相关函数

#include"butto_16.h"

void Delay_ms(int z)//1ms延时
{
 int x,y;
 for(x=z;x>0;x--);
  for(y=110;y>0;y--);
}

unsigned char saomiao()     //4*4键盘扫描函数
{
	unsigned char row,column;//记录行的4位数据、记录列的4位数据
	P1=0x0f; //P1=0000 1111 
	row=P1&0x0f;
	if(row!=0x0f)//检测每行按键是否被按下
	{
		Delay_ms(1);
		if(row!=0x0f)
		{
			row=P1&0x0f;//取出低4位数据
			 /*  1&0为0、1&1为1 */
			
			P1=row|0xf0;  
			column=P1&0xf0;//取出高4位数据
			
			return(column+row);//把行列的数据整合获得按键的唯一坐标
		}
	}
	return(0xff);//返回按键没被按下
}

unsigned int anjian_16()       //键盘电平转码信息函数
{
	unsigned char key;
	unsigned int a;
	key=saomiao();//获取键盘扫描的坐标数据
	switch(key)//转码信息
	{
        case 0xee:a=1;break;  //P=1110 1110  坐标(1,1)
		case 0xde:a=2;break;  //P=1101 1110  坐标(2,1)
		case 0xbe:a=3;break;  //P=1011 1110  坐标(3,1)
		//case 0x7e:a=;break; //P=0111 1110  坐标(4,1)
		case 0xed:a=4;break;
		case 0xdd:a=5;break;
		case 0xbd:a=6;break;
		//case 0x7d:a=;break;
		case 0xeb:a=7;break;
		case 0xdb:a=8;break;
		case 0xbb:a=9;break;
        //case 0x7b:a=;break;
		case 0xe7:a=0;break;
		//case 0xd7:a=;break;
		//case 0xb7:a=;break;		
		//case 0x77:a=;break;
		case 0xff:return(10);    //按键没按下
	}
	return a;
}

键盘的相关函数的头文件

/*
4*4矩阵键盘函数调用头文件

函数名    anjian_16()
输入参数  无
返回参数  被按下按键的坐标所代表的数据内容(数据内容可自定义)
*/
#ifndef __BUTTO_16
#define __BUTTO_16

#include<reg52.h>


unsigned int anjian_16();       //键盘电平转码信息函数

#endif

主函数

#include<reg52.h>
#include"74HC595.H"  
#include"butto_16.h"  //使用键盘函数的头文件


void main()
{
	int b[8]={10,10,10,10,10,10,10,10},c,d=0;
    while(1)
		{
			for(c=0;c<8;c++)
			{
				if(anjian_16()!=10&&d<8)//判断按键是否被按下并输入数据个数小于等8个
				{
					b[d]=anjian_16();//通过键盘输入数据
				    d++;
					while(1)if(anjian_16()==10)break;//等待按键释放
					//delay(300);
				}
				Send_CP(c,b[c]);//数码管打印数据
	   		    delay(3);
				Send_Byte(0xff);//消隐
			}
		}			
}

仿真效果

以上就是本次分享的全部内容了。

  • 23
    点赞
  • 143
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值