01-51单片机LED与独立按键
一、单片机概述
注意:个人学习笔记,里面涉及到的C语言和进程转换相关的知识在C语言部分已经写了,这里是默认都会的状态学习单片机。
1.什么是单片机
单片机,英文Micro Controller Unit,简称MCU。其内部集成了CPU、RAM、ROM、定时器、中断系统、通讯接口等一系列电脑的常用硬件功能。
我们可以依靠单片机的传感器采集相应的数据,可以通过 CPU 处理数据,还可以完成对硬件设备,如:LED,蜂鸣器,电机等的控制。
- 单片机相当于一台微型计算机,相比于我们平时使用的电脑,有优势也有劣势:
- 缺点:在性能上,与计算机相差甚远,处理数据的能力要远低于计算机;
- 优点:单片机成本低、体积小、结构简单,有其适用的领域,比如智能家居、工业自动化控制等。并不一定说性能越高的就越好,要看起使用需求,合适的才是最好的。
2. 51单片机简介
2.1命名规范

2.2笔记使用单片机配置
本笔记学习使用的是普中科技 STC89C52RC 的开发板。
- 系列:51单片机系列
- 公司:STC公司
- 位数:8位
- RAM:512字节,理解为电脑内存条,断电丢失
- ROM:8K(Flash),理解为电脑磁盘,断电不丢失
- 工作频率:12MHz
二、LED 模块
1.认识LED
LED:发光二极管,外文名(Light Emitting Diode),用于:照明、广告灯、指引灯、屏幕等。
LED 具有单向导电性,即电流只能从正极流向负极,引脚较长的一端为正极,引脚较短的一端为负极。
2.单片机中 LED 模块电路图

- 说明:
- LED 的电路图可以看出,这是一个共阳极电路,我们需要通过芯片从另外一端(阴极)控制 LED 的亮灭,串联的电阻用于限流,防止烧坏 LED;
- 单片机里用 1 表示高电平(简单理解为给电),0 表示低电平(不给电),当我们给阴极赋 1 的的时候,两边都给电,没有压差,没有电势差,无法形成电流, LED 就无法点亮,因此这里给阴极赋 0 就可以点亮对应的LED;
- 而芯片控制 LED 对应线路的方式,单片机的芯片引出一定数目的引脚,此单片机 40 引脚,分为几组(也有独立的),8个引脚为一组,正好一字节数据也是 8 位。一组一个寄存器,一个寄存器分为 8 个,每个就是一个驱动器。我们通过代码的一字节数据,给对应位赋 0 ,其它位赋 1 ,就能点亮我们想要点亮的 LED 灯泡了;
- 上图可以看到,每条线路对应了一个编号,如 P21 ,这里的 p2 就代表了使用 P2 号锁存器来控制 LED ,后面的 1 对应的是锁存器的其中一个位选段,具体到驱动几号 LED。
3. LED 实验
3.1点亮一颗 LED
- 代码演示
#include <REGX52.H>void main()
{P2=0xFE; // 1111 1110while(1);
}
-
说明:
- 上面的演示效果,是点亮了电路图中的 D1 号 LED;
- 在分析每位二进制的时候,对应的 LED 灯泡从 D1 ~ D8 分别对应二进制中的由低位到高位,代码里面显示的从右往左依次是低位到高位,但是C语言里面没有二进制类型,依次通过十六进制表示;
- 要想通过C语言调用对应的寄存器和驱动器,需要包含头文件
#include <REGX52.H>; - 单片机里程序运行结束不会直接停止,而是会反复去执行,因此下面放一个死循环,防止反复执行,减小 CPU 占用,但是实现效果上是没有区别的。
-
点亮指定多颗 LED
#include <REGX52.H>void main()
{P2=0xAA; // 1010 1010while(1);
}
- 说明:上面的代码点亮了,D1 3 5 7 四颗 LED。
3.2 LED 闪烁
- 代码演示
#include <REGX52.H>
#include <INTRINS.H> // _nop_需要的头文件void Delay500ms() //@12.000MHz
{unsigned char i, j, k;_nop_();i = 4;j = 205;k = 187;do{do{while (--k);} while (--j);} while (--i);
}void main()
{while(1){P2=0xFE; // 1111 1110 亮Delay500ms(); // 延时500msP2=0xFF; // 1111 1111 灭Delay500ms();}
}
- 说明:
- 上面的演示效果,是实现了 D1 LED 每 0.5 秒闪烁一次的效果;
- 上面的延时函数可直接通过软件 STC-ISP 软件的延时计算器生成,需要包含头文件
#include <INTRINS.H>; - 这里实现原理很简单,即先点亮,过 0.5s 熄灭,再过 0.5s 点亮,通过 while 实现循环。
3.3 LED 流水灯
- 代码演示
#include <REGX52.H>
#include <INTRINS.H>// 自定义延时多少毫秒
void Delayxms(unsigned int xms) //@12.000MHz
{unsigned char i, j;while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;}
}void main()
{// 定义变量,保存延时的毫秒数unsigned int time_ms = 500;while(1){P2=0xFE; // 1111 1110Delayxms(time_ms);P2=0xFD; // 1111 1101Delayxms(time_ms);P2=0xFB; // 1111 1011Delayxms(time_ms);P2=0xF7; // 1111 0111Delayxms(time_ms);P2=0xEF; // 1110 1111Delayxms(time_ms);P2=0xDF; // 1101 1111Delayxms(time_ms);P2=0xBF; // 1011 1111Delayxms(time_ms);P2=0x7F; // 0111 1111Delayxms(time_ms);}
}
- 说明:
- 代码运行结果,会从 D1 ~ D8 号 LED 依次点亮 0.5s ,如此循环;
- 和上面闪烁原理一样,只不过交替闪烁而已,需要计算出每个 LED 点亮对应的十六进制码就行了;
- 这里实现了自定义点亮时间,即先生成一个一毫秒的延时函数,然后在延时函数里放一个 while 循环,将延时函数函数体放到循环里面,要延时多少毫秒,就循环多少遍函数体即可;
- 需要注意的是,在单片机里,int 类型占16位,2字节。
三、按键控制 LED
1.认识独立按键模块
1.1独立按键介绍
- 按键的结构实物图

