[Wstęp]
Technologia mikrokontrolerów jest nieodzowną technologią głównego nurtu współczesnej automatyki przemysłowej, elektroniki, elektrotechniki i Internetu Rzeczy (IoT). W miarę jak nasze życie staje się coraz bardziej inteligentne, technologia mikrokontrolerów przeniknęła praktycznie każdy aspekt naszego codziennego życia, na przykład w inteligentnych urządzeniach do gotowania ryżu, inteligentnych głośnikach i nie tylko.
Mając to na uwadze, seria artykułów „Relearning the 51 Microcontroller” ma na celu pomóc początkującym w rozpoczęciu pracy z technologią mikrokontrolerów. Zaczniemy od najprostszego zadania,-włączenia pojedynczej diody LED-i stopniowo przejdziemy do wdrożenia modułów, takich jak sterowanie przyciskami, wyświetlacz LCD1602, czujniki temperatury DS18B20 i DS1302 oraz komunikacja między dwoma mikrokontrolerami. Omówimy także sprzętowe protokoły komunikacyjne, takie jak UART, I²C i SPI. Łącząc te koncepcje z technikami programowania w języku C, wykorzystamy-rzeczywiste projekty inżynieryjne do zilustrowania podejść programistycznych, umożliwiając elastyczne stosowanie wskaźników i struktur w języku C w celu osiągnięcia programowania modułowego.
Wróćmy teraz do głównego tematu: wykorzystanie mikrokontrolera 51 do sterowania diodą LED i stworzenia efektu oddychającego światła.
[Jak działają światła oddechowe]
Przyjrzyjmy się najpierw, jak działa efekt oddychającego światła.
Światło oddechowe stopniowo się rozjaśnia, a następnie stopniowo przygasa, powtarzając ten cykl w sposób przypominający oddychanie. Jednakże, ponieważ piny mikrokontrolera mogą wysyłać tylko 1 (wł.) lub 0 (wył.), w jaki sposób można osiągnąć efekt stopniowego przejścia?
Wynika to z utrzymywania się wzroku w naszych oczach. Kiedy na coś patrzymy, obraz tworzony przez nasze oczy utrzymuje się przez 0,04 sekundy (wartość tę znaleziono w Internecie).
Jeśli obliczymy na podstawie 0,04 sekundy, będzie to równe 40 ms. Dlatego też, gdy dioda LED włącza się i wyłącza na 20 ms każde, ludzkie oko wydaje się, jakby świeciła stale.

Czy efekt migania diody LED przez 20 ms i wyłączania na 20 ms jest taki sam, jak włączenie jej przez cały czas?
Haha, na pewno jest inaczej. Kiedy światło włącza się i wyłącza co 20 milisekund, efekt, który widzimy, jest słabszy niż w przypadku, gdy światło pozostaje włączone w sposób ciągły. Jeśli założymy, że jasność światła stale świecącego wynosi 100%, wówczas jasność światła, które włącza się i wyłącza na zmianę co 20 milisekund, wynosi 50%. Na tej podstawie możemy dostosować jasność diody LED.

W tym momencie możemy dostosować jasność diody LED (ustawiając czas trwania wysokiego poziomu w cyklu 40ms). Na tej zasadzie opiera się-znana metoda PWM (modulacja szerokości impulsu) kontroli jasności, a ustawienie czasu trwania wysokiego poziomu jest równoznaczne z dostosowaniem cyklu pracy (tj. czasu trwania wysokiego poziomu podzielonego przez całkowity cykl: 20/40=50%).
Tutaj najważniejszym czynnikiem jest cykl pracy. Na przykład, jeśli okres wynosi 20 ms, a dioda LED zmienia się na 10 ms włączona i 10 ms wyłączona, postrzegana jasność nadal wynosi 50% (tj. współczynnik wypełnienia wynosi 10/20=50%).
Następnie zobaczmy, jak jest to zaimplementowane w programie.
[Wdrożenie programu]
Włączanie diody LED
Najpierw zacznijmy od włączenia diody LED, a następnie stopniowo będziemy wdrażać efekt oddychającego światła. Sprzęt, którego będziemy używać, jest następujący:
| Rada Rozwoju | Płytka rozwojowa do szkolenia mikrokontrolerów ZeroOne |
|---|---|
| Model mikrokontrolera | STC89C52 |
| Interfejs LED | Przypnij P4^4 |

Ze schematu widać, że dioda LED jest podłączona do pinu P4^4 mikrokontrolera. Kiedy mikrokontroler wyprowadza wartość 1, dioda LED włącza się; gdy na wyjściu pojawi się 0, dioda LED zgaśnie. Dlatego program włączający diodę LED jest dość prosty, jak pokazano poniżej:

Program do włączenia diody LED jest dość prosty; Jestem pewien, że każdy wie, jak to zrobić.
Regulacja jasności diody LED
Następnie zaimplementujemy funkcję, która pozwoli nam dostosować jasność (tj. dostosować cykl pracy) w następujący sposób:

