Kurs # podstawy programowania, porty I/O W drugiej części kursu zaczniemy pisać programy. Na początku zajmiemy się kompletnymi podstawami. operuje na dostosowanym do platformy języku C. Artykuł ten wprowadzi więc w podstawy programowania w C i przedstawi jego praktyczne wykorzystanie na przykładzie portów I/O. Nawigacja serii artykułów: «poprzednia część następna część»» Pokaż/ukryj cały spis treści «Kup zestaw elementów i zacznij naukę w praktyce! Przejdź do strony dystrybutora» Podstawowy szkielet programu Każdy program komputerowy jest zbiorem rozkazów. Dedykowany układ zwany licznikiem rozkazów wywołuje kolejne rozkazy jeden po drugim. W języku C wszystkie instrukcje, które chcemy wykonać, umieszczamy w funkcji main (o funkcjach dokładniej później), która wygląda tak: int main() //Zawartość programu Uwaga! Musisz to zapamiętać! Symbolami // oznaczamy komentarze. Czyli informacje mieszczące się w jednej linijce, które pomagają człowiekowi w zrozumieniu programu. Podczas kompilacji zostają one pominięte. Jeśli chcemy umieścić dłuższy komentarz, to należy zawrzeć go /* w takich symbolach */. Komentowanie jest bardzo ważne! Pamiętajcie, aby komentować kod nawet, gdy programy piszecie tylko na własny użytek. W pewne sprawy są uproszczone. Otóż w każdym programie najpierw niektóre instrukcje wykonują się jednorazowo, a następnie inne, wykonują się w pętli. //Instrukcje, które wykonają się jeden raz //Instrukcje, które będą wykonywały się w koło (w pętli) W praktyce pierwsza funkcja będzie zawierała najczęściej pewne ustawienia. Dzięki nim dane piny mikrokontrolera będą ustawione jako wejścia lub wyjścia. Uruchomimy bardziej zaawansowane peryferia oraz wykonamy akcje, które mają dziać się tylko raz, po włączeniu zasilania. W drugiej funkcji umieścimy właściwy kod aplikacji, który będzie wykonywał się cały czas (w pętli). Dużo łatwiej zrozumiesz to na praktycznych przykładach, które znajdują się dalej. Funkcje co oznaczają te zapisy? Funkcje można pisać samodzielnie, może również korzystać z gotowych, dostarczanych przez producentów lub przez maniaków programowania, którzy zechcieli podzielić się własnym kodem. Na początku kursu skupimy się na wykorzystywaniu funkcji dostarczanych w bibliotekach razem z kompilatorem. Nie zaszkodzi jednak odrobina szczegółów na ich temat. W języku C istnieje pojęcie funkcji. Skojarzenie z matematyką jest tutaj trafne. Otóż okazuje się, że funkcja w językach programowania to blok (lista) pewnych wyodrębnionych rozkazów z głównego kodu, których wykonanie zapewnia jakiś wynik. Dla nas jest to wygodne, ponieważ raz zadeklarowaną funkcję możemy wywoływać dowolną ilość razy bez żmudnego powielania tych samych linii kodu wystarczy nazwa funkcji. Każda funkcja może przyjmować pewną ilość argumentów oraz (standardowo) zwracać jeden wynik. Programista może określać, jakimi wartościami będą wynik oraz dane wejściowe. Każda funkcja ma swój typ (czyli rodzaj wynik) może być liczbą, znakiem lub czymś jeszcze innym. Istnieje też specyficzny rodzaj funkcji nie zwracającą wyniku (ma ona przedrostek void).
Skupmy się na głównych funkcjach w programach pisanych na. Procedura setup ma za zadanie wykonać jednorazowo blok instrukcji, które się w niej znajdują. Jak wskazuje nazwa przeznaczona jest głównie do ustawień. W niej inicjalizowany jest procesor, konfigurowane są peryferia itd. Funkcja (procedura) loop jest pętlą nieskończoną. Znajdują się w niej instrukcje, które powinny wykonywać się bez przerwy. Przejdźmy do przykładów praktycznych. Pamiętaj, że podstawą w zrozumieniu programowania jest praktyka. Nie będziesz umiał wykorzystać zdobytej tu wiedzy, jeśli nie wykonasz ćwiczeń z kursu. Zestaw elementów do przeprowadzenia ćwiczeń Gwarancja pomocy na forum dla osób, które kupią poniższy zestaw! Teraz możesz kupić zestaw ponad 0 elementów niezbędnych do przeprowadzenia ćwiczeń z kursu u naszych dystrybutorów! Uwaga nowość! Masz już zestaw? Zarejestruj go! Sprawdź dlaczego warto» Wyprowadzenia UNO Tak jak zostało powiedziane w poprzedniej części, korzystając ze specjalnych złącz, do można podłączyć elementy zewnętrzne takie jak np.: diody i przełączniki. Za nim jednak do tego dojdziemy musimy poznać wyprowadzenie złącz oraz odpowiednie funkcje, które służą do operowania na portach I/O (Input/Output), czyli na portach wejścia/wyjścia.
Na powyższym zdjęciu zaznaczone zostały najważniejsze sygnały, do których mamy dostęp. Ciemnozielone sygnały (0-), to porty I/O (wejściowo/wyjściowe). Są to piny cyfrowe, czyli takie, których wyjściu możemy ustawić 0V lub V, takie same sygnały możemy z nich odczytywać. Oznacza, to że właśnie za ich pomocą możemy przykładowo sterować diodami lub odczytywać informacje z prostych czujników/przycisków. Jasnozielonym kolorem zaznaczone zostały wejścia analogowe (A0-A). Są to wyjątkowe wejścia, które pozwalają na pomiar napięcia (w zakresie 0-V). Jak niedługo przekonasz się sam, wejścia te są bardzo przydatne szczególnie podczas pomiarów wielkości fizycznych (np.: natężenie światła). Na niebiesko zaznaczone zostały alternatywne funkcje dla poszczególnych sygnałów pinów. Oznacza to, że oprócz bycia standardowym wejściem lub wyjściem mogą one pełnić bardziej skomplikowane funkcje. Zajmiemy się nimi później, na ten moment wystarczy jedynie krótki opis: SDA, SCL wyprowadzenia magistrali I²C, wykorzystywana np.: do komunikacji z bardziej zaawansowanymi czujnikami, TX, RX interfejs UART, wykorzystywany np.: do komunikacji z komputerem, PWM wyprowadzenia, na których możliwe jest generowanie sygnału prostokątnego o zmiennym wypełnieniu. Bardzo przydatna funkcja np.: przy sterowaniu serwomechanizmami, LED dioda świecąca, wbudowana na stałe w, która połączona jest z pinem nr. Kolor pomarańczowy, to wyprowadzenia które nie są programowalne. Odpowiadają one głównie za zasilanie układu. Zostaną one dokładniej omówione, gdy przyjdzie pora na ich wykorzystanie. Wyjścia w praktyce dioda LED Teraz zajmiemy się rzeczą najprostszą, włączymy diodę LED. Zgodnie z powyższym opisem możemy do tego wykorzystać dowolny pin I/O. Na początek wybierzmy wyjście cyfrowe o nr. Wyjście cyfrowe jest to wyjście, które możemy ustawić w jeden z dwóch stanów. Niski lub wysoki. W przypadku będzie to V lub 0V. Układ należy podłączyć zgodnie z poniższym rysunkiem. Diodę łączymy szeregowo z rezystorem (0R). Następnie dłuższą nóżkę diody (anodę) łączymy z wyprowadzeniem nr. Drugą, przez rezystor z masą, którą znajdziemy w złączu zasilania (opisaną jako GND).Na płytce znajdują się wyprowadzenia opisane jako GND. Możemy wybrać dowolne. UWAGA! Pamiętaj, aby podczas podłączania większości peryferiów (diody, buzzery) do robić to przez rezystory! Stosowne informacje znajdziesz na naszych rysunkach poglądowych. Brak rezystora możesz doprowadzić do USZKODZENIA podłączonych elementów, a nawet! Podłączenie diody do. Programowe włączenie diody jest bardzo proste. Podłącz do komputera za pomocą kabla USB. Uruchom IDE i przepisz poniższy kod. Następnie wgraj go na płytkę. Opis tej czynności znajdziesz w pierwszej części kursu. Staraj się przepisywać kody! Kopiowanie jest szybsze, ale sprawi, że będziesz mniej umiał!
pinmode(, OUTPUT); digitalwrite(, HIGH); Funkcja pinmode(pin, Tryb) umożliwia wybranie, czy dany pin jest wejściem, czy wyjściem. Pin może być liczbą całkowitą z zakresu od 0 do, zaś Tryb to: INPUT, OUTPUT, INPUT_PULLUP. Jeżeli chcemy sterować wyjściem, to zawsze używamy trybu Output. Pozostałe tryby zostaną omówione później. Dzięki takiej konfiguracji możemy ustawić stan logiczny na wyjściu (i dzięki temu włączyć diodę). Do tego celu służy funkcja digitalwrite(pin, Stan). Stan jest stanem logicznym, który może być HIGH bądź LOW (wysoki bądź niski). W naszym przykładzie dioda została już podłączona do masy, dlatego musi doprowadzić do niej stan wysoki stąd digitalwrite(, HIGH);. Każdy rozkaz kończymy średnikiem! Po jednorazowym ustawieniu pinu w stan wysoki jego wartość nie zmieni się do momentu, gdy sami ustawimy mu inną wartość. W związku z tym, program taki jak powyższy sprawi, że dioda będzie świeciła się cały czas. Opóźnienia w programie miganie diodą Tym razem będziemy diodą migać. Do tego potrzebna jest nowa funkcja, której zadaniem będzie wprowadzanie opóźnienia delay. Schemat połączeń jest dokładnie taki sam jak w pierwszym przypadku. Natomiast kod będzie wyglądał jak poniżej: 0 pinmode(, OUTPUT); //Konfiguracja pinu jako wyjście digitalwrite(, HIGH); //Włączenie diody delay(000); //Odczekanie sekundy digitalwrite(, LOW); //Wyłączenie diody delay(000); //Odczekanie jednej sekundy Stan wyjścia zmienia się tu cały czas w pętli nieskończonej. W programie zostały dodane opóźnienia z pomocą funkcji delay(czas) (dzięki temu miganie jest widoczne). Funkcja ta jako argument przyjmuje liczbę milisekund, jakie mają zostać przeczekane. Bez wprowadzonych opóźnień układ zmieniał by stan swojego wyjścia tak szybko, że zauważenie zmian gołym okiem byłoby niemożliwe. Możesz przeprowadzić taki eksperyment ustawiając opóźnienie na 0ms. Zadanie domowe nr. Sprawdź przy jakiej najmniejszej wartości opóźnień będziesz w stanie zauważyć miganie diody! Co stanie się, gdy dioda będzie migała zbyt szybko? Swoimi spostrzeżeniami podziel się w komentarzu! Zadanie domowe nr. Wybierz wolny pin i podłącz do niego drugą diodę. Napisz program, który będzie włączał obie diody LED. Następnie napisz program, w który sprawi, że obie diody będą migały na zmianę. Wejścia układu w praktyce instrukcja warunkowa Bardzo często chcemy, aby zaprogramowany układ mógł reagować na sygnały z zewnątrz. Tym razem do podłączymy oprócz diody przycisk. Należy zrobić to zgonie z poniższym przykładem. Jedna strona przycisku została podłączona do masy (minusa), druga do wyprowadzenia nr.
Podłączenie przycisku do. Uwaga! Przyciski dołączane do zestawów mają wyprowadzenia zamiast. Wszystko dlatego, aby pasowały lepiej do płytki stykowej. Nie musisz przejmować się tym, że przełącznik na grafikach ma wyjścia. Zadanie na będzie proste, ale musimy wykorzystać coś nowego instrukcje warunkowe. Naszym celem jest stworzenie programu, który w momencie wciśnięcia przycisku włączy diodę. Przejdźmy do realizacji zadania. Oczekujemy, że program będzie nieustannie w jednym z dwóch stanów dioda włączona lub wyłączona. Na początek konieczne jest odczytanie stanu logicznego, który występuje na wejściu z przyciskiem. Z konfiguracja wejścia spotkasz się tutaj pierwszy raz. Zwróć uwagę, na wcześniej wspomniany tryb INPUT_PULLUP. Będziemy wykorzystywać go za każdym razem, gdy do podłączymy przełącznik. Pierwszy człon nazwy (input) oznacza oczywiście wejście. natomiast drugi (pullup) sugeruje nam włączenie wewnętrznego rezystora podciągającego wejście. Jeśli nie wiesz o czym mowa, to zajrzyj do tego artykułu. Teraz musimy odczytać stan wejścia. Do tego konieczna jest funkcja digitalread(pin), która zwraca wartość HIGH bądź LOW, zależnie od stanu. W naszym układzie przycisk zwiera wejście z masą (LOW). Samo odczytanie wejścia nic nam nie da, musimy umieć uzależnić od tej informacji działanie programu. Stąd instrukcja warunkowa (potocznie if lub warunek). Instrukcja ta jest bardzo popularna. Dzięki niej możemy wykonać daną część kodu, jeśli zaszły pewne okoliczności. Czyli np.: jeśli wciśnięto przycisk. 0 [...] //Kod wykonywany przy każdym obiegu pętli if ( WARUNEK ) /* Kod wykonywany tylko, gdy w danym obiegu pętli spełniony jest WARUNEK */ //Kod wykonywany przy każdym obiegu pętli Instrukcja ta może zostać bardzo łatwo rozbudowana o część kodu, która zostanie wykonana tylko, gdy warunek nie zostanie spełniony. Służy do tego instrukcja else. [...]
0 //Kod wykonywany przy każdym obiegu pętli if ( WARUNEK ) /* Kod wykonywany tylko, gdy w danym obiegu pętli spełniony jest WARUNEK */ else /* Kod wykonywany tylko, gdy w danym obiegu pętli warunek NIE jest spełniony*/ //Kod wykonywany przy każdym obiegu pętli Łącząc zdobytą wiedzę możemy stworzyć program realizujący nasze zadanie. Przeanalizuj go, a następnie wgraj do. 0 pinmode(, OUTPUT); //Dioda jako wyjście pinmode(, INPUT_PULLUP); //Przycisk jako wejście digitalwrite(, LOW); //Wyłączenie diody if (digitalread() == LOW) //Jeśli przycisk wciśnięty digitalwrite(, HIGH); //Włącz diodę else //Jeśli warunek nie został spełniony (przycisk nie jest wciśnięty) digitalwrite(, LOW); //Wyłącz diodę Program taki jest jednak mało użyteczny. Po co nam włącznik światła, który działa tylko, gdy go trzymamy palcem? Czy nie lepiej byłoby, gdyby po wciśnięciu przycisku dioda świeciła przez określony czas? Przykład Włącznik światła z czasomierzem Załóżmy, że chcemy przerobić powyższy przykład tak, aby dioda świeciła przez 0 sekund od wciśnięcia przycisku. Później ma być wyłączona, oczywiście tylko do czasu ponownego wciśnięcia przycisku. Czy jesteś w stanie napisać już taki program samodzielnie? Mam nadzieje, że tak! W razie problemów możesz podejrzeć mój kod: 0 pinmode(, OUTPUT); //Dioda jako wyjście pinmode(, INPUT_PULLUP); //Przycisk jako wejście digitalwrite(, LOW); //Wyłączenie diody if (digitalread() == LOW) //Jeśli przycisk wciśnięty digitalwrite(, HIGH); //Włącz diodę delay(0000); //Czekamy 0 sekund digitalwrite(, LOW); //Wyłączamy diodę Przykład Światła drogowe Nasz kolejny układ będzie układem przełączanych świateł drogowych. Naszym głównym celem będzie napisanie programu, który po wciśnięciu przycisku wyświetli kolejną, poprawną sekwencje świateł. Przyjmijmy taki cykl pracy świateł: [ ] -> Zielone -> Pomarańczowe -> Czerwone -> Czerwone + Pomarańczowe[ ] Kiedy naciśniemy przycisk, układ powinien przełączyć światła w ich kolejną sekwencję. Dojdziemy do tego kilkoma etapami. Na początku podłącz diody oraz przełącznik zgodnie z poniższym rysunkiem.
Podłączenie sygnalizacji drogowej. Przygotujmy szkielet programu, na którym będziemy działać. Jego zadanie to tylko konfiguracja wejść i wyjść. 0 pinmode(0, OUTPUT); //Dioda czerwona pinmode(, OUTPUT); //Dioda żółta pinmode(, OUTPUT); //Dioda zielona pinmode(, INPUT_PULLUP); //Przycisk digitalwrite(0, LOW); //Wyłączenie diod digitalwrite(, LOW); digitalwrite(, LOW); //Tutaj będzie nasz program Teraz zapomnijmy o przełączniku i napiszmy program, który będzie zmieniał światła samoczynnie, co sekundę. Powinien on wyglądać następująco: 0 0 0 pinmode(0, OUTPUT); //Dioda czerwona pinmode(, OUTPUT); //Dioda żółta pinmode(, OUTPUT); //Dioda zielona pinmode(, INPUT_PULLUP); //Przycisk digitalwrite(0, LOW); //Wyłączenie diod digitalwrite(, LOW); digitalwrite(, LOW); digitalwrite(0, LOW); //Czerwona digitalwrite(, LOW); //Pomarańczowa digitalwrite(, HIGH); //Zielona delay(000); //Czekamy sekundę digitalwrite(0, LOW); //Czerwona digitalwrite(, HIGH); //Pomarańczowa digitalwrite(, LOW); //Zielona delay(000); //Czekamy sekundę digitalwrite(0, HIGH); //Czerwona digitalwrite(, LOW); //Pomarańczowa digitalwrite(, LOW); //Zielona delay(000); //Czekamy sekundę digitalwrite(0, HIGH); //Czerwona digitalwrite(, HIGH); //Pomarańczowa
digitalwrite(, LOW); //Zielona delay(000); //Czekamy sekundę Wgraj program do i sprawdź czy działa. Musimy mieć pewność, że wszystko jest poprawnie podłączone zanim przejdziemy do dalszej pracy. Pętla While Do tej pory korzystaliśmy tylko z głównej, obowiązkowej pętli w kodzie loop(). Teraz pora na poznanie pętli, którą będziemy mogli używać wewnątrz naszych programów. Różnych pętli będziemy mieli do dyspozycji kilka. Kolejnymi zajmiemy się w dalszych częściach kursu. Teraz omówimy pętlę while(), która działa, do momentu, gdy warunek jest spełniony. Jej praca została przedstawiona w poniższym kodzie: 0 [...] //Kod wykonywany przy każdym obiegu GŁÓWNEJ pętli loop while ( WARUNEK ) /* Kod wykonywany w koło, do momentu, gdy WARUNEK przestanie być spełniany */ //Kod wykonywany przy każdym obiegu GŁÓWNEJ pętli loop Dla jasności, pętle while() wykonuje cały czas tylko ten kod, który mieści się między jej nawiasami klamrowymi (zaznaczony u góry na pomarańczowo). Cała reszta kodu nie jest wtedy wykonywana. Wykorzystajmy złożony w tej chwili układ ze światłami drogowymi i napiszmy program, który będzie migał jedną diodą, tylko gdy mamy wciśnięty przycisk. Prawdopodobnie pomyślałeś tutaj o instrukcji warunkowej if. Jednak jak chciałbyś zrealizować miganie diodą? To wbrew pozorom trudniejsze zadanie od napisanego wcześniej ciągłego świecenia. Program ten najlepiej zrealizować z użycie pętli while(), będzie to wyglądało następująco: 0 0 pinmode(0, OUTPUT); //Dioda czerwona pinmode(, OUTPUT); //Dioda żółta pinmode(, OUTPUT); //Dioda zielona pinmode(, INPUT_PULLUP); //Przycisk digitalwrite(0, LOW); //Wyłączenie diod digitalwrite(, LOW); digitalwrite(, LOW); while (digitalread() == LOW) //Jeśli przycisk jest wciśnięty digitalwrite(0, LOW); //Czerwona wyłącz delay(000); digitalwrite(0, HIGH); //Czerwona włącz delay(000); Jeśli rozumiesz powyższy kod możemy przejść do zrealizowania naszego pierwotnego zadania. Czyli automatycznego przełączania świateł. Tym razem sekwencje mają być wyświetlane do momentu, gdy wciśniemy przycisk (wtedy ma nastąpić zmiana). Zakładamy na razie, że przycisk wciskamy i puszczamy bardzo szybko. Gotowy program powinien wyglądać jak poniżej:
0 0 0 pinmode(0, OUTPUT); //Dioda czerwona pinmode(, OUTPUT); //Dioda żółta pinmode(, OUTPUT); //Dioda zielona pinmode(, INPUT_PULLUP); //Przycisk digitalwrite(0, LOW); //Wyłączenie diod digitalwrite(, LOW); digitalwrite(, LOW); digitalwrite(0, LOW); //Czerwona digitalwrite(, LOW); //Pomarańczowa digitalwrite(, HIGH); //Zielona while (digitalread() == HIGH) //Jeśli przycisk jest wciśnięty digitalwrite(0, LOW); //Czerwona digitalwrite(, HIGH); //Pomarańczowa digitalwrite(, LOW); //Zielona while (digitalread() == HIGH) //Jeśli przycisk jest wciśnięty digitalwrite(0, HIGH); //Czerwona digitalwrite(, LOW); //Pomarańczowa digitalwrite(, LOW); //Zielona while (digitalread() == HIGH) //Jeśli przycisk jest wciśnięty digitalwrite(0, HIGH); //Czerwona digitalwrite(, HIGH); //Pomarańczowa digitalwrite(, LOW); //Zielona while (digitalread() == HIGH) //Jeśli przycisk jest wciśnięty W tym wypadku pętla została wykorzystana w dość dziwny sposób. Otóż jak możecie zobaczyć w nawiasach klamrowych nie znajduje się nic! Dlaczego więc program działa? Dzieje się tak, bo program wykorzystuje pętle do tego, aby się zatrzymać. Jak to działa?. Uruchamiamy świecenie diodami zgodnie z pewną sekwencją. Wchodzimy w pętlę while(), które jest tuż poniżej. Pętla jest pusta, więc program cały czas kręci się w koło i nic nie robi. Dopiero po wciśnięciu przycisku (niespełnienie warunku) program wychodzi z pętli. Zapalana jest kolejne sekwencja i sytuacja się powtarza. Sprawdźmy działanie programu w praktyce! Co się dzieje? Czy wszystko działa tak jak powinno? Otóż nie! Pomimo, że przycisk wciskamy nawet na bardzo krótko, to czasami program działa poprawnie, a czasami przeskakuje o kilka pozycji. Dlaczego tak się stało?jak powinieneś pamiętać z pierwszej części, mówiąc w uproszczeniu, procesor wykonuje około milionów operacji na sekundę. W związku z tym, podczas wciśnięcia przycisku zdąży obiec wszystkie stany naszej sygnalizacji (i to nie jeden raz ). Różne efekty po zwolnieniu przycisku, to tylko efekt losowego wstrzelenia się w daną sekwencję. Jak rozwiązać ten problem? Bardzo prosto. Wystarczy przerobić program w taki sposób, aby zmiana świateł nie następowała częściej niż np.: co sekundę. Możemy wykorzystać do tego znaną już funkcję opóźniającą delay(). pinmode(0, OUTPUT); //Dioda czerwona pinmode(, OUTPUT); //Dioda żółta pinmode(, OUTPUT); //Dioda zielona
0 0 0 0 pinmode(, INPUT_PULLUP); //Przycisk digitalwrite(0, LOW); //Wyłączenie diod digitalwrite(, LOW); digitalwrite(, LOW); digitalwrite(0, LOW); //Czerwona digitalwrite(, LOW); //Pomarańczowa digitalwrite(, HIGH); //Zielona delay(000); //Zatrzymujemy program przed wejsciem do pętli na sekunde while (digitalread() == HIGH) //Jeśli przycisk jest wciśnięty digitalwrite(0, LOW); //Czerwona digitalwrite(, HIGH); //Pomarańczowa digitalwrite(, LOW); //Zielona delay(000); //Zatrzymujemy program przed wejsciem do pętli na sekunde while (digitalread() == HIGH) //Jeśli przycisk jest wciśnięty digitalwrite(0, HIGH); //Czerwona digitalwrite(, LOW); //Pomarańczowa digitalwrite(, LOW); //Zielona delay(000); //Zatrzymujemy program przed wejsciem do pętli na sekunde while (digitalread() == HIGH) //Jeśli przycisk jest wciśnięty digitalwrite(0, HIGH); //Czerwona digitalwrite(, HIGH); //Pomarańczowa digitalwrite(, LOW); //Zielona delay(000); //Zatrzymujemy program przed wejsciem do pętli na sekunde while (digitalread() == HIGH) //Jeśli przycisk jest wciśnięty Teraz wszystko musi już działać poprawnie! Warto wspomnieć, że warunki w pętli while() mogą być łączone oraz znacznie bardziej rozbudowane, wrócimy jednak do tego tematu, gdy poznamy zmienne. Pamiętaj, że komplet elementów niezbędnych do przeprowadzenia wszystkich ćwiczeń jest dostępny w Botlandzie. Zakup zestawów wspiera kolejne publikacje na Forbocie! Podsumowanie Po sprawdzeniu i zrozumieniu programów z tej części nie powinniście mieć problemów z najważniejszymi peryferiami mikrokontrolerów portami I/O. Mam nadzieje, że zauważyłeś równie, że często warto rozbić program na kilka etapów zamiast od razu pisać pełną funkcjonalność. Pytajcie w komentarzach jeśli coś jest niejasne. W kolejnej części zajmiemy się komunikacją z komputerem przez port USB. Dzięki temu ułatwione będzie testowanie późniejszych, rozbudowanych programów. 0