单片机第1季:零基础学51单片机-按键

学习目标:

1.原理图
2.程序代码
3.键值检测与显示
4.按键消抖
5.完整的按键检测
6.矩阵键盘

学习内容:

1)原理图
独立按键
2)程序代码(监测按键少,可以采用位监测,多需要采用端口字节变量监测)

#include <reg51.h>

//当前要处理的是K1,对应P1.0 I/O口,操控的LED是LED1,对应P0.0
sbit key1 = P1^0;
sbit led1 = P0^0;

void delay(void)
{
	unsigned char i,j;
	
	for(i=0;i<100;i++)
		for(j=0;j<100;j++);
}
void main()
{
	while(1)
	{
		 //读key1引脚
		 if(key1==1)
		 {
		 	//没有按键
			led1=0;   // led1熄灭
		 }
		 else
		 {
		 	//有按键
			led1=1;	  // led1点亮
		 }
		 delay();	
	}	
}

3)键值检测与显示
键值
( 1 ) 一般的产品中按键都有很多, 对于整个程序来说一般都是把按键进行编码, 给每个按键一个对应的编码值, 就叫做按键的键值。
( 2 ) 在正式的比较庞大的程序中, 按键的检测部分和处理部分都是隔开的。这两部分隔开有利于各自部分的程序编写, 两部分之间用键值来连接。按键监测部分负责监测按键, 一旦发生一个按键事件就产生一个键值, 然后将键值传递给按键处理部分。
加入数码管显示键值
( 1 ) 整个程序包括2 部分: 1 部分做按键监测并且发出键值, 另一部分负责将接收到的键值显示在独立数码管上。

#include <reg51.h>

//当前要处理的是K1,对应P1.0 I/O口,操控的LED是LED1,对应P0.0
sbit key1 = P1^0;
sbit led1 = P0^0;

//独立数码管的段码表
unsigned char val[16] = {0xc0,0xf9,0xa4,0xb0,
						 0x99,0x92,0x82,0xf8,
						 0x80,0x90,0x88,0x83,
						 0xc6,0xa1,0x86,0x8e};

void delay(void)
{
	unsigned char i,j;
	
	for(i=0;i<100;i++)
		for(j=0;j<100;j++);
	
}
//数码管显示
void display(unsigned char num)
{
	P0 = val[num];
}

void main()
{
	unsigned char keynum = 0;
	char i=0;
	while(1)
	{
		 unsigned char i = 0;
		 for(i=0; i<8; i++)
		 {
		 	if((P1 & (0x1<<i))) == 0
			{
				keynum = i+1;
			}
		 
		 }
//		 if(P1 == 0xfe)
//		 {
//		 	keynum = 1;
//		 }
//		 if(key2 == 0)
//		 {
//		 	keynum = 2;
//		 }
//		 if(key3 == 0)
//		 {
//		 	keynum = 3;
//		 }
//		 if(key4 == 0)
//		 {
//		 	keynum = 4;
//		 }
//		 if(key5 == 0)
//		 {
//		 	keynum = 5;
//		 }
//		 if(key6 == 0)
//		 {
//		 	keynum = 6;
//		 }
//		 if(key7 == 0)
//		 {
//		 	keynum = 7;
//		 }
//		 if(key8 == 0)
//		 {
//		 	keynum = 8;
//		 }
	
		 delay();

		 display(keynum);
	
	}	

}

4)按键消抖

#include <reg51.h>

//当前要处理的是K1,对应P1.0 I/O口,操控的LED是LED1,对应P0.0
sbit key1 = P1^0;
sbit led1 = P0^0;

unsigned char dnum=0;

//独立数码管的段码表
unsigned char val[16] = {0xc0,0xf9,0xa4,0xb0,
						 0x99,0x92,0x82,0xf8,
						 0x80,0x90,0x88,0x83,
						 0xc6,0xa1,0x86,0x8e};

void delay(void)
{
	unsigned char i,j;
	
	for(i=0;i<100;i++)
		for(j=0;j<100;j++);
	
}
//数码管显示
void AddDisplay()
{

	dnum = dnum+1;
	if(dnum>15)
	{
		dnum = 0;
	}
	P0 = val[dnum];
}

void main()
{
	unsigned char keynum = 0;
	char i=0;
	while(1)
	{
		 unsigned char i = 0;
		 if(key1 == 0)
		 {
		 	 delay();
			 if(key1==0)
			 {
			 	AddDisplay();	
			 }
		 }
	
		 delay();
	
	}	

}

