详解51单片机按键控制流水灯原理

1、按键的使用

<1>独立按键的原理图

按键所对应的引脚为P3的0、1、2、3引脚口,并且这里总共有四个独立按键,它们公共的一段都接到了GND电源的负极。这样我们就知道按键上电的默认电平为高电平。所以我们只需要控制按键按下时给一个低电平0,不按下时默认高电平1就行。

 <2>按键控制LED灯的亮灭

按键消抖:抖动是机械按键存在的现象,是必须要进行处理的。一般处理有两种方式:一种是硬件消抖,另一种是软件消抖。硬件消抖不仅会增加开发成本,而且有时不稳定。一般都会选择软件消抖。

#include  "reg51.h"	

sbit LED = P2^0;//LED灯引脚定义
sbit KEY = P3^1;//按键引脚定义

void delay(int x)//延时函数(ms)
{
	int i,j;
	for(i=0;i<x;i++)
		for(j=0;j<100;j++);
}

void main()
{
    while(1)
    {
        if(!KEY)//当按键按下时   
	    {
		    delay(15);//按键消抖
		    if(!KEY)//确定按键按下
		    {
		    	LED = !LED;//LED灯的状态取反
		    }
	    }
    }
}

if(!KEY)的含义:因为按键默认高电平,所以!KEY的值为0,当按下按键电平变为低电平,!KEY的值也就变为"非0";这样就可以做出判断了。

 注意:独立按键K1按键与K2按键按键网络编号是相反的,K1=P3^1、K2=P3^0。

2、独立按键控制LED灯

根据上一章流水灯、走马灯代码结合:

 LED流动正反方向中的type()函数与LED灯状态切换

#include "reg51.h"

#define LED P2

sbit KEY = P3^1;
bit direction;
char i;

void delay(int x)//延时函数(ms)
{
	int i,j;
	for(i=0;i<x;i++)
		for(j=0;j<100;j++);
}

void type()				//流水灯的翻转
{
	if(!direction)	  
	{ 		   
		if(++i>8)			//正向移动
			i=0;
	}
	else
	{ 		   
		if(--i<0)			//反向移动
			i=8;
	}
}

void main()
{
    LED = buf[i];//LED灯的默认流向
    while(1)
    {
        if(!KEY)
        {
            delay(15);
            if(!KEY)
                direction = !direction;
        }
    }
}

#include  "reg52.h"	
#define	LED	P2				//宏定义LED引脚
sbit  K0=P3^1;				//定义按键引脚口
sbit  K1=P3^0;
sbit  K2=P3^2;
sbit  K3=P3^3;
bit   key_mark,direction;			//两个标志位,key_mark用于结束循环;direction用于LED灯亮灭的翻转
char  Buf[] = {0xff,0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00}; 		//第一种流水灯方式,灯亮个数依次增加
char  Puf[] = {0xff,0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};			//第二种流水灯方式,灯依次位移一位
char i;					//全局标量i,用于各个循环的使用
int n = 100;		//全局变量n用于延时的使用

void delay(int x)//延时函数(ms)
{
	int i,j;
	for(i=0;i<x;i++)
		for(j=0;j<100;j++);
}

void speed()			//延时的加减
{
	if(!K1)
	{
		delay(15);
		if(!K1)
		{
			n += 100;			//加100ms
			if(n>1000)
				n=1000;
		}
	}
	if(!K2)
	{
		delay(15);
		if(!K2)
		{
			n -= 100;			//减100ms
			if(n<300)
				n=300;
		}
	}
}

void type()				//流水灯的翻转
{
	if(!direction)	  
	{ 		   
		if(++i>8)			//正向移动
			i=0;
	}
	else
	{ 		   
		if(--i<0)			//反向移动
			i=8;
	}
}

void mode1()		//模式1,当按下K0时,流水灯进行翻转
{
		if(!K0)
		{
			delay(15);
			if(!K0)
			{
				direction = !direction;//标志位direction状态取反
			}
		}
}

void mode2()		//模式2,当按下K1时流水灯使用第一种流水灯方式
{
	type();
	LED = Buf[i];   
	delay(n);		//延时n ms
}

void mode3()		//模式3,当按下K2时流水灯使用第二种流水灯方式
{
	type();
	LED = Puf[i];
	delay(n);
}

void mode4()		//模式4,当按下K3时,key_mark置为1,退出循环(在程序中起到一个暂停作用,用于流水灯状态切换的使用)
{
	if(!K3)
	{
		delay(15);
		if(!K3)
			key_mark = 1;
	}
}

void main()
{
	while(1)
	{
		if(!K1 && !key_mark)//判断按键是否按下K1,以及标志位key_mark是否为0(当key_mark不为0时说明此函数在其他循环中,则无法进入新循环)
		{
			delay(15);
			if(!K1)
			{
				while(!key_mark)
				{
					speed();					//引用函数,节省代码量以及书写的规范
					mode1();
					mode2();
					mode4();
				}
			}
		}
		if(!K2 && !key_mark)//判断按键是否按下K2,以及标志位key_mark是否为0(当key_mark不为0时说明此函数在其他循环中,则无法进入新循环)
		{
			delay(15);
			if(!K2)
			{
				while(!key_mark)
				{
					speed();
					mode1();
					mode3();
					mode4();
				}
			}
		}
		if(K0 || K1 || K2 ||K3)//没有按键按下时,标志位key_mark自动置0
			key_mark=0;
	}
}
物联沃分享整理
物联沃-IOTWORD物联网 » 详解51单片机按键控制流水灯原理

发表评论