【嵌入式51單片機】深入LED燈的奧秘:從原理,方法、控制、流水燈到相關擴展_#嵌入式硬件

🔥小龍報✨ 永遠相信美好的事情即將發生

【嵌入式51單片機】深入LED燈的奧秘:從原理,方法、控制、流水燈到相關擴展_#51單片機_02

文章目錄

  • 前言
  • 一、應用場景
  • 二、點燈原理
  • 2.1LED的限流電阻計算
  • 三、點亮LED
  • 3.1如何用單片機點亮LED
  • 3.2 通過編程控制芯片某個IO輸出高低電平
  • 3.3板卡LED部分的原理圖
  • 3.4點燈方法
  • 方法一:操作整個寄存器
  • 方法二 操作寄存器的某個位
  • 四、閃爍控制
  • 五、流水燈
  • 六、相關擴展
  • 總結與每日勵志

前言

本文討論了點亮 LED 的相關知識,包括應用場景、點燈原理、點亮方法、閃爍控制、流水燈實現以及相關擴展知識

一、應用場景

【嵌入式51單片機】深入LED燈的奧秘:從原理,方法、控制、流水燈到相關擴展_#單片機_03

二、點燈原理

插件led燈珠長引腳為正極,短引腳為負極。

【嵌入式51單片機】深入LED燈的奧秘:從原理,方法、控制、流水燈到相關擴展_#單片機_04


【嵌入式51單片機】深入LED燈的奧秘:從原理,方法、控制、流水燈到相關擴展_#嵌入式硬件_05


LED(發光二極管)兩端存在電壓差,有一定的電流流過時會亮起。電流可以理解為水流,電壓差可以理解為水位差,當兩個點水位高度不一樣時,水流會從高水位流向低水位。

【嵌入式51單片機】深入LED燈的奧秘:從原理,方法、控制、流水燈到相關擴展_單片機_06

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 歐姆.

【嵌入式51單片機】深入LED燈的奧秘:從原理,方法、控制、流水燈到相關擴展_#51單片機_07

很多時候你看到別人設計的電路中,LED串聯的電阻去到幾百歐或幾千歐都有,是設計錯了嗎?
實際上這是非常合理的, 因為大多數電路中,LED只是一個提示燈,對亮度沒有要求,反而希望把功耗降低,所以需要增大限流電阻來實現超低電流 ,像產品中的貼片LED去到0.5ma也是能看清楚燈光的。

三、點亮LED

3.1如何用單片機點亮LED

首先是接線部分,我們可以通過單片機的引腳,又叫做GPIO,這些IO都是具備輸出和輸入能力的,什麼是 GPIO 呢?GPIO 的 英文全程是 General-purpose input/output,翻譯過來就是:通用輸入輸出,也就是我們可以設置某個引腳輸出高低電平,或讀取某個引腳輸入的電平。


【嵌入式51單片機】深入LED燈的奧秘:從原理,方法、控制、流水燈到相關擴展_#單片機_08


【嵌入式51單片機】深入LED燈的奧秘:從原理,方法、控制、流水燈到相關擴展_#51單片機_09


所以,所以我們的做法是:將LED和電阻串聯,一段接負極(接地),另一端接單片機IO口,然後 控制單片機的IO口電平 就可以決定LED是否點亮了

【嵌入式51單片機】深入LED燈的奧秘:從原理,方法、控制、流水燈到相關擴展_寄存器_10


注意:通常我們不採用第一種情況,因為單片機IO口雖然可以達到高電壓,但是輸出電流不會大,因此單片機IO口給LED供電時可能會出現電流不足,導致LED不會全亮。

因此,我們一般選擇第二種,利用電源直接供電,電流灌入單片機IO口的方式來給LED燈供電

3.2 通過編程控制芯片某個IO輸出高低電平

操作芯片對應IO的寄存器即可,這部分我們可以在芯片手冊上看到

51單片機的每組IO口的電平狀態都被儲存在一個單獨的8位寄存器中,寄存器的位為0或1就分別對應其相應的GPIO電平為低或高。

【嵌入式51單片機】深入LED燈的奧秘:從原理,方法、控制、流水燈到相關擴展_#51單片機_11

3.3板卡LED部分的原理圖

【嵌入式51單片機】深入LED燈的奧秘:從原理,方法、控制、流水燈到相關擴展_單片機_12


【嵌入式51單片機】深入LED燈的奧秘:從原理,方法、控制、流水燈到相關擴展_寄存器_13


【嵌入式51單片機】深入LED燈的奧秘:從原理,方法、控制、流水燈到相關擴展_單片機_14


