51单片机-第3节、独立按键控制LED

在这一节,老师教了4个实验:3-1 独立按键控制LED亮灭

                                                 3-2 独立按键控制LED灯状态

                                                 3-3 独立按键控制LED显示二进制

                                                 3-4 独立按键控制LED移位

       如图3-1所示,为独立按键模块的原理图。K1-K4为四个按键,按键右边连接GND(表示电源负极,低电平),按键左边连接P30-P31。要注意的是,单片机开发工程师这里搞错了,按键K1对应的是P31,K2-P30,K3-P32,K4-P33。

图3-1

        IO口(输入输出接口):input/output 口,可以通过引脚向CPU里输入数据,CPU也可以通过引脚输出电压信号。单片机通电时候,所有IO口默认高电平,即直接读寄存器值为1。图3-2中,P00-P37这些全是IO接口。

        如图3-2所示,我们直接找到独立按键对应的关键部分P30-P33。松开按键,P3相对于GND电位差5V,高电平;按下时,P3和GND导通,同等电位,电位差为0V,低电平。

        也就是说,如果按键松开,直接读寄存器,应该是高电平,值为1。如果按键按下,直接读寄存器值应该为0。根据这个特点我们可以检测按键是否被按下。比如P3_1==0,则表示按键K1被按下。

        我们向寄存器写一个值,它就会送到IO接口上;寄存器还可以检测IO口电平,然后再读回(1/0)到寄存器中。简单来说,就是寄存器是双向的,它既可以给IO口值,也可以根据IO的状态读回值。展现在按键上效果就是:如果按键松开,IO接口是高电平,寄存器读值为1;如果按键按下,IO接口是低电平,寄存器读值为0。根据这个特点我们可以检测按键是否被按下。

图3-2

        按键松开时,金属弹片凸起,开关断开,如图3-3左边第三个图所示。按键按下时,金属弹片变平,开关连接,如图3-3右边第三个图所示。

图3-3

3-1 独立按键控制LED亮灭

按下按键K1亮灯D1,松开按键K1灭灯D1。按键有4个:K1-K4,灯有8个:D1-D8

#include <REGX52.H>

void main()
{
	while(1)
	{
		 if(P3_1==0)
			 P2_0=0;
		 else
			 P2_0=1;
	}
}

  同时按下按键K1和K2亮灯D1,松开按键K1和K2灭灯D1。

#include <REGX52.H>

void main()
{
	while(1)
	{
		 if(P3_1==0&&P3_0==0)
			 P2_0=0;
		 else
			 P2_0=1;
	}
}

 3-2 独立按键控制LED灯状态

        按键使得LED长亮功能时,会遇到图3-3中金属弹片抖动的问题,也就是按键抖动。通常我们采用延时的方法,帮助我们度过按键抖动的过程。通俗点说,就是按键如果抖动10ms,我们就延时10ms,,这样我们就感受不到因按键抖动而产生的LED灯的闪烁了。

图3-4

        按键消抖,检测松手,才改变LED灯的状态,使按下按键后长亮或长灭。

#include <REGX52.H>

void Delay(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}	
}


void main()
{
	while(1)
	{
		if(P3_1==0)
		{
			Delay(20);
			while(P3_1==0);
			Delay(20);
			
			P2_0=~P2_0;
		}	
	}
}

图3-5

        如图3-5所示,方框1代码为按键消抖的延时代码,这是按键实现LED常亮,必写的代码。第1个Delay(20)是为了消除按键按下时的抖动;第二个Delay(20)是为了消除按键送开始的抖动。按键按下的时候,执行while空循环和P2_1取反操作。   

        方框2为对灯取反操作,前面说了,单片机通电时候,所有IO口默认高电平,直接读寄存器值为1。因此P2_0默认是1,高电平,D1灯没亮,取反之后变为0,D1灯亮。

        注意:按键在按住的时候,灯并没有亮或者灭;而是按完之后,长亮或长灭。这是与第一个实验不同的地方,3-1实验按住按键灯亮,松开按键灯灭。也就是说,3-1实验,按住按键,P2_0直接就等于0,灯亮;松开按键,P2_0直接就等于1,灯灭。但是在3-2实验,想通过按键控制LED常亮或者长灭,按住按键,P2_0没有立刻取反(P2_0没有取反变为0),而是等松开按键的瞬间(也就是退出if 按下按键这个循环后),P2_0直接变成了0或者1。

        重点:按键消抖,检测松手,才改变LED灯的状态

