【嵌入式51单片机】让 LED 按你想法亮!从原理、点灯方法、闪烁与流水灯实现 + 拓展知识

【嵌入式51单片机】让 LED 按你想法亮!从原理、点灯方法、闪烁与流水灯实现 + 拓展知识

🔥小龙报:个人主页

🎬作者简介:C++研发,嵌入式,机器人方向学习者

❄️个人专栏:《工科必装软件安装教程》《嵌入式的开端 ---- 51单片机》

✨ 永远相信美好的事情即将发生

前言 本文讨论了点亮 LED 的相关知识,包括应用场景、点灯原理、点亮方法、闪烁控制、流水灯实现以及相关扩展知识

一、应用场景在这里插入图片描述二、点灯原理插件led灯珠长引脚为正极,短引脚为负极。

在这里插入图片描述在这里插入图片描述

LED(发光二极管)两端存在电压差,有一定的电流流过时会亮起。电流可以理解为水流,电压差可以理解为水位差,当两个点水位高度不一样时,水流会从高水位流向低水位。

在这里插入图片描述2.1LED的限流电阻计算注意:流过LED的电流需要在一定范围内,否则会烧坏LED,一般小于20ma,所以我们就需要串联电阻分压,那串联的电阻需要多大阻值呢?

一般插件LED电流是20ma左右,压降:红/黄色1.8V, 蓝/白色 3V, 实际电压要看 LED 规格书。​

一般贴片LED电流是5ma左右,压降:红/绿/橙色1.8V,蓝/白色 3V​

例如:供电电压是3.3V,黄色贴片LED​

根据V = I * R ,则R= (3.3 - 1.8) /0.005 (5ma = 0.005), 所以 R = 300 欧姆.​

在这里插入图片描述很多时候你看到别人设计的电路中,LED串联的电阻去到几百欧或几千欧都有,是设计错了吗?​

实际上这是非常合理的, 因为大多数电路中,LED只是一个提示灯,对亮度没有要求,反而希望把功耗降低,所以需要增大限流电阻来实现超低电流 ,像产品中的贴片LED去到0.5ma也是能看清楚灯光的。​

三、点亮LED3.1如何用单片机点亮LED首先是接线部分,我们可以通过单片机的引脚,又叫做GPIO,这些IO都是具备输出和输入能力的,什么是 GPIO 呢?GPIO 的 英文全程是 General-purpose input/output,翻译过来就是:通用输入输出,也就是我们可以设置某个引脚输出高低电平,或读取某个引脚输入的电平。

在这里插入图片描述在这里插入图片描述

所以,所以我们的做法是:将LED和电阻串联,一段接负极(接地),另一端接单片机IO口,然后 控制单片机的IO口电平 就可以决定LED是否点亮了

在这里插入图片描述

注意:通常我们不采用第一种情况,因为单片机IO口虽然可以达到高电压,但是输出电流不会大,因此单片机IO口给LED供电时可能会出现电流不足,导致LED不会全亮。

因此,我们一般选择第二种,利用电源直接供电,电流灌入单片机IO口的方式来给LED灯供电

3.2 通过编程控制芯片某个IO输出高低电平操作芯片对应IO的寄存器即可,这部分我们可以在芯片手册上看到

51单片机的每组IO口的电平状态都被储存在一个单独的8位寄存器中,寄存器的位为0或1就分别对应其相应的GPIO电平为低或高。

在这里插入图片描述3.3板卡LED部分的原理图在这里插入图片描述在这里插入图片描述在这里插入图片描述

因为摆放顺序错的原因,LED灯的顺序如下哦:

在这里插入图片描述3.4点灯方法方法一:操作整个寄存器直接在C语言代码中用赋值法即可,例如操作P2口的P2.0 P2.1 P2.4 P2.6口输出高电平的代码是

代码语言:javascript复制P2 = 0x53;

0x53的是16进制的53,即53H,对应二进制01010011,即01010011B,

