51单片机——实验3:按键扫描

一、实验任务:

1.用单个按键控制数码管显示0-9-A-F(按一下,加1)

2.用矩阵键盘控制数码管显示矩阵键盘的位置编号(01-02----12)

二、实验目的及原理

1.实验目的:了解键盘的三种工作方式;掌握独立按键、矩阵式键盘的工作原理及编程方法;掌握如何进行按键消抖。

2.实验原理:通过0,1表示按键的状态;矩阵式键盘通过依次读取行列数据确定按键状态。

三、实验中使用的仪器与材料

Keil、PZ-ISP、普中科技51单片机、数码管、发光二极管、独立按键、矩阵式按键

四、实验方案、步骤及原始记录(数据、图表、计算等)

1.任务一:单个数码管静态显示独立按键编号

(1)用keil编写程序,输出hex文件

#include<reg52.h>

unsigned char code Tab[]=     //共阴数码管段码表0-F
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

sbit key =P3^1; 
void Delay1ms(unsigned int xms)  //延时1ms函数
{
   unsigned char i,j;
   while(xms)
   {
     i = 2 ;
     j = 239 ;
     do
     {
        while (--j);
      }
     while (--i);
     xms--;
   }
}

void main ()    //主函数
{
		unsigned char n	= 0 ;   //局部变量计位数n是段码表的位置
		P0= 0x3f;    //定义初始值显示0
		while(1)
		{

			if(key == 0)		//判断按键是否按下
			{
				Delay1ms(20);    //消抖
				
				if(key==0)   //再次判断
				{
					while(key==0) //按键松开检测
					{;}
					n++;
					if(n>15)  //判断是否超出断码表,超出置0
					n=0;
					Delay1ms(300);
					P0=Tab[n];
				 }	
			 }
		}
}

(2)将输出的hex文件烧录到开发板上

 

2.任务二:两个数码管动态扫描显示矩阵键盘按键编号

(1)用keil编写程序,输出hex文件

#include<reg52.h>    

typedef unsigned int u16;	  
typedef unsigned char u8;

#define GPIO_DIG P0
#define GPIO_KEY P1

sbit LSA = P2^2;  //P2_2,P2_3,P2_4控制数码管位选
sbit LSB = P2^3;
sbit LSC = P2^4;
sbit key = P3^0;

u8 KeyValue;
u8 DisplayData[2]; //分别包含个位、十位
u8 code DIG_CODE[17]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
					0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //0-F数字

void delay(u16 i)  //延时函数
{
	while(i--);	
}


void KeyDown(void)  //判断哪个按键被按下
{
	char a=0;
	GPIO_KEY=0x0f; //行线置0,列线置1,读取列线
	if(GPIO_KEY!=0x0f)   //!=0x0f,说明有按键按下
	{
		delay(1000);  //延时
		
		if(GPIO_KEY!=0x0f) //再次判断有无按键按下
		{	
			GPIO_KEY=0X0F; //行线置0,列线置1,读取列线
			switch(GPIO_KEY)
			{
				case(0X07):	KeyValue=0;break; //列线P13被置0,说明第一列有按键被按下 
				case(0X0b):	KeyValue=1;break; //第二列有按键被按下
				case(0X0d): KeyValue=2;break; //第三列有按键被按下
				case(0X0e):	KeyValue=3;break; //第四列有按键被按下
			}
			
			GPIO_KEY=0XF0; //列线置0,行线置1,读取行线
			switch(GPIO_KEY)
			{
				case(0X70):	KeyValue=KeyValue;break; //行线P17被置0,说明第一行有按键被按下 
				case(0Xb0):	KeyValue=KeyValue+4;break;//第二行有按键被按下
				case(0Xd0): KeyValue=KeyValue+8;break;//第三行有按键被按下
				case(0Xe0):	KeyValue=KeyValue+12;break;//第四行有按键被按下
			}
		}
	}
}
void DigDisplay() //数码管显示
{
	u8 i;
	
	for(i=0;i<2;i++)
	{
		switch(i)	 //i=0首先显示个位 i=1显示十位
		{
			case(0):
				LSA=0;LSB=0;LSC=0; break; //1号数码管亮 个位
			case(1):
				LSA=1;LSB=0;LSC=0; break; //2号数码管亮 十位
		}
		
		GPIO_DIG=DisplayData[i]; //数码管显示数字
		delay(10); //延时
		
		GPIO_DIG=0x00;//清屏
	}
}
void main(void)
{

	while(1)
	{
		KeyDown();//确认所按按键
	if(KeyValue>0 && KeyValue< 10) //1-9按键
	{
		DisplayData[1] = ~DIG_CODE[0]; //十位显示0
		DisplayData[0] = ~DIG_CODE[KeyValue];	//个位显示键值
	}
	else
 { 
		DisplayData[1] = ~DIG_CODE[KeyValue/10];      //十位           
		DisplayData[0] = ~DIG_CODE[KeyValue%10];     //个位
 }

		DigDisplay();
}
	}

(2)将输出的hex文件烧录到开发板上

五、实验结果及分析、实验过程中遇到问题及处理过程说明

1.任务一结果:

7616a98f85a147ecaab6fb2277647e34.jpeg

2.任务二结果:

b26cf22fd7f84c15977ceff279b4a5b8.jpeg

3.遇到的问题及处理过程

       在网上看到一个对端口进行位操作时未用sbit,直接P1_3,非常不理解,仔细观察他的代码后发现他的头文件为<regx52.h>,而我一般用的是<reg52.h>,查找后发现这两个头文件的位操作是不一样的,<regx52.h>可以直接P1_3,而<reg52.h>必须是P1^3;

六、实验总结及心得体会

       通过本次实验,我学会了独立按键、矩阵式按键的原理及编程应用,理解了软件消抖的内部逻辑。编写代码时可以利用网上的资源,重在理解其逻辑,要看懂,还要结合自己的实验任务对代码进行修改。

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值