51单片机(三)独立按键控制LED

❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。
☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋。
🌙专栏目标:实现从零基础入门51单片机和STM32单片机,力求在玩好单片机的同时,能够了解一些计算机的基本概念,了解电路及其元器件的基本理论等。

⭐️ 专栏主要内容: 主要学习51单片机的功能、各个模块、单片机的外设、驱动等,最终玩好单片机和单片机的外设,全程手敲代码,实现我们所要实现的功能。
🌴 专栏说明 :如果文章知识点有错误的地方,欢迎大家随时在文章下面评论,我会第一时间改正。让我们一起学习,一起进步。
💑专栏主页:http://t.csdn.cn/HCD8v

本学习过程参考:https://space.bilibili.com/383400717

单片机安装软件、各种资料以及源码的路径:
https://pan.baidu.com/s/1vDTN2o8ffvczzNQGfyjHng
提取码:gdzf

一、本节背景和目标

1.1 独立按键的原理(很重要!!!)


独立按键在开发板上的位置如下图所示,左右到右依次是K1、K2、K3、K4
在这里插入图片描述

独立按键的原理图如下所示:

在这里插入图片描述

其在MCU上的位置如下所示:
在这里插入图片描述
由上面两张图可以知道,独立按键是接在MCU的P3.0口到P3.3口的;

可以看到,独立按键的右端是接地的;这里需要注意,独立按键跟LED灯的原理有区别,LED灯是通过高低电平通电,进而使灯亮;而独立按键不一样,独立按键的一端接地,独立按键就是一个开关;以K1为例,K1右端是GND,左端是RXD,我们知道,单片机在刚上电时,所有i/o口默认都是高电平的;所以当K1按键没有按下时,RXD是高电平,但当K1按键按下时,电路进行了连通,RXD接通了GND,所以RXD此时变成了低电平。

从上一篇文章中我们知道了,在寄存器中写入一个值,该值就会同步到对应的i/o口上;其实反之也成立,即通过寄存器可以读到i/o口的状态,是高电平还是低电平。

所以当按键没有按下时,寄存器读到的该i/o的状态就是高电平(即1);反之,当按键按下时,寄存器就可以读到该i/o口的状态为低电平(即0);我们则可以通过寄存器读到的i/o口的状态是高电平还是低电平,就知道按键是按下还是松开了,进一步可以写程序对小灯进行控制。

1.2 本节目标

目标1:独立按键控制LED亮灭

K1控制LED灯D1的亮灭,即按下K1(持续不松开)时D1亮,松开D1时D1灭;如下图所示

在这里插入图片描述

目标2:独立按键控制LED状态

还是K1控制D1灯,现象是K1按一下并松开,D1点亮;再按一下并松开,D1灭;再按一下并松开,D1变亮;再按一次并松开,D1灭;如下图

在这里插入图片描述

目标3:独立按键控制LED显示二进制

每按下并松开一次K1,LED灯点亮一次,多次按下并松开,实现按照二进制递增的顺序进行点亮;具体的说,可以将8个等比作8个二进制数字,最右边的亮表示1,右边第二个灯亮表示2,右边第三个灯亮表示4,右边第四个灯亮表示8;以此类推;也可以知道,右边第一个和右边第二个灯同时亮表示3(1+2)以此类推;每次按下并松开一次K1,此8个灯中亮起的一个或几个灯组成的数字就加1;如下图所示:

在这里插入图片描述

目标4:独立按键控制LED移位

按下K1并松开时,LED灯向左移一位;按下K2时,LED灯向右移一位。

K1每按下一次,LED灯向左移动一位:
在这里插入图片描述

K2每按下一次,LED灯向右移动一位:

在这里插入图片描述

二、独立按键控制LED亮灭

代码路径:51单片机入门教程资料\课件及程序源码\程序源码\KeilProject\3-1 独立按键控制LED亮灭
代码实现:

#include <REGX52.H>

void main()
{
	while(1)
	{
		if(P3_1==0 || P3_0==0)	//如果K1按键或K2按键按下
		{
			P2_0=0;		//LED1输出0,点亮
		}
		else
		{
			P2_0=1;		//LED1输出1,熄灭
		}
	}
}

代码解释:
P3_1和P3_0分别表示按键K1和按键K2在MCU上的端口;P3_0等于0表示通过寄存器读到的P3_0端口电平状态为低电平,由1.1 独立按键的原理中可知,按键按下时对应的i/o口为低电平,按键松开时对应的i/o口为高电平。所以P3_1==0表示K2按键按下,P3_0==0表示K1按键按下。

P2_0=0表示P2_0端口赋值为低电平,即对应的LED1灯点亮。注意,在上一篇文章的学习中,我们是对P2口整体进行控制,所以使用P2=0xFE这种方式,这种方式可以一次性控制8个灯的状态;例如P2=0xFE就表示第一个灯亮,其他的均灭;但是除了对P2口整体进行控制外,我们也可以分别对P2口的8个端口进行控制,例如P2_0=0则表示第一个灯亮,至于其他七个灯是什么状态,不管。

最终实现的效果就是目标1:K1控制LED灯D1的亮灭,即按下K1(持续不松开)时D1亮,松开D1时D1灭;如下图所示
在这里插入图片描述

三、独立按键控制LED状态

代码路径:51单片机入门教程资料\课件及程序源码\程序源码\KeilProject\3-2 独立按键控制LED状态
代码实现:

#include <REGX52.H>

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

void main()
{
	while(1)
	{
		if(P3_1==0)			//如果K1按键按下
		{
			Delay(20);		//延时消抖
			while(P3_1==0);	//松手检测
			Delay(20);		//延时消抖
			
			P2_0=~P2_0;		//LED1取反
		}
	}
}

代码解释:
P3_1==0表示K1按键按下,上一节已经进行了解释,这里不再解释。
Delay(20)表示延时20ms,此延时函数的是通过stc-isp生成的,生成过程在上一篇文章中有讲解,这里不再重复叙述。在里面加了参数xms,是为了能实现延时时间可配置。
至于为什么要设置延时呢?目的是消除按键的抖动,什么事抖动?

在这里插入图片描述

通俗的解释,当我们按下按键时,并不会马上接通,可能会进行抖动,如 通->断->通->断等过程逐渐的接通;当然,在断开时,也不会马上断开,而是断->通->断->通等过程;这些抖动过程其实是不能作为准确值的,所以要消除抖动。

所以通过延时函数,将抖动期间的动作忽略掉,就可以消除抖动带来的影响,达到的消抖的目的。

最终程序运行的结果就是上面提到的目标2:
还是K1控制D1灯,现象是K1按一下并松开,D1点亮;再按一下并松开,D1灭;再按一下并松开,D1变亮;再按一次并松开,D1灭;如下图

在这里插入图片描述

四、独立按键控制LED显示二进制

代码路径:51单片机入门教程资料\课件及程序源码\程序源码\KeilProject\3-3 独立按键控制LED显示二进制
代码实现:

#include <REGX52.H>

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

void main()
{
	unsigned char LEDNum=0;
	while(1)
	{
		if(P3_1==0)			//如果K1按键按下
		{
			Delay(20);		//延时消抖
			while(P3_1==0);	//松手检测
			Delay(20);		//延时消抖
			
			LEDNum++;		//变量自增
			P2=~LEDNum;		//变量取反输出给LED
		}
	}
}

代码解释:
前面的代码都跟上一节一致,就是判断按键按下,且按键松开,以及延时消抖操作。

最主要的是LEDNum++以及P2=~LEDNum两行代码;下面按照程序的运行过程解释一下这两行代码;
第一次按下并松开K1按键时,进入第一次进入循环,此时LEDNum是0,所以LEDNum++后的值即为1(十六进制表示为0x0000 0001);此时将LEDNum取反后的值是0x1111 1110,将这个值给到P2口;这样8个LED灯的状态为:高7位寄存器的值是1,即P20-P26口是高电平,则前7个LED灯都是灭的,同理,最低位的寄存器的值是0,则P27口是低电平,则最后一个LED灯是亮的;

第一次按下并松开K1按键时,进入第二次进入循环,此时LEDNum是1,所以LEDNum++后的值即为2(十六进制表示为0x0000 0010);此时将LEDNum取反后的值是0x1111 1101,将这个值给到P2口;这样8个LED灯的状态为:高6位以及最低位的寄存器的值是1,即P20-P25以及P27口是高电平,则前6个LED灯以及第8个LED灯都是灭的,同理,第7个LED灯是亮的;

依次类推,每按下并松开一次K1按键,则二进制数字加1,对应的寄存器和LED灯也都加一。

最终实现的效果就是目标3:独立按键控制LED显示二进制

每按下并松开一次K1,LED灯点亮一次,多次按下并松开,实现按照二进制递增的顺序进行点亮;具体的说,可以将8个等比作8个二进制数字,最右边的亮表示1,右边第二个灯亮表示2,右边第三个灯亮表示4,右边第四个灯亮表示8;以此类推;也可以知道,右边第一个和右边第二个灯同时亮表示3(1+2)以此类推;每次按下并松开一次K1,此8个灯中亮起的一个或几个灯组成的数字就加1;如下图所示:

在这里插入图片描述

五、独立按键控制LED位移

代码路径:51单片机入门教程资料\课件及程序源码\程序源码\KeilProject\3-4 独立按键控制LED移位
代码实现:

#include <REGX52.H>
void Delay(unsigned int xms);

unsigned char LEDNum;

void main()
{
	P2=~0x01;				//上电默认LED1点亮
	while(1)
	{
		if(P3_1==0)			//如果K1按键按下
		{
			Delay(20);
			while(P3_1==0); //循环直到K1键松开
			Delay(20);
			
			LEDNum++;		//LEDNum自增
			if(LEDNum>=8)	//限制LEDNum自增范围
				LEDNum=0;
			P2=~(0x01<<LEDNum);	//LED的第LEDNum位点亮
		}
		if(P3_0==0)			//如果K2按键按下
		{
			Delay(20);
			while(P3_0==0);//循环直到K2键松开
			Delay(20);
			
			if(LEDNum==0)	//LEDNum减到0后变为7
				LEDNum=7;
			else			//LEDNum未减到0,自减
				LEDNum--;
			P2=~(0x01<<LEDNum);	//LED的第LEDNum位点亮
		}
	}
}

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


代码解释:

有了前三节的基础,这一节就比较简单了,看注释即可。

最终的效果是实现目 标4:独立按键控制LED移位

按下K1并松开时,LED灯向左移一位;按下K2时,LED灯向右移一位。

K1每按下一次,LED灯向左移动一位:
在这里插入图片描述

K2每按下一次,LED灯向右移动一位:

在这里插入图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乘凉~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值