所以它对应P2.0 P2.1 P2.4 P2.6口输出高电平这里的0x53是十六进制的表示方法,为什么需要十六进制,什么是十进制,什么是二进制呢?

进制的作用:更好的表示数值。

(1)十进制: 十进制是人类最自然的数字系统,因为我们有十个手指,故我们使用十进制进行计数,使用 0-9 来表示数字,逢10进1。

(2)二进制: 二进制的出现是因为数字电路中,数字信号只有高/低或开/关两种状态,所以只需要使用两个数字 0 和 1 来表示数字 ,优点是非常直观,缺点是书写起来冗长,过长的二进制容易记录错误,不便阅读和书写。

(3)十六进制:为了可以更紧凑地表示二进制数据,就有了十六进制,使用十六个数字 0-9 和字母 A-F 来表示数字,在代码中,使用0x前缀来表示十六进制。

在这里插入图片描述方法二 操作寄存器的某个位在C语言中,先定义你要操作的位,使用 关键字sbit(这是标准C语言没有的关键字,是C51编译器的拓展关键字,用于定义寄存器的某个位)。你就可以理解成sbit就是给寄存器的某个位起一个别名。之后用等号赋值即可更改此位的0或1​

代码语言:javascript复制例:

sbit led1= Px^y;​(1)符号^在C51中也表示寄存器的第某位,如上方代码,Px^y表示Px寄存器的第y位。​

代码语言:javascript复制//定义变量led1表示P2寄存器的第7位​

sbit led1= P2^7;​注意:"^"实质代表的是异或运算,可以算一下,恰好符合。

代码语言:javascript复制//定义变量led1表示P2寄存器的第7位

sbit led1= P2^7;

//定义变量led2表示P2寄存器的第6位

sbit led2= P2^6;

...

//将P2.7口 输出低电平

led1= 0;

//将P2.6口 输出高电平

led2= 1;

...我们可以这样来定义P2.7这个引脚的输出低电平

代码语言:javascript复制#include

sbit led = P2^7;

void main(void)

{

led = 0;

while(1)

{

}

}四、闪烁控制前面,我们通过设置某个引脚输出低电平,点亮LED,也就是我们设置输出高电平时,会关闭LED,那我们需要 实现LED闪烁的功能时,如何实现呢?​

解决方案: 先点亮LED,延时一段时间,关闭LED,再延时一段时间,如此反复,就可以得到一个闪烁的LED功能。

在单片机中如何实现延时功能呢?有以下几种生成延时函数的生成方法​

1、让芯片循环执行一些无意义的代码​

我们知道,芯片执行每一句代码都需要时间,假设执行一句代码的时间为1ms,那我们点亮LED,然后执行500句(500ms)无意义的代码,再关闭LED,就可以得到闪烁的效果啦。

代码语言:javascript复制//带参延时函数

void delay_ms(unsigned int xms) //@12MHz

{

unsigned int i, j;

for(i=xms;i>0;i--)

{

for(j=124;j>0;j--)

{}

}

}2、使用STC-ISP工具生成

代码语言:javascript复制//延时函数,延时500ms

void delay_500ms()

{

unsigned char i, j, k;

i = 4;

j = 129;

k = 119;

do

{

do

{

while (--k);

} while (--j);

} while (--i);

}最终效果:

代码语言:javascript复制#include

sbit led = P2^7;

//带参延时函数

void delay_ms(unsigned int xms) //@12MHz

{

unsigned int i, j;

for(i=xms;i>0;i--)

{

for(j=124;j>0;j--)

{}

}

}

void main()

{

while(1)

{

led = 0;

delay_ms(500);

led = 1;

delay_ms(500);

}

}五、流水灯如果需要实现多个灯的显示和熄灭呢?​

其实就是流水灯的效果

代码语言:javascript复制#include "reg52.h"

#include "intrins.h"

sbit LED1 = P2^7;

sbit LED2 = P2^6;

