矩阵按键的应用2.0(行列式扫描法+独立按键)

使用某C51学习板,编写一个C51程序,实现如下功能

1)启动时,数码管显示11, 代表第1行第1列

2)按下矩阵键盘中某键时,数码管显示按键对应的行号和列号,例如23代表2行3列

3)按下K1时,行号显示减小1,如行号等于1不再减小

4)按下K2时,行号显示增加1,如行号等于4不再增加

5)  按下K3时,列号显示减小1,如列号等于1不再减小

6)   按下K4时,列号显示增加1,如列号等于4不再增加

#include <reg51.h>

typedef unsigned int u16;	//对系统默认数据类型进行重定义
typedef unsigned char u8;

//定义四个独立按键
sbit K1=P3^1;
sbit K2=P3^0;
sbit K3=P3^2;
sbit K4=P3^3;


//定义矩阵按钮的端口
#define AnNiu P1

//定义数码管段码口
#define SMG	P0

//定义数码管位选信号控制脚
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

//共阴极数码管显示0~F的段码数据
u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
				          0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

u16 x=1;//定义一个变量存储按键的值
u16 num=0;//定义一个变量存储按键返回的值	
																		
									
//延时
void delay_10us(u8 ten_us)
{
	while(ten_us--);	
}


//矩阵按键
u16 key_discern(void)
{	
	
	AnNiu=0xf7;//第一列为低电平
	if(AnNiu!=0xf7)
	{
		delay_10us(1000);
		switch(AnNiu)
		{
			case 0x77:x=1;break;
			case 0xb7:x=5;break;
			case 0xd7:x=9;break;
			case 0xe7:x=13;break;

		}	
	}	
	AnNiu=0xfb;//第二列为低电平
	if(AnNiu!=0xfb)
	{
		delay_10us(1000);
		switch(AnNiu)
		{
			case 0x7b:x=2;break;
			case 0xbb:x=6;break;
			case 0xdb:x=10;break;
			case 0xeb:x=14;break;

		}	
	}		
	AnNiu=0xfd;//第三列为低电平
	if(AnNiu!=0xfd)
	{
		delay_10us(1000);
		switch(AnNiu)
		{
			case 0x7d:x=3;break;
			case 0xbd:x=7;break;
			case 0xdd:x=11;break;
			case 0xed:x=15;break;

		}	
	}	
	AnNiu=0xfe;//第四列为低电平
	if(AnNiu!=0xfe)
	{
		delay_10us(1000);
		switch(AnNiu)
		{
			case 0x7e:x=4;break;
			case 0xbe:x=8;break;
			case 0xde:x=12;break;
			case 0xee:x=16;break;

		}	
	}		
	return x;
}	

//显示数码管									
void smg_display(void)
{	
	//行的数码管
	LSC=1;LSB=1;LSA=1;
	SMG=gsmg_code[(num-1)/4+1];//传送段选数据
	delay_10us(100);//延时一段时间,等待显示稳定
	SMG=0x00;//消隐
	
	//列的数码管
	LSC=1;LSB=1;LSA=0;
	SMG=gsmg_code[(num-1)%4+1];//传送段选数据
	delay_10us(100);//延时一段时间,等待显示稳定
	SMG=0x00;//消隐
}


void main()
{		
	while(1)
	{	
				
		num=key_discern();
		
		//按键消抖
		if(K1==0||K2==0||K3==0||K4==0)
		{
			delay_10us(1000);
			
			//K1按键控制行的减
			if(K1==0&&x>4&&x<=16)
			{
				x=x-4;
        while(1)//等待K1松开
				{
					;
					if(K1!=0)
						break;
				}					
			}
			
			//K2按键控制行的加			
			if(K2==0&&x>=1&&x<=12)
			{
				x=x+4;
        while(1)//等待K2松开
				{
					;
					if(K2!=0)
						break;
				}					
			}
			
			//K3按键控制列的减			
			if(K3==0&&x>1&&x<=16)
			{
				if((x-1)/4==(x-1-1)/4)//检测是否在同一行(现键位的行与前一个键位的行比较)
					x=x-1;
        while(1)//等待K3松开
				{
					;
					if(K3!=0)
						break;
				}					
			}

			//K4按键控制列的加			
			if(K4==0&&x>=1&&x<16)
			{
				if((x-1)/4==(x+1-1)/4)//检测是否在同一行(现键位的行与后一个键位的行比较)
					x=x+1;
        while(1)//等待K4松开
				{
					;
					if(K4!=0)
						break;
				}					
			}
			
		}	
		//显示数码管
		smg_display();
	}		
}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值