W naszym poprzednim samouczku dowiedzieliśmy się o miganiu diodą LED za pomocą mikrokontrolera PIC i zbudowaliśmy ten sam obwód na płycie Perf. Następnie użyliśmy PICkit 3, ICSP i MPLAB IPE do umieszczenia programu na naszej tablicy Perf. Teraz, w tym samouczku, przejdziemy do korzystania z większej liczby pinów mikrokontrolera PIC. Będziemy używać 7 wyjść (diod LED) i jednego wejścia. W tym samouczku użyjemy starej tablicy Perf (pokazanej poniżej) i dodamy patyki berg, aby wyciągnąć wymagane szpilki na drugiej płycie LED. Pod koniec tego samouczka wygenerujemy sekwencję migających diod LED za pomocą mikrokontrolera PIC PIC16F877A i nauczymy się, jak korzystać z wielu wejść i wyjść, a także dowiemy się, jak korzystać z wielu wejść i wyjść, a także dowiemy się, jak korzystać z pętli „for” i wywoływania funkcji.
Płytka LED to nic innego jak kolejna płytka perf, na której przylutujemy diody LED za pomocą rezystora ograniczającego prąd (pokazany poniżej). Dodamy również przycisk inicjujący sekwencję migania diody LED.
Schemat obwodu:
Mikrokontroler PIC PIC16F877A Dioda migająca Kod sekwencji i objaśnienie robocze:
Pełny kod został podany poniżej (sprawdź na końcu), tutaj przejdziemy do niego linijka po linijce. Ten kod zacznie świecić diodami LED w sposób sekwencyjny po naciśnięciu przycisku. Aby zrozumieć sekwencje, obejrzyj film na końcu samouczka. Poleciłbym porównać dane wyjściowe pokazane na filmie z poniższym kodem i spróbować zrozumieć program.
Spójrzmy na kod linia po linii. Pierwsze kilka wierszy służy do ustawiania bitów konfiguracyjnych, które zostały wyjaśnione w poprzednim samouczku, więc na razie je pomijam. Najlepszym sposobem zrozumienia każdego programu jest rozpoczęcie od funkcji głównej ( void main () ), więc zróbmy to
TRISB0 = 1; // Poinstruuj MCU, że pin 0 PORTB jest używany jako wejście dla przycisku. TRISD = 0x00; // Poinstruuj MCU, że wszystkie piny są wyprowadzane PORTD = 0x00; // Zainicjuj wszystkie piny na 0
Słowo TRIS jest używane do określenia, czy pin jest używany jako wejście / wyjście, a słowo PORT jest używane do tworzenia pinów High / Low. Linia TRISB0 = 1 uczyni 0-ty pin PORTU B jako wejście. To będzie nasz przycisk. Wiersze TRISD = 0x00; PORTD = 0x00; uczyni wszystkie piny portu D jako Wyjście i przypisze im początkową wartość LOW.
Ponieważ powiedzieliśmy, że B0 jest używane jako wejście, podłączamy jeden koniec przycisku do pinu B0, a drugi koniec do masy. Do tego czasu za każdym razem, gdy wciśniemy przycisk, styk zostanie utrzymany w uziemieniu, jak pokazano na powyższym schemacie połączeń. Ale aby to się stało, musimy użyć rezystora podciągającego, aby pin był trzymany wysoko, gdy przycisk nie jest wciśnięty. Rezystor podciągający to coś takiego.
Ale nasz PIC MCU ma wewnętrzny słaby rezystor podciągający, który może być aktywowany przez oprogramowanie w ten sposób, oszczędzając wiele kłopotów (gdy ma być podłączonych więcej przycisków).
Co to jest słaby rezystor podciągający?
Istnieją dwa rodzaje rezystorów podciągających, jeden to Weak Pull Up, a drugi to Strong Pull Up. Słabe rezystory podciągające mają dużą wartość, co pozwala na przepływ słabego prądu, a silne rezystory podciągające mają niską wartość, umożliwiając w ten sposób przepływ silnego prądu. Wszystkie MCU używają głównie słabych rezystorów podciągających. Aby aktywować to w naszym PIC MCU, musimy zajrzeć do naszego arkusza danych dla OPTION_REG (rejestr opcji), jak pokazano na poniższej migawce.
Jak pokazano, bit 7 dotyczy słabego rezystora podciągającego. Aby go aktywować, należy ustawić zero. Odbywa się to przez OPTION_REG <7> = 0 . Dotyczy to w szczególności bitu 7, który pozostawia pozostałe bity do wartości domyślnych. W ten sposób przechodzimy do naszej pętli while, w której sprawdza, czy przycisk jest naciśnięty za pomocą if (RB0 == 0). Jeśli warunek jest spełniony, wywołujemy naszą funkcję z parametrami 1, 3, 7 i 15.
mrugnięcie (1); // WYWOŁANIE FUNKCJI 1 z parametrem 1 sblink (3); // FUNCTION CALL 3 z parametrem 3 sblink (7); // FUNCTION CALL 7 z parametrem 7 sblink (15); // FUNCTION CALL 4 z parametrem 15
Dlaczego używamy funkcji?
Funkcje służą do zmniejszenia liczby wierszy w naszym kodzie. To właśnie wiedziałaby większość z nas. Ale dlaczego musimy zmniejszyć liczbę linii, szczególnie jeśli chodzi o programowanie MCU. Powodem jest ograniczona ilość miejsca w pamięci programu. Jeśli nie zoptymalizujemy odpowiednio kodu, może zabraknąć miejsca w pamięci. Przyda się to, gdy będziemy pisać długie strony kodów.
Każda funkcja będzie miała definicję funkcji (w naszym przypadku sblink (int get) ) i funkcję Call (w naszym przypadku sblink (1) ). Posiadanie deklaracji funkcji jest opcjonalne, aby tego uniknąć, umieściłem definicję funkcji przed wywołaniem funkcji w mojej funkcji głównej.
Parametry funkcji to wartości, które zostaną przekazane z wywołania funkcji do definicji funkcji. W naszym przypadku wartości całkowite (1, 3, 7, 15) to parametry przekazywane z wywołania funkcji, a zmienna „get” pobiera wartość parametrów do definicji funkcji w celu ich przetworzenia. Funkcja może mieć więcej niż jeden parametr.
Po wywołaniu funkcji zostaną wykonane poniższe wiersze definicji funkcji.
for (int i = 0; i <= 7 && RB0 == 0; i ++) {PORTD = get << i; // Ruch diody LED Sekwencja w lewo __delay_ms (50); } for (int i = 7; i> = 0 && RB0 == 0; i--) {PORTD = get << i; // Ruch diody LED Sekwencja w lewo __delay_ms (50); }
Teraz ta linia wydaje się dziwna: PORTD = get << i . Wyjaśnię, co się tutaj właściwie dzieje.
„<<” to lewy operator przesuwający, który przesuwa wszystkie bity do lewej pozycji. Teraz, gdy wywołujemy funkcję sblink (int get) z parametrem „1” jako sblink (1), spowoduje to, że wartość „get” będzie równa 1, co w systemie binarnym wynosi 0b00000001. Stąd ta linia będzie wyglądać następująco: PORTD = 0b00000001 << i .
Wartość „i” będzie się zmieniać od 0 do 7, ponieważ użyliśmy „pętli for ” for (int i = 0; i <= 7 && RB0 == 0; i ++). Wartość „i” wynosząca od 0 do 7 zmieni wynik w następujący sposób:
Jak widać, włączyliśmy jedną diodę na raz (od lewej do prawej), pozostawiając resztę WYŁĄCZONĄ. Kolejna pętla for (int i = 7; i> = 0 && RB0 == 0; i--) , również zrobi to samo, ale tym razem dioda LED zostanie włączona od prawej do lewej w sekwencji, jak zaczynaliśmy od 7 i schodziliśmy do 0. Zastosowaliśmy opóźnienie 200 ms, abyśmy mogli wizualizować włączanie i wyłączanie diody LED.
Teraz, gdy przekażemy wartość 3 w funkcji sblink (int get) , to funkcja sblink (3) zostanie wykonana, co spowoduje, że wartość 'get' będzie równa 0b00000011, stąd wynik na PORTD będzie wyglądał następująco:
Więc teraz tym razem dwie diody LED zostaną włączone w dowolnym momencie za pomocą sblink (3). Podobnie dla sblink (7) i sblink (15), kolejno trzy i cztery diody będą się świecić. Gdy to się skończy, włączymy wszystkie diody LED za pomocą wiersza PORTD = 0xFF . Sprawdź poniższy film, aby uzyskać pełną demonstrację.
Mam nadzieję, że zrozumiałeś kod i dzięki temu nauczyłeś się używać funkcji, pętli „for” i „while”, aby uzyskać pożądane wyniki. Teraz możesz modyfikować kod, aby uzyskać inną sekwencję migania diody LED. Śmiało, skompiluj swój kod i zrzuć go na MCU i ciesz się wynikami. Możesz skorzystać z sekcji komentarzy, jeśli gdzieś utkniesz. Załączam również pliki symulacji i programu.
To na razie wszystko, w następnym samouczku dowiemy się, jak używać timerów PIC16F877A zamiast korzystać z funkcji opóźnienia. Możesz przeglądać wszystkie samouczki mikrokontrolera PIC tutaj.