一、LED实际应用场景
LED即发光二极管,生活中随处可见:显示屏、广告牌、指示灯、装饰灯带。单片机最基础、经典的入门实验就是点亮LED。
二、LED点灯基础原理
插件LED灯珠长引脚=正极,短引脚=负极。

LED只有两端形成电压差、流过合适大小电流的时候才会发光。

⚠️LED不能直接接电源!必须串联限流电阻,电流过大直接烧毁灯珠。
限流电阻计算公式
R=VCC−VLEDIR=\frac{V_{CC}-V_{LED}}{I}R=IVCC−VLED
- 插件LED常规工作电流:20mA
- 贴片LED常规工作电流:5mA
- 红/黄光压降约1.8V,蓝/白光压降约3V
举个例子:3.3V供电、黄色贴片LED
R=(3.3−1.8)/0.005=300ΩR=(3.3-1.8)/0.005=300ΩR=(3.3−1.8)/0.005=300Ω
实际产品指示灯经常选用几千欧的大电阻,牺牲亮度换取更低功耗。

三、单片机GPIO控制LED
GPIO全称General‑purpose input/output通用输入输出引脚,可以配置输出高低电平,以此控制LED亮灭。

STC89C51的IO分组:
- P0口:P0.0~P0.7
- P1口:P1.0~P1.7
- P2口:P2.0~P2.7
- P3口:P3.0~P3.7
- P4口:P4.0~P4.6
两种硬件接法
- IO口直接输出高电平点亮LED(不推荐):单片机IO输出驱动能力弱,亮度不足
- VCC供电,LED负极接IO引脚,IO输出低电平点亮LED(开发板标准接法)
本实验开发板硬件:LED1、LED2、LED3分别接
P2.7、P2.6、P2.5,引脚输出低电平 → LED点亮
方式1:整体操作IO寄存器
直接给整个端口寄存器赋值,一次性控制8个引脚电平
P2 = 0x53;
0x53是十六进制,对应二进制0101 0011,对应控制P2口8个引脚电平。
进制简单科普
- 十进制:0‑9,逢十进一,适合人阅读
- 二进制:只有0、1,对应硬件高低电平,但是数字太长不好写
- 十六进制:0‑9、A‑F,
0x前缀,紧凑表达二进制,单片机代码最常用
一键点亮P2口全部LED示例代码
#include <reg52.h>
void main(){
P2=0x00; //全部输出低电平
while(1)
{
}
}
while(1)死循环,单片机程序运行到这里永久停留
方式2:单独控制某一个引脚(sbit位定义)
sbit是C51编译器独有的关键字,可以单独操作寄存器其中某一个IO引脚,语法格式
sbit led1= P2^7;
代表:把P2.7引脚别名定义为led1,后续代码直接操作led1即可控制引脚电平。
单颗LED点亮完整代码
#include <reg52.h>
sbit led = P2^7;
void main(void)
{
led = 0; //输出低电平,点亮LED
while(1)
{
}
}
四、LED闪烁实验
闪烁逻辑:点亮 →延时一段时间 →熄灭 →延时一段时间,循环往复。
51单片机时间基础概念
- 时钟周期:晶振频率的倒数,12M晶振,时钟周期=1/12 us
- 机器周期:51单片机默认12时钟周期 =1个机器周期
- 指令周期:CPU执行一条汇编指令花费的总机器周期
软件延时原理:让CPU空循环,消耗时间,达到延时效果
通用毫秒延时函数(12M晶振)
void delay_ms(unsigned int xms) //@12MHz
{
unsigned int i, j;
for(i=xms;i>0;i--)
{
for(j=124;j>0;j--)
{}
}
}
也可以使用STC‑ISP软件自动生成精准延时代码,省去手动计算
LED闪烁完整可运行代码
#include <reg52.h>
sbit led = P2^7;
//带参延时函数 12M晶振
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)
{
led = 0;
delay_ms(500); //亮500ms
led = 1;
delay_ms(500); //灭500ms
}
}
五、流水灯实现
硬件:LED1(P2.7)、LED2(P2.6)、LED3(P2.5)依次循环点亮
版本1:单独位操作写法,可读性高
#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();
}
}
版本2:端口寄存器整体赋值写法,代码简洁
#include <reg52.h>
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 P2.7输出低
delay_ms(500);
P2 = 0xBF; //1011 1111 P2.6输出低
delay_ms(500);
P2 = 0x7F; //0111 1111 P2.5输出低
delay_ms(500);
}
}
版本3:位运算封装函数,扩展性最强
#include <reg52.h>
void delay_ms(unsigned int xms)
{
unsigned int i, j;
for(i=xms;i>0;i--)
{
for(j=124;j>0;j--)
}
}
//点亮指定P2端口引脚
void open_led(unsigned int num){
P2 = 0xFF & ~(1 << num);
}
void main()
{
while(1)
{
open_led(7);
delay_ms(500);
open_led(6);
delay_ms(500);
open_led(5);
delay_ms(500);
}
}
六、拓展知识点 bit / sbit / sfr区别
- bit:C51扩展基础数据类型,1位布尔变量,值只能是
0或1,在单片机RAM空间分配存储空间,类似bool
bit flag = 0;
- sbit:位别名定义,用来直接操作特殊寄存器的某一个引脚,不占用RAM内存,直接绑定硬件地址
sbit OV=PSW^2;
sbit三种标准写法
sbit OV=0xd2;
sbit OV=PSW^2;
sbit OV=0xD0^2;
- sfr:定义8位特殊功能寄存器,直接绑定硬件寄存器地址,
reg52.h头文件内部大量使用sfr定义P0‑P3等端口
sfr P1 = 0x90;
七、本章小结
1、LED必须串联限流电阻,防止烧毁
2、可以整体赋值寄存器或者sbit单独控制单个IO引脚
3、软件空循环实现延时,完成LED闪烁效果
4、流水灯可以使用3种不同编码思路实现
下一章预告:独立按键检测,软件消抖原理与代码实现

193

被折叠的 条评论
为什么被折叠?