如图右边,按键的底部有四个引脚,左边两个是接通的,右边两个是接通的,左右两边不接通,当我们按下的时候,左图所示的金属弹片会将左右接通,因此按下的时候,四个引脚都是接通的。
1.2独立按键电路图

- 说明:
- 如图所示,这里的独立按键是一个共阴极电路;
- 前面讲到的寄存器,除了可以将指令发送到 IO 口控制 LED 的亮灭,还能读取线路中的高低电平状态返回到 IO 口;
- 因此,按键按下的时候,和 GND 接通,回馈信号为 0 ,松开按键,回馈信号为1;
- 这里使用的是 P3 锁存器,1 ~ 4 位选段。
2.按键实验
2.1按键控制 LED 亮灭
- 代码演示
#include <REGX52.H>void main()
{while(1){// 按键按下回馈信号为0,反之为1if(P3_1==0)P2_0=0;elseP2_0=1;}
}
- 说明:
- 运行效果:按键 K1 按下的时候,LED 亮起,松开 LED 熄灭;
- 除了上面 LED 实验里,一次性对一个段的 8 位进行操作以外,也能单独对某一位进行操作。
2.2按键控制 LED 状态
2.2.1按键抖动
前面提到的按键里面的金属弹片,按键按下的时候,弹片会将左右引脚接通,但是机械触点也会产生振动,虽然这振动对于宏观世界而言无关紧要。但从微观来看,机械触点的弹性作用,一个开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开,所以在开关闭合及断开的瞬间会伴随一连串的抖动,如下图:

因此,在按键按下和松开的时候,各设置一个延时函数消抖即可。
2.2.2按键点亮 LED
- 代码演示
#include <REGX52.H>
#include <INTRINS.H>void Delayxms(unsigned int xms) //@12.000MHz
{unsigned char i, j;while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;}
}void main()
{while(1){if(P3_1 == 0){// 延时为了消除按键抖动Delayxms(20);// 如果按键不松开就一直循环while(P3_1 == 0);Delayxms(20);// 这一次值为上一次的取反,即上一次灭,这一次就亮P2_0 =~ P2_0;}}}
- 说明:
- 上面代码运行的效果:按下松开, LED 点亮,再次按下松开,LED 熄灭;
- 在按下和松开的瞬间各设置一个延时消抖,如果按下没有松开,通过一个 while 循环阻塞,直到松开按键,循环解阻塞;
- 当前 LED 的亮灭状态为按键前的取反,即按键前是亮,则按下后是灭,按下前是灭,按下后是亮。
2.3按键控制 LED 以二进制显示
- 代码演示
#include <REGX52.H>
#include <INTRINS.H>void Delayxms(unsigned int xms) //@12.000MHz
{unsigned char i, j;while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;}
}void main()
{unsigned char LEDNum = 0;while(1){if(P3_1 == 0){Delayxms(20);while(P3_1 == 0);Delayxms(20);LEDNum++;P2 = ~LEDNum;}}}
- 说明:
- 上面代码的运行效果:每按下一次按键,LED 就以二进制数值递增的方式显示;
- 定义一个局部变量,用于存放每个 LED 的高低电平状态,每按键一次,对变量 +1 ;
- 因为 LED 模块是共阳极电路,因此给 0 LED 才亮,因此对局部变量按位取反,实现真正的效果。
2.4按键控制 LED 左右移动
- 代码演示
#include <REGX52.H>
#include <INTRINS.H>void Delayxms(unsigned int xms) //@12.000MHz
{unsigned char i, j;while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;}
}void main()
{unsigned char LEDNum = 0;P2=~0x01; // led默认开始在第一个while(1){// 实现灯号递增移动if(P3_1 == 0){Delayxms(20);while(P3_1 == 0);Delayxms(20);LEDNum++;if(LEDNum >= 8)LEDNum = 0;P2 = ~(0x01<<LEDNum);}// 实现灯号递减少移动if(P3_0 == 0){Delayxms(20);while(P3_0 == 0);Delayxms(20);if(LEDNum == 0)LEDNum = 7;LEDNum--;P2 = ~(0x01<<LEDNum);}}
}
- 说明:
- 运行结果:点按 K1 按键, LED 从低位向高位,每按键一次,移动一个;
- 点按 K2 按键,LED 从高位向低位,每按键一次,移动一个;
- 这里设置 LED 默认点亮 D1 号,定义一个变量用于保存下一次按键点亮 LED 的偏移量,通过左移右移实现每按键一次,左移或右移一个 LED ;
- 同时判断,移动范围,低位到高位移动,最大偏移量为 7 ,当超过 7 的时候复位到最低位 LED ;同理由高位到低位移动,最低位偏移量为0,先判断为 0,复位到最高位 LED,如此循环实现。
相关文章:
01-51单片机LED与独立按键
一、单片机概述 注意:个人学习笔记,里面涉及到的C语言和进程转换相关的知识在C语言部分已经写了,这里是默认都会的状态学习单片机。 1.什么是单片机 单片机,英文Micro Controller Unit,简称MCU。其内部集成了CPU、R…...
【微服务】SpringBoot 整合Redis实现延时任务处理使用详解
目录 一、前言 二、延迟任务的高频使用场景 三、延迟任务常用解决方案 3.1 Quartz 3.2 DelayQueue 3.2.1 Timer + TimerTask 3.2.2 ScheduledExecutorService 3.3 Redis sorted set 3.4 RabbitMQ 四、Redis实现延时队列操作实战 4.1 Redis Sorted Set 概述 4.1.1 Re…...
【Java项目】基于SpringBoot的【校园交友系统】
【Java项目】基于SpringBoot的【校园交友系统】 技术简介:系统软件架构选择B/S模式、SpringBoot框架、java技术和MySQL数据库等,总体功能模块运用自顶向下的分层思想。 系统简介:系统主要包括管理员和用户。 (a) 管理员的功能主要有首页、个人…...
Elasticsearch学习(1) : 简介、索引库操作、文档操作、RestAPI、RestClient操作
目录 1.elasticsearch简介1.1.了解es1.2.倒排索引正向索引和倒排索引 1.3.es的一些概念:文档和字段;索引和映射;Mysql与ES1.4.安装es、kibana部署单点es部署kibanaIK分词器安装IK分词器与测试扩展与停用词词典总结 部署es集群 2.索引库操作2.1.mapping映…...
ls指令详讲
🏝️专栏:https://blog.csdn.net/2301_81831423/category_12872319.html 🌅主页:猫咪-9527-CSDN博客 “欲穷千里目,更上一层楼。会当凌绝顶,一览众山小。” 目录 基本语法 常用选项详解 1. 基本选项 …...
【前端】【CSS3】基础入门知识
目录 如何学习CSS 1.1什么是CSS编辑 1.2发展史 1.三种导入方式 1.1、行内样式 1.2、外部样式 1.3、嵌入方式 2.选择器 2.1、基本选择器 (1)元素选择器 (2)类选择器 (3)id选择器:必…...
计算机网络之---RIP协议
RIP协议的作用 RIP (Routing Information Protocol) 协议是一个基于距离矢量的路由协议,它在网络中用来动态地交换路由信息。RIP 是最早的路由协议之一,通常用于小型和中型网络中。它的工作原理简单,易于实现,但在一些大型网络中效…...
【LeetCode Hot100 贪心算法】 买卖股票的最佳时机、跳跃游戏、划分字母区间
贪心算法 买卖股票的最佳时机买卖股票的最佳时机II跳跃游戏跳跃游戏II划分字母区间 买卖股票的最佳时机 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的…...
互联网架构变迁:从 TCP/IP “呼叫” 到 NDN “内容分发” 的逐浪之旅
本文将给出关于互联网架构演进的一个不同视角。回顾一下互联网的核心理论基础产生的背景: 左边是典型的集中控制通信网络,很容易被摧毁,而右边的网络则没有单点问题,换句话说它很难被全部摧毁,与此同时,分…...
git相关操作笔记
git相关操作笔记 1. git init git init 是一个 Git 命令,用于初始化一个新的 Git 仓库。执行该命令后,Git 会在当前目录创建一个 .git 子目录,这是 Git 用来存储所有版本控制信息的地方。 使用方法如下: (1ÿ…...
jenkins 使用 ssh-agent向windows进行部署
背景: jenkins在linux的docker环境内,应用服务部署在windows。需要使用jenkins实现自动化部署。 实现方式: jenkins上构建pipeline任务,脚本如下: 遇到问题: 1、问题:jenkins 调用部署bat脚…...
MySQL入门学习笔记
第一章 数据库系统概述 数据库的4个基本概念 数据、数据库、数据库管理系统、数据库系统是与数据库技术密切相关的4个基本概念 数据 数据是数据库中存储的基本对象,描述事物的符号记录称为数据,数据的表现形式还不能完全表达其内容,需要…...
机器学习全流程解析:数据导入到服务上线全阶段介绍
目录 1. 数据导入 2. 数据预处理 3. 超参数搜索与优化 4. 模型训练 5. 模型评估 6. 模型压缩与优化 7. 模型注册与版本管理 8. 服务上线与部署 总结 1. 数据导入 数据源:数据库、文件系统、API等。数据格式:CSV、JSON、SQL 数据库表、Parquet …...
C#从“Hello World!“开始
是时候一览C#的庐山真面目了。现在,让我们从"Hello World"开始吧,出发! 1. 一个简单的C#程序 先来看一段最简单的示例代码,如代码清单2-1所示。 代码清单2-1 HelloWorldClass.cs using System;namespace Programmi…...
LVS 支持 UDP 协议代理
在现代网络架构中,负载均衡技术是保证高可用性和高性能的关键组成部分。Linux Virtual Server(LVS)作为一个高效、稳定的负载均衡解决方案,广泛应用于处理 TCP 流量的场景。然而,随着实时通信、视频流和在线游戏等应用的不断发展,UDP 协议的支持成为了 LVS 负载均衡的重要…...
【C++经典例题】求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句
💓 博客主页:倔强的石头的CSDN主页 📝Gitee主页:倔强的石头的gitee主页 ⏩ 文章专栏: 期待您的关注 题目描述: 原题链接: 求123...n_牛客题霸_牛客网 (nowcoder.com) 解题思路: …...
Rabbitmq 具体怎么做到削峰的,是丢弃部分消费吗,有的实际场景是不允许丢弃
在高并发场景中,RabbitMQ 可以通过几种策略来实现 削峰(缓解瞬时负载激增),而这些策略并不一定需要丢弃消息。在一些业务场景下,丢弃消息显然是不允许的,因此在这种情况下,可以使用以下方法来确…...
Linux渗透实战之Nullbyte靶场提权
0x1 前言 一、浅谈 哈喽师傅们,这次又到了给师傅们分享文章的时候了,这篇文章呢主要是给师傅们以vulnhub中的Nullbyte靶场来给师傅们演示下通过Hydra表单暴力破解等操作拿到账户密码,然后中间以四种sql注入的方式给大家非常详细的操作了sql…...
(STM32笔记)十二、DMA的基础知识与用法 第三部分
我用的是正点的STM32F103来进行学习,板子和教程是野火的指南者。 之后的这个系列笔记开头未标明的话,用的也是这个板子和教程。 DMA的基础知识与用法 三、DMA程序验证1、DMA 存储器到存储器模式实验(1)DMA结构体解释(2…...
品牌账号矩阵如何打造?来抄作业
在讲究全域营销的当下,目前企业都在各自搭建品牌矩阵号,以提升自己在不同渠道上的影响力。虽然不同平台之间有诸多细节值得深究,但也不妨碍我们先了解如何搭建品牌矩阵。接下来,就让我们一同来了解下该如何搭建。 一、一个主账号 …...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