5)完整的按键检测
完整的按键检测
一次完整的按键事件
( 1 ) 按键事件就是按键操作过程中的不同状态切换
( 2 ) 一个完整的按键事件包括: 按下事件( 由高变低) 、弹起事件( 由低到高)
( 3 ) 一般都认为发生了一次完整的按键事件才算是用户操作了一次按键, 程序才会去处理按键, 所以在一次完整的按键事件中程序只会去处理一次按键。

#include <reg51.h>

// 当前要处理的是K1,对应P1.0IO口,操控的LED是LED1,对应P0.0

/*********************变量定义************************************/
sbit key1 = P1^0;
sbit key2 = P1^1;
sbit key8 = P1^7;



// 独立数码管的段码表
unsigned char val[16] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};



/*********************************** 函数声明 ***********************/
void AddDisplay(void);
void delay(void);
void delay10ms(void);

/******************************全局变量定义*************************/
unsigned char dnum = 0;

void main(void)
{
	unsigned char flag = 0;		// 默认状态等于0

	while (1)
	{
		if (key1 == 0)
		{
			// 发现1次低电平,有可能是按键按下,也有可能是抖动,软件消抖
			delay10ms();
			if (key1 == 0)
			{
				 // 10ms后还是低电平,说明真的是按键按下了,不是抖动
				 // 这里说明发现了一个按下事件
				//flag = 1;
				if (flag == 0)
				{
					AddDisplay();
					flag = 1;
				}
			}
		}
		else
		{
			// 电平 == 1
			delay10ms();
			if (key1 == 1)
			{
				// 说明弹起了
				if (flag == 1)
				{
					//AddDisplay();
					flag = 0;
				}
			}
		}

		delay(); 
	}
}


// 该函数将num数字送到独立数码管去显示
void AddDisplay(void)
{

	dnum = dnum + 1;
	if (dnum > 15)
	{
		dnum = 0;
	}

	P0 = val[dnum];
}

// 延时函数
void delay(void)
{
	unsigned char i, j;

	for (i=0; i<100; i++)
		for (j=0; j<200; j++);
}

void delay10ms(void)   //误差 0us
{
    unsigned char a,b,c;
    for(c=5;c>0;c--)
        for(b=4;b>0;b--)
            for(a=248;a>0;a--);
}

6)矩阵键盘
矩阵键盘

#include <reg51.h>

// P0端口接LED
// P0端口接数码管
// P3端口接矩阵键盘

#define LED P0
#define KEY P3

#define DIG P0

// 独立数码管的段码表
unsigned char val[16] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};

/*********************变量定义************************************/


/********************************* 函数声明 ***********************/
unsigned char GetKey(void);
void delay(void);

/******************************全局变量定义*************************/
void main(void)
{
	unsigned char key = 0;
	while(1)
	{
		key = GetKey();
		if(key != 0)
		{
			DIG = val[key];
		}
	}

}
unsigned char GetKey(void)
{
	unsigned char hang = 0, lie = 0;
	unsigned char keyvalue = 0;

	//第1回合第1步
	KEY = 0x0f;		  //从IO口输出,写IO口
	if(KEY != 0x0f)	  //从IO口输入,读IO口
	{
		//读出的不是0x0f说明有按键被按下
		//第1回合第2步,读出端口从读出值来判断哪一行
		
		//第一回合中算出行号
		switch(KEY)
		{
			case 0xfe:	hang = 1;  break;
			case 0xfd:	hang = 2;  break;
			case 0xfb:	hang = 3;  break;
			case 0xf7:	hang = 4;  break;
			default: 			   break;
		}
		delay();
		//第2回合第一步	
		KEY = 0xf0;
		if(KEY != 0xf0)
		{
			//第二回合中算出行号
			switch(KEY)
			{
				case 0xef:	lie = 1;  break;
				case 0xdf:	lie = 2;  break;
				case 0xbf:	lie = 3;  break;
				case 0x7f:	lie = 4;  break;
				default: 			  break;
			}
			//经过2个回合后hang和lie都知道了,然后根据hang和lie去计算键值即可
			keyvalue = (hang - 1) * 4 + lie;

			return keyvalue;
		}		
	}
	return 0;
}


// 延时函数
void delay(void)
{
	unsigned char i, j;

	for (i=0; i<100; i++)
		for (j=0; j<200; j++);
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值