因為擺放順序錯的原因,LED燈的順序如下哦:

【嵌入式51單片機】深入LED燈的奧秘:從原理,方法、控制、流水燈到相關擴展_#51單片機_15

3.4點燈方法

方法一:操作整個寄存器

直接在C語言代碼中用賦值法即可,例如操作P2口的P2.0 P2.1 P2.4 P2.6口輸出高電平的代碼是

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前綴來表示十六進制。

【嵌入式51單片機】深入LED燈的奧秘:從原理,方法、控制、流水燈到相關擴展_寄存器_16

方法二 操作寄存器的某個位

在C語言中,先定義你要操作的位,使用 關鍵字sbit(這是標準C語言沒有的關鍵字,是C51編譯器的拓展關鍵字,用於定義寄存器的某個位)。你就可以理解成sbit就是給寄存器的某個位起一個別名。之後用等號賦值即可更改此位的0或1

例:
sbit led1= Px^y;

(1)符號^在C51中也表示寄存器的第某位,如上方代碼,Px^y表示Px寄存器的第y位。

//定義變量led1表示P2寄存器的第7位
sbit led1= P2^7;

注意:"^"實質代表的是異或運算,可以算一下,恰好符合。

//定義變量led1表示P2寄存器的第7位
sbit led1= P2^7;
//定義變量led2表示P2寄存器的第6位
sbit led2= P2^6;
        ...
        //將P2.7口 輸出低電平
        led1= 0;
        //將P2.6口 輸出高電平
        led2= 1;
        ...

我們可以這樣來定義P2.7這個引腳的輸出低電平

#include <reg52.h>
sbit led = P2^7;
void main(void)
{
    led = 0;
    while(1)
    {
                
    }
}

四、閃爍控制

前面,我們通過設置某個引腳輸出低電平,點亮LED,也就是我們設置輸出高電平時,會關閉LED,那我們需要 實現LED閃爍的功能時,如何實現呢?
解決方案: 先點亮LED,延時一段時間,關閉LED,再延時一段時間,如此反覆,就可以得到一個閃爍的LED功能。
在單片機中如何實現延時功能呢?有以下幾種生成延時函數的生成方法
1、讓芯片循環執行一些無意義的代碼
我們知道,芯片執行每一句代碼都需要時間,假設執行一句代碼的時間為1ms,那我們點亮LED,然後執行500句(500ms)無意義的代碼,再關閉LED,就可以得到閃爍的效果啦。

//帶參延時函數
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工具生成

//延時函數,延時500ms
void delay_500ms()
{
        unsigned char i, j, k;
        i = 4;
        j = 129;
        k = 119;
        do
        {
                do
                {
                        while (--k);
                } while (--j);
        } while (--i);
}

最終效果:

#include <reg52.h>

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);
    }
}

五、流水燈

如果需要實現多個燈的顯示和熄滅呢?
其實就是流水燈的效果

#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();
        }
}

代碼優化:

#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
        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也有區別,這又是另外一個坑,這裏就不説了),它是為已經分配了內存空間的變量重新取一個別名,一般用來定義特殊功能寄存器的位變量,以方便對寄存器的某位進行操作的,
例:

bit i = 0;
//意思就是在內存中劃一塊空間給i,讓他存儲0這個數據位。
sbit Flag = P0^1;//意思就是給P0^1取一個別名,它叫做Flag,
他是一個位操作變量,它代表訪問的地址是P0^1,0x80的第二位數據位。

sbit的用法有三種:
第一種方法:sbit 位變量名=地址值
第二種方法:sbit 位變量名=SFR名稱^變量位地址值
第三種方法:sbit 位變量名=SFR地址值^變量位地址值

如定義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變量名=地址值。

例:sfr P1 = 0x90;
這樣的一行即定義P1 與地址0x90 對應,P1 口的地址就是0x90.
SFR的定義在頭文件reg51.h或reg52.h中。

總結與每日勵志

✨ ***本文介紹了LED點亮的原理、方法及擴展應用。主要內容包括:LED工作原理及限流電阻計算,單片機控制LED的接線方式與編程方法(通過寄存器操作或位操作),閃爍LED的實現原理及延時函數生成技巧(循環代碼或STC-ISP工具)。文章還提供了51單片機控制LED的具體代碼示例,並簡要提及流水燈等擴展應用場景。適合嵌入式初學者快速掌握LED控制的基礎知識。***

【嵌入式51單片機】深入LED燈的奧秘:從原理,方法、控制、流水燈到相關擴展_#51單片機_17