Zdefiniuj zmienną statyczną „cykl_pracy” do przechowywania cyklu pracy. Gdy „flaga” wynosi 1, cykl pracy stopniowo wzrasta do 255, następnie ustawia się „flagę” na 0, a „cykl pracy” stopniowo zmniejsza się z 255 do 0. Powtórz ten cykl.
Haha, w tym momencie można by pomyśleć, że światło oddechowe już działa, ale tak nie jest. Jeśli mi nie wierzysz, wypróbuj powyższy kod samodzielnie.
Gdzie więc dokładnie leży problem?
Problem leży w naszym bezpośrednim wywołaniu funkcji-ustawiania jasności `set_led_luminance()`. Wykonanie jednego cyklu tej funkcji zajmuje 40 ms, co oznacza, że w ciągu tych 40 ms nie można zmienić cyklu pracy; w przeciwnym razie regulacja jasności nie będzie działać. Przyjrzyjmy się jeszcze raz funkcji „breath_led”. Po każdym wywołaniu funkcji `set_led_luminance()` w celu ustawienia cyklu pracy, natychmiast zmienia ona wartość `set_led_luminance()`, bez czekania 40 ms.
W tym momencie musimy dodać timer programowy, aby zaktualizować wartość „cyklu_obowiązku” po upływie 40 ms. Zmodyfikowany program wygląda następująco:

Uwaga: Czas trwania timera musi być większy niż 40 ms (co oznacza, że wartość `s_breathCounter` musi być większa niż 255), ale najlepiej jest ustawić go na wielokrotność cyklu. Na przykład, jeśli nasz cykl wynosi 255 (tj. 256 wartości od 0 do 255), możemy ustawić go na dwukrotnie większą wartość: 256 * 2 - 1=511 (tj. 512 wartości od 0 do 511).
I gotowe,-nasza lampa oddechowa jest gotowa! Czy to nie jest proste? (* ̄︶ ̄)
Następna w kolejce jest dzisiejsza sekcja bonusowa.
Chociaż udało nam się uzyskać efekt oddychającego światła, kod nie jest wystarczająco zwięzły i elegancki,-wykorzystuje wiele instrukcji if i else. Zobaczmy, czy możemy to jeszcze bardziej uprościć.
Najpierw uprośćmy tę sekcję funkcji set_led_luminance(), jak pokazano na poniższym rysunku.

Zanim to uprościmy, omówmy krótką wskazówkę dotyczącą języka C: bitowej operacji AND.

Z tego wiemy, że niezależnie od tego, czy jest to 1, czy 0, wykonanie bitowej operacji AND na 0 daje 0.
Niezależnie od tego, czy jest to 1, czy 0, wykonanie bitowej operacji AND na 1 daje pierwotną wartość.
Dla wygody używamy notacji szesnastkowej (z przedrostkiem „0x”); na przykład 0xff odpowiada 255 w systemie dziesiętnym. Dlatego,
Gdy liczba mniejsza lub równa 0xff zostanie poddana operacji AND z 0xff, wynikiem będzie sama liczba, jak pokazano poniżej

Co się stanie, jeśli wykonasz operację bitową AND między liczbą większą niż 0xff i 0xff?

Wynik jest resztą z dzielenia tej liczby przez (0xff + 1) (tzn. wynik nadal mieści się w przedziale od 0 do 0xff).
Dzięki tej bitowej operacji AND powyższy kod można uprościć

W ten sposób wartość s_Counter będzie zawsze mieścić się w zakresie od 0x00 do 0xff.
Podobnie, timer programowy w powyższej funkcji Breath_led można również uprościć w następujący sposób:

W linii 3 0x1ff to 511 w systemie dziesiętnym. Warunek jest prawdziwy, gdy wartość s_breathCounter wynosi (0x1ff+1), lub 512, ponieważ 512 & 0x1ff=0. Wykrzyknik przed nim oznacza bitową operację NOT (dokładniej warunek jest spełniony, gdy wartość `s_breathCounter` jest wielokrotnością 512; eliminuje to konieczność resetowania `s_breathCounter`. Mam nadzieję to wyjaśnienie jest jasne.-Przemyśl je). Jeśli warunek jest spełniony, cykl pracy zaczyna się zwiększać lub zmniejszać.
Ale czy zakres cyklu pracy nie mieści się w zakresie od 0 do 255? Dlaczego linia 5 również staje się 0x1ff (511)? Nie martw się,-spójrz na linię 8. Ponownie odejmujemy 0xff, więc zakres współczynnika wypełnienia pozostaje w zakresie od 0 do 255.
Linie 7–10 oznaczają: Gdy „cykl_pracy > (0xff)”, tj. 256–511, odjęcie 0xff jest równoznaczne ze zwiększeniem od 1 do 255, zatem jasność stopniowo wzrasta.
Kiedy cykl_pracy<= 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, myśleliście, że nasze uproszczenia się skończyły?
Nie, nie, nie
Właściwie linie od 7 do 10 można jeszcze bardziej uprościć. Tutaj z pomocą przychodzi funkcja wartości bezwzględnej.
Co? Po co używać funkcji wartości bezwzględnej?
Spójrz na linię 10: 0xff - cykl_pracy jest równoważny cyklowi pracy - 0xff, a następnie przyjmuje wartość bezwzględną. OK, oto uproszczony kod:
Funkcja makro służąca do przyjmowania wartości bezwzględnej jest następująca
Na koniec zamieściłem poniżej cały uproszczony kod

Jak myślisz? Czy to nie proste? (* ̄︶ ̄)




