Implementering af et LED-åndelys ved hjælp af 51 Microcontroller

Jun 11, 2026 Læg en besked

[Indledning]


Mikrocontrollerteknologi er en uundværlig mainstream-teknologi inden for moderne industriel automation, elektronik, elektroteknik og tingenes internet (IoT). Efterhånden som vores liv bliver mere og mere smart, har mikrocontrollerteknologi gennemsyret stort set alle aspekter af vores daglige liv, såsom i smarte riskogere, smarte højttalere og meget mere.


Med dette i tankerne har artiklerne "Relearning the 51 Microcontroller" til formål at hjælpe begyndere med at komme i gang med mikrocontrollerteknologi. Vi starter med den enkleste opgave-at tænde en enkelt lysdiode-og gradvist gå videre til implementering af moduler såsom knapstyring, LCD1602-skærmen, DS18B20 og DS1302 temperatursensorer og kommunikation mellem to mikrocontrollere. Vi vil også dække hardwarekommunikationsprotokoller som UART, I²C og SPI. Ved at kombinere disse koncepter med C-programmeringsteknikker bruger vi ingeniørprojekter fra den virkelige{10}}verden til at illustrere programmeringstilgange, så du fleksibelt kan anvende C-pointere og -strukturer for at opnå modulær programmering.


Lad os nu vende tilbage til hovedemnet: Brug af en 51 mikrocontroller til at styre en LED og skabe en vejrtrækningslyseffekt.

 

[Sådan fungerer åndedrætslys]


Lad os først tage et kig på, hvordan en vejrtrækningslyseffekt virker.
Et vejrtrækningslys lyser gradvist op og dæmpes derefter gradvist, og gentager denne cyklus på en måde, der ligner vejrtrækning. Men da en mikrocontrollers ben kun kan udsende enten et 1 (til) eller et 0 (fra), hvordan kan en gradvis overgangseffekt opnås?
Dette skyldes det vedvarende syn i vores øjne. Når vi ser på noget, forbliver billedet dannet af vores øjne i 0,04 sekunder (denne figur blev fundet online).
Hvis vi beregner baseret på 0,04 sekunder, svarer det til 40 ms. Derfor, når LED'en er tændt og slukket i 20 ms hver, ser det ud for det menneskelige øje, som om det lyser konstant.

图片

Er effekten af ​​at en LED blinker tændt i 20 ms og slukket i 20 ms den samme som at den bliver tændt hele tiden?

 

Haha, det er bestemt anderledes. Når lyset skifter mellem tændt og slukket hvert 20. millisekund, er den effekt, vi ser, svagere, end når den forbliver tændt konstant. Hvis vi antager, at lysstyrken af ​​et konstant tændt lys er 100 %, så er lysstyrken af ​​et lys, der skifter mellem tændt og slukket hvert 20. millisekund, 50 %. Ud fra dette kan vi justere LED'ens lysstyrke.

图片

 

På dette tidspunkt kan vi justere lysstyrken på LED'en (ved at indstille varigheden af ​​det høje niveau inden for 40ms-cyklussen). Dette er princippet bag den velkendte PWM (Pulse Width Modulation) metode til lysstyrkekontrol, og indstilling af varigheden af ​​det høje niveau svarer til at justere arbejdscyklussen (dvs. varigheden af ​​det høje niveau divideret med den samlede cyklus: 20/40=50%).


Her er den vigtigste faktor denne arbejdscyklus. For eksempel, hvis perioden er 20 ms, med lysdioden skiftende mellem 10 ms tændt og 10 ms slukket, er den opfattede lysstyrke stadig 50% (dvs. arbejdscyklussen er 10/20=50%).

Lad os derefter se, hvordan dette implementeres i programmet.

 

[Programimplementering]


Tænder en LED
Lad os først starte med at tænde en LED, og ​​derefter implementerer vi gradvist en åndedrætslyseffekt. Den hardware, vi skal bruge, er som følger:

Udviklingsnævn ZeroOne Microcontroller Training Development Board
Mikrocontroller model STC89C52
LED interface Pin P4^4
图片

 

Fra skemaet kan vi se, at LED'en er forbundet til pin P4^4 på mikrocontrolleren. Når mikrocontrolleren udsender et 1, tændes LED'en; når den udsender et 0, slukker LED'en. Derfor er programmet til at tænde en LED ret simpelt, som vist nedenfor:

info-299-230

 

 

Programmet til at tænde en LED er ret simpelt; Jeg er sikker på, at alle ved, hvordan man gør det.
 

Justering af LED-lysstyrke


Dernæst implementerer vi en funktion, der giver os mulighed for at justere lysstyrken (dvs. justere driftscyklussen), som følger:

info-400-538


 

Definer en statisk variabel `duty_cycle` for at gemme duty cycle. Når `flag` er 1, øges arbejdscyklussen gradvist til 255, derefter indstilles `flag` til 0, og `duty_cycle` falder gradvist fra 255 til 0. Gentag denne cyklus.
Haha, på dette tidspunkt tror du måske, at vejrtrækningslyset allerede virker, men det er det ikke. Hvis du ikke tror mig, så prøv selv koden ovenfor.