3-3 独立按键控制LED显示二进制

        实现状态:通过不停的按下按键(按下按键后,灯会常亮,所以说会有按键抖动,需要消抖),使得灯以二进制的方式,不断往上加一,达到用灯来表示按键次数。

#include <REGX52.H>

void Delay(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

unsigned char LEDnum;
void main()
{
	while(1)
	{
		if(P3_1==0)  //P3_1±íʾµÚÒ»¸ö°´¼ü
		{
			Delay(20);
			while(P3_1==0);
			Delay(20);

			LEDnum++; 
			P2=~LEDnum;  
		}
	}
}

unsigned char LEDnum=0;//unsigned char直接定义8位二进制的数字,刚好符合单片机8位寄存器。

        在void main主函数里面写unsigned char LEDnum=0则为局部变量,局部变量必须赋初始值。全局变量则不需要,如果不给初始值,则默认为0。

        P2代表的8位二进制数,而P2_0只代表一位二进制数;另外刚开始P2=1111 1111,此时P2为为8位寄存器最大的数,如果继续给P2加1,则会溢出,变为0000 0000。所以我们经常用unsigned char定义变量,因为unsigned char LEDnum,数范围在0-255(1+2+4+8+16+32+64+128)之间,刚好符合8位寄存器,最大值为1111 1111(255),如果LEDnum继续加1,则会溢出,变为0000 0000,符合寄存器的情况。 unsigned char常用来表示寄存器(8位)。

3-4 独立按键控制LED移位

按下K1键,往左边移一位,以LED灯来展示。

//这段代码,按下按键K1,LED第一个灯才会亮

#include <REGX52.H>

void Delay(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

unsigned char LEDnum;
void main()
{
//	P2=~(0x01);
	while(1)
	{
		if(P3_1==0)
		{
			Delay(20);
			while(P3_1==0);
			Delay(20);
			
			
			if(LEDnum>=8)
			{
				LEDnum=0;
			}
			P2=~(0x01<<LEDnum);
			LEDnum++;
		}
	}
}

下面这段代码,还没按K1键,LED第一个灯就亮了。

#include <REGX52.H>

void Delay(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

unsigned char LEDnum;
void main()
{
	P2=~(0x01);
	while(1)
	{
		if(P3_1==0)
		{
			Delay(20);
			while(P3_1==0);
			Delay(20);
			
			LEDnum++;
			if(LEDnum>=8)
			{
				LEDnum=0;
			}
			P2=~(0x01<<LEDnum);	
		}
	}
}

按下K1键,往左边移一位;按下K2键,往右边移一位,以LED灯来展示。

#include <REGX52.H>

void Delay(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

unsigned char LEDnum;
void main()
{
	P2=~(0x01);
	while(1)
	{
		if(P3_1==0)
		{
			Delay(20);
			while(P3_1==0);
			Delay(20);
			
			LEDnum++;
			if(LEDnum>=8)
			{
				LEDnum=0;
			}
			P2=~(0x01<<LEDnum);	
		}
		if(P3_0==0)
		{
			Delay(20);
			while(P3_0==0);
			Delay(20);
					
			if(LEDnum==0)
				LEDnum=7;
			else
				LEDnum--;
			P2=~(0x01<<LEDnum);	
			
		}
	}
}

实现这个功能,我自己写的代码

#include <REGX52.H>

void Delay(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

unsigned char LEDnum;
void main()
{
	P2=~(0x01);
	while(1)
	{
		if(P3_1==0)
		{
			Delay(20);
			while(P3_1==0);
			Delay(20);
			
			LEDnum++;
			if(LEDnum>=8)
			{
				LEDnum=0;
			}
			P2=~(0x01<<LEDnum);	
		}
		if(P3_0==0)
		{
			Delay(20);
			while(P3_0==0);
			Delay(20);
			
			
			if(LEDnum<=0)
				LEDnum=8;
			LEDnum--;
			P2=~(0x01<<LEDnum);	
			
		}
	}
}

到此,独立按键控制LED灯,已全部写完。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值