单片机——C51实验含Proteus仿真(独立键盘,矩阵键盘)

  • 文章仅为本人学习记录,如有引用部分会另加说明引用出处

矩阵键盘检测原理:(独立键盘的原理在代码注释中很详细)

线反法的原理为:首先使P1口的高四位输出高电平,P1口低四位输出低电平,这时键盘的行线被拉高,列线被拉低。如果有按键按下,则某一条行线将被拉低,此时读取P1口高四位,读取到的将不再全为高电平,说明有按键按下。(在判断是否有按键按下这一点上,线反法与逐行逐列扫描法是一致的)根据读取到0值的I/O口所连接的行线,就可以判断出按下的按键位于哪一行。接下来使P1口的高四位输出低电平,P1口低四位输出高电平(即与上次输出的电平相反,因此称为线反法)。如果有按键按下,此时读取P1口低四位,读取到的将不再全为高电平,根据读取到0值的I/O口所连接的列线,就可以判断出按下的按键位于哪一列。综合按键所在的行线与列线,即可唯一确定按键所在位置,进而获取按键的键值。
————————————————
版权声明:本文为CSDN博主「星水天河」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44509533/article/details/107823449

代码部分

#include<reg52.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char

sbit LED_LE=P2^0;	//LED锁存器控制端
sbit Duan=P2^3;		//数码管段选锁存端
sbit Wei=P2^4;		//数码管位选锁存端
sbit D1=P1^0;		//灯组
sbit key1=P3^4;		//独立键盘P3^4

uchar code s[]={	//数码管段选0~9(高电平有效)
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar code ss[]={	//数码管段选0~9带小数点(高电平有效)
0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};
uchar code w[]={	//数码管位选值
0x00,0x01,0x02,0x04,0x08,0x10,0x20};

uint num=0;
uchar temp;
int fl=0;//按键标志位 

void delay(uint z)//延时函数
{
	uint x,y;
	for(x=z;x>0;x--)
		for(y=110;y>0;y--);
}

void UP_Duan(uint i)//更新段选
{
	Duan=1;
	P0=s[i];
	Duan=0;
}

void main()
{	
	//初始化位选和段选
	Wei=1;
	P0=~w[1];
	Wei=0;
	Duan=1;
	P0=0;
	Duan=0;

	P3=0xff;//初始化P3口的值
	while(1)
	{
		//独立键盘(延时消抖)
		/*if(key1==0)
		{
			delay(10);//消抖(软件延时跳过按下的抖动时间)
			if(key1==0)
			{
			   	D1=0;//按下按键时灯亮
				num++;
				if(num==10)
					num=0;
			}
			while(!key1);//消抖(检测按键是否松开)
			delay(10);//消抖(软件延时跳过松开的抖动时间)
			while(!key1);//消抖(再次检测按键是否松开)
		}	
		else
			D1=1;
		Duan=1;//无论按键是否按下都更新数码管
		P0=s[num];
		Duan=0;*/

		/*//独立键盘(标志位消抖)
		if(key1==0&&fl==0)//按键按下,先置标志位f1为1,且点亮灯
		{
			fl=1;
			D1=0;
		}
		if(key1==1&&fl==1)//按键松开,灯灭且更新num的值
		{
			fl=0;
			D1=1;
			num++;
			if(num==10)
				num=0;
		}
		Duan=1;//无论按键是否按下都更新数码管
		P0=s[num];
		Duan=0;*/

		//矩阵键盘
		//检测第一行
		P3=0xfe;//低位赋值
		temp=P3;//读取变化
		temp=temp&0xf0;//只取高位的变化
		while(temp!=0xf0)//检查是否有键按下
		{
			delay(5);
			temp=P3;//重新读取
			temp=temp&0xf0;
			while(temp!=0xf0)//确认是否有键按下
			{
				temp=P3;//实时读取按下哪个键,否则无法检测该行其他按键被按下
				switch(temp)
				{
					case 0xee:num=0;
						break;
					case 0xde:num=1;
						break;
					case 0xbe:num=2;
						break;
					case 0x7e:num=3;
						break;
				}
				while(temp!=0xf0)//检查是否松开按键,不检查无法出这个循环导致其他行的按键按下无法被检测到
				{
					temp=P3;//一直更新P3口的值,检查是否松开按键
					temp=temp&0xf0;
				}
				UP_Duan(num);//更新段选
			}
		}	
		//检测第二行
		P3=0xfd;
		temp=P3;
		temp=temp&0xf0;
		while(temp!=0xf0)//检查是否有键按下
		{
			delay(5);
			temp=P3;
			temp=temp&0xf0;
			while(temp!=0xf0)//重新读取,确认是否有键按下
			{
				temp=P3;
				switch(temp)
				{
					case 0xed:num=4;
						break;
					case 0xdd:num=5;
						break;
					case 0xbd:num=6;
						break;
					case 0x7d:num=7;
						break;
				}
				while(temp!=0xf0)
				{
					temp=P3;//一直更新P3口的值,检查是否松开按键
					temp=temp&0xf0;
				}
				UP_Duan(num);
			}
		}
		//检测第三行
		P3=0xfb;
		temp=P3;
		temp=temp&0xf0;
		while(temp!=0xf0)//检查是否有键按下
		{
			delay(5);
			temp=P3;
			temp=temp&0xf0;
			while(temp!=0xf0)//重新读取,确认是否有键按下
			{
				temp=P3;
				switch(temp)
				{
					case 0xeb:num=8;
						break;
					case 0xdb:num=9;
						break;
					case 0xbb:num=10;
						break;
					case 0x7b:num=11;
						break;
				}
				while(temp!=0xf0)
				{
					temp=P3;//一直更新P3口的值,检查是否松开按键
					temp=temp&0xf0;
				}
				UP_Duan(num);
			}
		}		
		//检测第四行
		P3=0xf7;
		temp=P3;
		temp=temp&0xf0;
		while(temp!=0xf0)//检查是否有键按下
		{
			delay(5);
			temp=P3;
			temp=temp&0xf0;
			while(temp!=0xf0)//重新读取,确认是否有键按下
			{
				temp=P3;
				switch(temp)
				{
					case 0xe7:num=12;
						break;
					case 0xd7:num=13;
						break;
					case 0xb7:num=14;
						break;
					case 0x77:num=15;
						break;
				}
				while(temp!=0xf0)
				{
					temp=P3;//一直更新P3口的值,检查是否松开按键
					temp=temp&0xf0;
				}
				UP_Duan(num);
			}
		}			 	 				
	}
}

仿真部分

矩阵键盘原理图:

 对应工程原理图见:(96条消息) 单片机——C51实验含Proteus仿真(锁存器,流水灯,继电器,数码管静态显示,蜂鸣器)_暴躁海葵的博客-CSDN博客

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值