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

news2024/11/25 12:31:10

❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括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 独立按键的原理(很重要!!!)
    • 1.2 本节目标
  • 二、独立按键控制LED亮灭
  • 三、独立按键控制LED状态
  • 四、独立按键控制LED显示二进制
  • 五、独立按键控制LED位移

一、本节背景和目标

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灯向右移动一位:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/461176.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【SpringMVC源码三千问】DispatcherServlet源码解析

DispatcherServlet#doDispatch() 是 SpringMVC 处理请求分发的方法&#xff0c;只要是 spring mvc 处理的 http 请求&#xff0c;都会经过 DispatcherServlet 的请求分发处理&#xff0c;从而调用相应的 handler method。 DispatcherServlet#doDispatch() 源码分析&#xff1a…

PCL点云库(3) — common模块

目录 3.1 common模块中的头文件 3.2 common模块中的基本函数 &#xff08;1&#xff09;angle角度转换 &#xff08;2&#xff09;distance距离计算 &#xff08;3&#xff09;random随机数生成 &#xff08;4&#xff09;sping扩展模块 &#xff08;5&#xff09;time获…

请问你见过吐代码的泡泡吗(冒泡排序)

&#x1f929;本文作者&#xff1a;大家好&#xff0c;我是paperjie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 &#x1f970;内容专栏&#xff1a;这里是《算法详解》&#xff0c;笔者用重金(时间和精力)打造&#xff0c;将算法知识一网打尽&#xff0c;希望可以…

现场工程师救火-UEFI(BIOS)节能设置导致金牌服务器只跑出龟速

近期协助出现场&#xff0c;解决了一个非常典型的UEFI 启动参数配置不当导致的服务器降效案例。错误的节能参数配置&#xff0c;导致价值几十万的服务器变成龟速服务器&#xff0c;并造成严重的生产事故。 1. 现象 朋友公司近期准备升级2010年就部署的服务器组&#xff0c;新…

vue移动端项目通用技巧

目录 一、配置文件 1.1、取消eslint校验 1.2、基础文件引入 1.3、iconfont引入svg使用 1.4、css的简化应用 1.5、内容溢出用省略号替代 1.6、非组件库的底部导航跳转 1.7、基础版轮播图 一、配置文件 1.1、取消eslint校验 在vue.config.js文件里&#xff1a; const …

【论文阅读】Robustness in Reinforcement Learning

原文为 Trustworthy Reinforcement Learning Against Intrinsic Vulnerabilities: Robustness, Safety, and Generalizability&#xff0c;是 2022 年 CMU 发表的综述文章。 本文主要关注文章的第二部分即鲁棒性 1. 概述 鲁棒性主要解决的问题是提高策略在面对不确定性或者对抗…

Linux:文件查看:《cat》《more》《less》《head》《tail》《wc》《grep》使用方法

同样是查看为什么要有这么多查看方法&#xff1f;&#xff1f;&#xff1f; 因为他们的用法和扩功能肯定不一样&#xff0c;选择与你需要匹配的一条命令可以节省时间的同时更快速 cat 文件 可以直接查看文件内的内容 直接可以查看文件内的内容 要直接看更多的文件以空格隔开的…

AI大模型+低代码,在项目管理中的应用实践

随着ChatGPT大火之后&#xff0c;新的AI技术和模型被证明已经具备的很高的使用价值。 诸如Copilot、Midjourney、notion等产品通过AI的加持&#xff0c;已经让用户能够充分地在应用层面感受到了便利性。 原本几天的工作通过AI模型&#xff0c;可能只需要1分钟就能完成。可以大…

面试腾讯T7,被按在地上摩擦,鬼知道我经历了什么?

时间总是过得飞快&#xff0c;金三银四已经过去了&#xff0c;人们已经开始备战互联网大厂2023年的秋招计划了。刚好最近我有个小徒弟去腾讯面试的时候挂掉了&#xff0c;感觉被技术吊打。根据他的描述我复盘了一下&#xff0c;希望能给备战秋招的朋友一些帮助。 腾讯面试的内…

Leetcode——485. 最大连续 1 的个数

