【嵌入式成长1】STC89C51点亮LED|GPIO原理、闪烁、流水灯实战教程

一、LED实际应用场景

LED即发光二极管,生活中随处可见:显示屏、广告牌、指示灯、装饰灯带。单片机最基础、经典的入门实验就是点亮LED。

二、LED点灯基础原理

插件LED灯珠长引脚=正极,短引脚=负极
在这里插入图片描述

LED只有两端形成电压差、流过合适大小电流的时候才会发光。
在这里插入图片描述

⚠️LED不能直接接电源!必须串联限流电阻,电流过大直接烧毁灯珠。

限流电阻计算公式

R=VCC−VLEDIR=\frac{V_{CC}-V_{LED}}{I}R=IVCCVLED

  • 插件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.31.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

两种硬件接法

  1. IO口直接输出高电平点亮LED(不推荐):单片机IO输出驱动能力弱,亮度不足
  2. VCC供电,LED负极接IO引脚,IO输出低电平点亮LED(开发板标准接法

本实验开发板硬件:LED1、LED2、LED3分别接 P2.7P2.6P2.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单片机时间基础概念

  1. 时钟周期:晶振频率的倒数,12M晶振,时钟周期=1/12 us
  2. 机器周期:51单片机默认12时钟周期 =1个机器周期
  3. 指令周期: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区别

  1. bit:C51扩展基础数据类型,1位布尔变量,值只能是01,在单片机RAM空间分配存储空间,类似bool
bit flag = 0;
  1. sbit:位别名定义,用来直接操作特殊寄存器的某一个引脚,不占用RAM内存,直接绑定硬件地址
sbit OV=PSW^2;

sbit三种标准写法

sbit OV=0xd2;
sbit OV=PSW^2;
sbit OV=0xD0^2;
  1. sfr:定义8位特殊功能寄存器,直接绑定硬件寄存器地址,reg52.h头文件内部大量使用sfr定义P0‑P3等端口
sfr P1 = 0x90;

七、本章小结

1、LED必须串联限流电阻,防止烧毁
2、可以整体赋值寄存器或者sbit单独控制单个IO引脚
3、软件空循环实现延时,完成LED闪烁效果
4、流水灯可以使用3种不同编码思路实现

下一章预告:独立按键检测,软件消抖原理与代码实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值