sbit LED3 = P2^5;

void Delay1000ms() //@11.0592MHz

{

unsigned char i, j, k;

_nop_();

i = 8;

j = 1;

k = 243;

do

{

do

{

while (--k);

} while (--j);

} while (--i);

}

void main(){

while(1){

LED1 = 0;

LED2 = 1;

LED3 = 1;

Delay1000ms();

LED2 = 0;

LED1 = 1;

LED3 = 1;

Delay1000ms();

LED3 = 0;

LED1 = 1;

LED2 = 1;

Delay1000ms();

}

}代码优化:

代码语言:javascript复制#include

void delay_ms(unsigned int xms)

{

unsigned int i, j;

for(i=xms;i>0;i--)

{

for(j=124;j>0;j--)

{}

}

}

void main()

{

while(1)

{

P2 = 0xDF; //1101 1111

delay_ms(500);

P2 = 0xBF; //1011 1111

delay_ms(500);

P2 = 0x7F; //0111 1111

delay_ms(500);

}

}六、相关扩展bit、sbit、sfr的区别​

首先,bit和sbit都是C51扩展的变量类型​

bit是一种数据类型,ta就跟int、char、double这些数据类型一样,只不过char=8位, bit=1位而已,这种变量只有两种值存在0或是1,和bool类似​

sbit更像是define或者typedef一样(define和typedef也有区别,这又是另外一个坑,这里就不说了),它是为已经分配了内存空间的变量重新取一个别名,一般用来定义特殊功能寄存器的位变量,以方便对寄存器的某位进行操作的,

例:

代码语言:javascript复制bit i = 0;

//意思就是在内存中划一块空间给i,让他存储0这个数据位。

sbit Flag = P0^1;//意思就是给P0^1取一个别名,它叫做Flag,

他是一个位操作变量,它代表访问的地址是P0^1,0x80的第二位数据位。sbit的用法有三种:​

第一种方法:sbit 位变量名=地址值​

第二种方法:sbit 位变量名=SFR名称^变量位地址值​

第三种方法:sbit 位变量名=SFR地址值^变量位地址值

代码语言:javascript复制如定义PSW中的OV可以用以下三种方法:

sbit OV=0xd2 (1)说明:0xd2是OV的位地址值

sbit OV=PSW^2 (2)说明:其中PSW必须先用sfr定义好

sbit OV=0xD0^2 (3)说明:0xD0就是PSW的地址值

因此这里用sfr P1_0=P1^0;就是定义用符号P1_0来表示P1.0引脚,如果你愿意也可以起P10一类的名字,只要下面程序中也随之更改就行了。sfr 不是标准C 语言的关键字,而是Keil 为能直接访问80C51 中的SFR 而提供了一个新的关键词,其用法是:​

sfr变量名=地址值。​

代码语言:javascript复制例:sfr P1 = 0x90;​

这样的一行即定义P1 与地址0x90 对应,P1 口的地址就是0x90.​

SFR的定义在头文件reg51.h或reg52.h中。总结与每日励志✨ ***本文介绍了LED点亮的原理、方法及扩展应用。主要内容包括:LED工作原理及限流电阻计算,单片机控制LED的接线方式与编程方法(通过寄存器操作或位操作),闪烁LED的实现原理及延时函数生成技巧(循环代码或STC-ISP工具)。文章还提供了51单片机控制LED的具体代码示例,并简要提及流水灯等扩展应用场景。适合嵌入式初学者快速掌握LED控制的基础知识。***

相关数据

excel表格里面怎么横线
365bet知乎

excel表格里面怎么横线

⌛ 11-10 👁️ 8692
EEPROM与内存Flash消耗能量计算
足球365网站网址

EEPROM与内存Flash消耗能量计算

⌛ 08-07 👁️ 4579
失重就是“失去重量”吗?
365bet知乎

失重就是“失去重量”吗?

⌛ 07-31 👁️ 1234