&#x1f4af;&#x1f4af;欢迎来到的热爱编程的小K的Leetcode的刷题专栏 文章目录 1、题目2、滑动窗口3、一次遍历(官方题解) 1、题目 题目&#xff1a;给定一个二进制数组 nums &#xff0c; 计算其中最大连续 1 的个数。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,0…

生成对抗网络pix2pixGAN

1.介绍 论文&#xff1a;Image-to-Image Translation with Conditional Adversarial Networks 论文地址&#xff1a;https://arxiv.org/abs/1611.07004 图像处理的很多问题都是将一张输入的图片转变为一张对应的 输出图片&#xff0c;比如灰度图、彩色图之间的转换、图像自动…

【JavaEE】SpringMVC_day02

今日内容 完成SSM的整合开发能够理解并实现统一结果封装与统一异常处理能够完成前后台功能整合开发掌握拦截器的编写 1&#xff0c;SSM整合 前面我们已经把Mybatis、Spring和SpringMVC三个框架进行了学习&#xff0c;今天主要的内容就是把这三个框架整合在一起完成我们的业务功…

网络基础-IP和端口号以及认识传输层协议

概念回顾 MAC地址仅需要在同一个局域网下唯一&#xff0c;就可以保证不会出现通讯问题。 通信的目的是两台机器上的应用软件要通信。即客户端进程和服务端进程要获取这个数据&#xff0c;借助主机来完成通信。故将数据在主机间转发仅仅是手段&#xff0c;机器收到后&#xff…

为什么别的测试工程师年薪30W,而你做不到?

最近收到一位同学的私信&#xff1a; “看到了这个岗位想去应聘&#xff0c;但任职要求熟悉Shell、Python、Java其中的一种语言。软件测试工程师不是对编程代码要求不高吗&#xff1f;我如果学习应该选择Java还是Python&#xff1f;” 对于刚入行的测试新人来说&#xff0c;在求…

深入理解Linux内核(第三版)- 进程切换

为了控制进程的执行&#xff0c;内核必须有能力挂起正在CPU上运行的进程&#xff0c;并恢复以前挂起的某个进程的执行。这种行为被称为进程切换&#xff08;process switch&#xff09;、任务切换&#xff08;task switch&#xff09;或上下文切换&#xff08;context switch&a…

手把手教你Java实现栈和队列

目录 一、栈(Stack) 1、概念 2、栈的使用 3、栈的模拟实现 4、栈的应用场景 2. 队列(Queue) 1、概念 2、队列的使用 3、队列模拟实现 4、循环队列 三、双端队列 (Deque) 五、栈和队列的互相实现 用队列实现栈&#xff1a; 用栈实现队列&#xff1a; 一、栈(St…

【剑指offer】(2)

系列文章目录 剑指offer系列是一本非常著名的面试题目集&#xff0c;旨在帮助求职者提升编程能力和应对面试的能力。 文章目录 系列文章目录[TOC](文章目录) 前言一、 用两个栈实现队列&#x1f525; 思路&#x1f308;代码 二、青蛙跳台阶问题&#x1f525; 思路&#x1f308…

git从入门到卸载

git是什么&#xff1f; 从git的官网Git可以找到&#xff1a; Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency. Git is easy to learn and has a tiny footpr…

SANGFOR防火墙如何查看现网运行参数

环境&#xff1a; 防火墙 8.0.48 AF-1000BB1510 问题描述&#xff1a; 公司防火墙设备使用2年多了 AF-2000-FH2130B-SC;性能参数&#xff1a;网络层吞吐量&#xff1a;20G&#xff0c;应用层吞吐量&#xff1a;9G&#xff0c;防病毒吞吐量&#xff1a;1.5G&#xff0c;IPS吞…

python基础实战4-python基础语法

1、注释&#xff08;Comments&#xff09; 注释用来向用户提示或解释某些代码的作用和功能&#xff0c;它可以出现在代码中的任何位置。 Python解释器在执行代码时会忽略注释&#xff0c;不做任何处理&#xff0c;就好像它不存在一样。 1.1 代码注释介绍 注释就是对代码的解…