Så hvor er problemet helt præcist?


Problemet ligger i vores direkte opkald til lysstyrke-indstillingsfunktionen `set_led_luminance()`. Denne funktion tager 40 ms at fuldføre en cyklus, hvilket betyder, at arbejdscyklussen ikke kan ændres i løbet af disse 40 ms; ellers virker lysstyrkejusteringen ikke. Lad os tage et nyt kig på funktionen `breath_led`. Efter hvert kald til `set_led_luminance()` for at indstille driftscyklussen, ændrer den straks `duty_cycle`-værdien uden at vente i 40 ms.


På dette tidspunkt skal vi tilføje en softwaretimer for at opdatere `duty_cycle`-værdien efter 40 ms er gået. Det ændrede program er som følger:

info-495-656

 

 

Bemærk: Timerens varighed skal blot være længere end 40 ms (hvilket betyder, at værdien af ​​`s_breathCounter` skal være større end 255), men det er bedst at indstille den til et multiplum af cyklussen. For eksempel, hvis vores cyklus er 255 (dvs. 256 værdier fra 0 til 255), kan vi indstille den til det dobbelte af denne værdi: 256 * 2 - 1=511 (dvs. 512 værdier fra 0 til 511).
Og der har du det-vores åndelys er komplet! Er det ikke simpelt? (* ̄︶ ̄)

 

Det næste er dagens bonussektion.

Selvom vi har opnået åndedrætslyseffekten, er koden ikke helt kortfattet eller elegant nok-den bruger en masse if og else-sætninger. Lad os se, om vi kan forenkle det yderligere.

Lad os først forenkle dette afsnit af set_led_luminance()-funktionen, som vist i figuren nedenfor.
 

图片

 

Før vi forenkler dette, lad os dække et hurtigt tip om C: den bitvise OG-operation.

info-600-117

 

Ud fra dette ved vi, at uanset om det er 1 eller 0, vil en bitvise AND-operation med 0 resultere i 0.

Uanset om det er 1 eller 0, vil udførelse af en bitvise OG-operation med 1 resultere i den oprindelige værdi.

For nemheds skyld bruger vi hexadecimal notation (med "0x" foran); for eksempel svarer 0xff til 255 i decimal. Derfor,

 

Når et tal, der er mindre end eller lig med 0xff, AND-sættes med 0xff, er resultatet selve tallet, som vist nedenfor

info-534-63

 

 

Hvad sker der, hvis du udfører en bitvise AND-operation mellem et tal større end 0xff og 0xff?

info-551-63

Resultatet er resten, når dette tal divideres med (0xff + 1) (dvs. resultatet er stadig mellem 0 og 0xff).
Med denne bitvise AND operation kan koden ovenfor simplificeres til

info-550-64

 

 

På denne måde vil værdien af ​​s_Counter altid være inden for området 0x00 til 0xff.
På samme måde kan softwaretimeren i breath_led-funktionen ovenfor også forenkles som følger:

info-389-353

I linje 3 er 0x1ff 511 i decimal. Betingelsen er sand, når værdien af s_breathCounter er (0x1ff+1), eller 512, fordi 512 & 0x1ff=0. Udråbstegnet før det angiver en bitwise NOT-operation (for at være præcis er betingelsen opfyldt, når værdien af `s_breathCounter` er et multiplum af 512 af 512, eliminerer dette håb for at nulstille dette. forklaringen er klar-tænk over det). Hvis betingelsen er opfyldt, begynder arbejdscyklussen at stige eller falde.


Men er arbejdscyklusområdet ikke 0 til 255? Hvorfor bliver linje 5 også til 0x1ff (511)? Bare rolig-se på linje 8. Vi trækker 0xff fra igen, så arbejdscyklusområdet forbliver 0 til 255.


Linje 7-10 betyder: Når `duty_cycle > (0xff)`, dvs. 256-511, er subtrahering af 0xff det samme som at øge fra 1 til 255, så lysstyrken øges gradvist.


Når duty_cycle<= 0xff, the duty_cycle increases from 0 to 255, while the set brightness is 255 - duty_cycle. This effectively decreases the brightness from 255 to 0, causing the light to gradually dim. This achieves the breathing light effect.


Haha, troede du, at vores forenkling var forbi?

 

Nej, nej, nej

Faktisk kunne linje 7 til 10 forenkles endnu mere. Det er her den absolutte værdi-funktion kommer til nytte.

Hvad? Hvorfor bruge funktionen absolut værdi?

 

Se på linje 10: 0xff - duty_cycle svarer til duty_cycle - 0xff og tager derefter den absolutte værdi. Okay, her er den forenklede kode:

set_led_luminance(ABS(duty_cycle - (0xff)));

 

 

Makrofunktionen til at tage den absolutte værdi er som følger

#define ABS(N) ((N) < 0 ? -(N) : (N))

 

Endelig har jeg inkluderet hele den forenklede kode nedenfor

 

info-562-684

Hvad synes du? Er det ikke simpelt? (* ̄︶ ̄)

Send forespørgsel

whatsapp

Telefon

E-mail

Undersøgelse