FORUM

Podstawy języka C cz.4

Erni86
Posty: 8
https://www.oferia.pl/wykonawca/meble-kuchenne-warszawa/1240988
Rejestracja: 09 sie 2021, 9:10
Kontakt:

Podstawy języka C cz.4

Post autor: Erni86 »

Zaczynamy programować

Do programowania Arduino stosowany jest język C. W poniższym rozdziale przedstawimy podstawy tego języka. Wiadomości, które nabędziesz podczas lektury tego rozdziału, będą przydatne podczas pisania każdego szkicu Arduino. Zrozumienie tych podstawowych wia­domości pozwoli Ci na wykorzystywanie wszystkich możliwości Arduino. Programowanie Wiele osób mówi w więcej niż jednym języku. Im więcej języków się zna, tym łatwiej przy­chodzi nauka kolejnych języków. Dzieje się tak, ponieważ poliglota zauważa reguły wystę­pujące w gramatyce i leksyce poszczególnych języków. Taka sama prawidłowość występuje w przypadku nauki języków programowania. Nauka języka C będzie przebiegać o wiele szyb­ciej, jeżeli znasz już jakiś inny język programowania. Pierwsza dobra wiadomość to fakt, że zakres wyrażeń stosowanych w języku progra­mowania jest o wiele mniejszy od zakresu słownictwa stosowanego w języku mówionym. Ponieważ język programowania jest językiem pisanym, a nie mówionym, możesz zawsze posłużyć się pomocą słownika lub podręcznika. Składnia języka programowania jest ściśle uregulowana. Gdy już opanujesz po dstawowe pojęcia, nauka kolejnych zagadnień związa­nych z danym językiem programowania przebiega bardzo sprawnie. Program (w przypadku Arduino zwany szkicem) można interpretować jako listę pole­ceń wykonywanych w kolejności, w jakiej zostały zapisane. Załóżmy, że napisałeś poniższy kod programu: digita1Wri te(l3, HIGH); delay (SOO); digita1Wri te(l3, LOW) ; Każda z tych trzech linii kodu służy do wykonania jakiejś czynności. Pierwsza linia ko­du ustawia wysoki (z ang. high) poziom napięcia na złączu wyjściowym o numerze 13. Jest to złącze, z którym połączona jest dioda LED znajdująca się na płytce Arduino. A więc dioda ta zostanie zapalona. Druga linia kodu informuje o tym, że Arduino zaczeka 500 milise­kund (pół sekundy) i wykona polecenie zawarte w trzeciej linii kodu, czyli wyłączy diodę. Zaprezentowane trzy linijki kodu sprawią, że dioda zostanie jednokrotnie zapalona, a na­stępnie zgaszona. Na po czątku może Cię przerażać zarówno zastosowana interpunkcja, jak również i wy­razy, które nie są rozdzielane spacjami. Wielu początkujących programistów wie, co chce zrobić, ale nie wie, jak ma to zapisać. Nie ma tu niczego strasznego. Wszystko zostanie wy­jaśnione. Na początek zajmijmy się interpunkcją i sposobem tworzenia wyrażeń. Obie te rzeczy są elementami składni języka programowania. Większość języków wymaga dokładnego stosowania się do reguł składniowych. Jedna z zasad tworzenia nazw mówi, że nazwy muszą być jednowyrazowe. A więc nie mogą zawierać znaku rozdzielającego - spacji. Wyrażenie digital Write jest nazwą. Jest to nazwa wbudowanej funkcji, która dokonuje konfiguracji złączy wyjściowych na płytce Arduino. Więcej informacji na temat funkcji zostanie przed­stawionych w kolejnych rozdziałach. Przy zapisie nazw należy uważać nie tylko na znaki rozdzielające. W zapisie nazw rozróżniane są wielkie i małe litery. Funkcja digital Write musi posiadać dane dotyczące tego, obsługą którego złącza ma się zająć. Funkcja powinna również posiadać informację dotyczącą napięcia, jakie ma się pojawić na złączu - wysokie (z ang. high) czy niskie (z ang. low). Te dwie informację noszą nazwę argumentów, które są przekazywane do funkcji podczas jej wywołania. Parametry funkcji muszą być umieszczone w nawiasach i oddzielone przecinkami. Istnieje konwencja zapisu mówiąca o tym, że nawias należy otwierać bezpośrednio za ostatnią literą nazwy funkcji, a pomiędzy przecinkiem i kolejnym parametrem powinna być umieszczona spacja. Jeżeli jednakże czujesz taką potrzebę, możesz zastosować więcej spacji wewnątrz nawiasów.

Jeżeli funkcja posiada tylko jeden argument, nie ma potrzeby umieszczania przecinku w naw1as1e. Zauważ, że każda linia kodu jest zakończona średnikiem. Bardziej logiczne byłoby zakonczenie każdej linii kodu kropką. Średnik sygnalizuje koniec danego polecenia, tak jak kropka sygnalizuje koniec zdania. W kolejnym podroz dziale dowiesz się, co dzieje się, gdy w zintegrowanym środowisku programistycznym Arduino klikniesz ikonę Załaduj . Pozwoli Ci to na pracę z przy kładowymi szkicami. Czym jest język programowania? To dziwne, że w książce dotyczącej programowania dopiero w trzecim rozdziale piszemy o tym, czym jest język programowania. Potrafisz rozpoznać szkic Arduino, a także masz już niewielkie pojęcie o tym, jakie operacje są w nim zdefiniowane. Musisz jednak mieć większą świadomość tego, jak kod zapisany w języku programowania jest tłumaczony z zapisanych wyrażeń na realnie wykonywaną czynność, taką jak włączenie i wyłączenie diody LED.

Blink po raz kolejny
W Arduino stosujemy funkcje setup oraz loop w celu oddzielenia od siebie rzeczy, które muszą być wykonane raz w wyniku uruchomienia programu, od rzeczy, które będą wyko­nywane w sposób ciągły. Funkcja setup jest uruchamiana jednokrotnie po uruchomieniu szkicu. Dodajmy do naszej funkcji kod, który sprawi, że dioda wbudowana w Arduino zostanie zapalona. Zmo­dyfikuj napisany wcześniej kod w sposób pokazany poniżej, a następnie załaduj gotowy szkic na płytkę.

Kod: Zaznacz cały

void setup() {
    pinMode(13, OUTPUT) ; 
    digitalWrite(13, HIGH); 
}
void  loop() {
 } 
Funkcja setup wywoła dwie wbudowane funkcje -pinMode i digitalWrite. Funkcja digital Write została omówiona wcześniej. Funkcja pinMode określa to, czy dane złącze (pin) ma działać jako wejście, czy ma odgrywać rolę wyjścia. A więc włączanie diody LED jest tak naprawdę procesem składającym się z dwóch etapów. Najpierw musimy określić to, że złącze o numerze 13 ma działać jako wyjście, a następnie musimy ustawić sygnał wyjściowy na wysoki
( 5 V).

Po uruchomieniu tego szkicu zobaczysz, że dioda zostaje zapalona i nie gaśnie. Efekt ten nie jest zachwycający, a więc spróbujmy sprawić, naprzemiennie włączając i wyłączając diodę, że będzie ona migać. Instrukcje włączającą i wyłączającą diodę umieścimy raczej w funkcji l oop niż w funkcji setup. Pozostawmy wywołanie funkcji pi nMode wewnątrz funkcji setup, ponieważ funkcja pi nMode musi zostać wywołana tylko jednokrotnie. Szkic nadal działałby, gdybyś przeniósł wywołanie funkcji pi nMode do funkcji loop, ale nie ma takiej potrzeby. Dobrą praktyką programistyczną jest robienie tylko raz rzeczy, które muszą być wykonane jednokrotnie. Zmodyfikuj swój szkic, aby wyglądał w następujący sposób:

Kod: Zaznacz cały

void setup() {
 pinMode(13, OUTPUT);
 } 
void loop() {
 digitalWrite(13, HIGH);
 delay (500); 
digitalWrite(l3, LOW) ; 
}
Uruchom ten szkic i zobacz, co się stanie. Efekt działania szkicu może odbiegać od oczekiwań. Dioda LED świeci światłem ciągłym. Dlaczego tak się dzieje? Przeanalizujmy kod krok po kroku:
1. Uruchom funkcję setup i zainicjuj złącze o numerze 13 tak, aby działało jako wyjście.
2. Uruchom funkcję loop i włącz wysoki sygnał na złączu o numerze 13 (włącz diodę LED).
3. Odczekaj pół sekundy.
4. Podaj niski sygnał na złącze o numerze 13 (wyłącz diodę LED).
5. Uruchom ponownie funkcję l oop -przejdź z powrotem do punktu drugiego i
ponownie włącz wysoki sygnał na złączu o numerze 13 (włącz diodę LED).

Problem znajduje się pomiędzy punktem czwartym i piątym. Dioda jest wyłączana, ale jest natychmiast włączana ponownie. Dzieje się to tak szybko, że wydaje się, że dioda LED jest cały czas włączona. Mikrokontroler znajdujący się na płytce Arduino jest w stanie przetwarzać 16 milionów instrukcji na sekundę. Nie jest to wykonywanie 16 milionów poleceń napisanych w języku C, lecz pomimo tego jest to bardzo duża wartość. Dioda będzie wyłączona tylko przez niewielki ułamek sekundy. Aby rozwiązać ten problem, należy dodać kolejną funkcję opóźniającą del ay po wyłą­czeniu diody LED. Twój kod powinien wyglądać w następujący sposób:

Kod: Zaznacz cały

void setup ( ) { 
pinMode ( 13 , OUTPUT ) ; 
}
void loop ( ) { 
digitalWrite ( 13 , HIGH ) ; 
delay (500) ; 
digitalWrite ( 13 , LOW) ; 
delay (500) ; 
}
Zmienne
W przytoczonym wcześniej szkicu korzystaliśmy ze złącza o numerze 13. Odwoływaliśmy
się do niego trzykrotnie. Jeżeli zdecydowałbyś się na korzystanie z innego złącza, musiałbyś
zmodyfikować kod programu w trzech miejscach. Podobnie jeżeli chciałbyś zmienić czę­
stotliwość błysków, musiałbyś zmienić wartość argumentu funkcji del ay w więcej niż jed­
nym miejscu.
Zmienne mogą być traktowane jako wartości, którym nadano nazwy. Mają one o wiele
szersze zastosowanie, jednakże na razie skupimy się jedynie na tym.
Definiuj ąc zmienną w języku C, musisz określić jej typ. Chcemy, aby nasze zmienne
były liczbami całkowitymi - w języku C zmienne takie noszą nazwę i nt (od angielskiego
słowa integer). Poniżej przedstawiono deklarację zmiennej o nazwie ledPin. Przypisano jej
wartość 13:
int ledPin 13 ;
Wyrażenie ledPin jest nazwą zmiennej. D o nazw zmiennych stosuje się te same reguły
co do nazw funkcji. A więc nazwy nie mogą zawierać żadnych spacji. Istnieje konwencja
dotycząca nazewnictwa zmiennych mówiąca o tym, że nazwy zmiennych zaczyna się z małej
litery, a każde kolejne słowo rozpoczyna się wielką literą. Programiści określają ten sposób
notacji terminem „camelCase".
Zmodyfikujmy nasz szkic w następujący sposób:

Kod: Zaznacz cały

int ledPin = 13; 
intdelayPeriod = 500 ; 

void setup ( ) 
{ 
pinMode ( ledPin , OUTPUT ) ; 
}
void loop ( ) 
{ 
} 
W zaprezentowanym szkicu zastosowano również kolejną zmienną - delayPeriod.
Wszędzie tam, gdzie w poprzednim szkicu stosowaliśmy wartość 13, teraz stosujemy
zmienną ledPin, a wszędzie tam, gdzie stosowaliśmy wartość 500, teraz stosujemy zmienną
delayPeriod.
Jeżeli chcesz, aby dioda błyskała z większą częstotliwością, wystarczy zmienić w jednym
miejscu wartość zmiennej delayPeriod. Spróbuj zmienić wartość tej zmiennej na 100 i uru­
chomić szkic na płytce Arduino.
Są inne rzeczy, do których możemy sprytnie zastosować funkcje. Zmodyfikujmy szkic
tak, aby na początku miganie przebiegało z bardzo dużą częstotliwością, a następnie częstotli­
wość błysków malała - tak jakby Arduino „męczyło się". Aby wykonać szkic dający taki
efekt, musimy po każdym błysku dodawać jakąś wartość do zmiennej del ayPeri od.
Zmodyfikuj szkic, dodając linię kodu na końcu funkcji l oop tak, jak to zrobiono w po­
niższym kodzie. Uruchom szkic na płytce Arduino. W ciśnij przycisk Reset i obserwuj efekt
działania szkicu.

Kod: Zaznacz cały

int ledPin = 1 3 ; 
int delayPeriod 100 ; 

void setup ( ) 
{ 
pinMode ( ledPin , OUTPUT ) ; 
}
void loop ( ) 
{
digital Write ( led Pin , H I G H ) ; 
delay (delayPeriod ) ; 
digital Write ( led Pin , LOW) ; 
delay (delayPeriod ) ; 
delayPeriod = delayPeriod + 100; 
}
W zaprezentowanym przykładzie Arduino wykonuje operacje arytmetyczne. Przy każ­
dym wywołaniu funkcji l oop Arduino mignie diodą LED oraz równocześnie doda 100 do
zmiennej del ayPeri od. Niedługo wrócimy do zagadnień związanych z operacjami aryt­
metycznymi, ale najpierw poznajmy inne funkcje Arduino.

Eksperymentowanie w języku C
Musisz w jakiś sposób testować pisany przez siebie kod. Jednym ze sposobów na to jest umieszczenie kodu, który chcesz sprawdzić, w funkcji setup, sprawdzenie kodu przy uży­ciu Arduino, a następnie wyświetlenie wyniku przez Arduino za pomocą tak zwanego mo­nitora portu szeregowego, co pokazano na rysunku
Rysunek7.png
Rysunek7.png (114.53 KiB) Przejrzano 2248 razy
Pisanie kodu języka C w fu nkcji setup
Rysunek8.png
Rysunek8.png (39.03 KiB) Przejrzano 2248 razy
Monitor portu szeregowego

Monitor portu szeregowego jest częścią środowiska programistycznego Arduino. Do­stęp do niego możesz uzyskać, klikając ikonę znajdującą się po prawej stronie paska narzę­dzi. Monitor działa jako kanał komunikacyjny pomiędzy Twoim komputerem i Arduino.
Możesz wpisać komunikat w górnej części okna monitora portu szeregowego, a kiedy klik­niesz ikonę Send lub wciśniesz klawisz Enter, wpisany kod zostanie wysłany do Arduino. Jeżeli Arduino ma coś do zakomunikowania, to zostanie to wyświetlone w oknie monitora portu szeregowego. Dane są przesyłane w obu kierunkach za pośrednictwem interfejsu USB. Jak zapewne się spodziewałeś, istnieje wbudowana funkcja pozwalająca na wysyłanie wiadomości do monitora portu szeregowego. Funkcja ta nosi nazwę Seri al . print l n. Jest to funkcja jednoargumentowa. Argumentem tym jest treść, którą chcemy przesłać. Treść ta jest zwykle pewną zmienną. Będziesz korzystać z tego mechanizmu do sprawdzania rzeczy związanych ze zmien­nymi oraz arytmetyką w języku C. Tak naprawdę jest to jedyny sposób na wizualizowanie rezultatów Twoich eksperymentów w języku C.
PODST A WY JĘZYKA C 45 Możesz wpisać komunikat w górnej części okna monitora portu szeregowego, a kiedy klik­niesz ikonę Send lub wciśniesz klawisz Enter, wpisany kod zostanie wysłany do Arduino. Jeżeli Arduino ma coś do zakomunikowania, to zostanie to wyświetlone w oknie monitora portu szeregowego. Dane są przesyłane w obu kierunkach za pośrednictwem interfejsu USB. Jak zapewne się spodziewałeś, istnieje wbudowana funkcja pozwalająca na wysyłanie wiadomości do monitora portu szeregowego. Funkcja ta nosi nazwę Seri al . print l n. Jest to funkcja jednoargumentowa. Argumentem tym jest treść, którą chcemy przesłać. Treść ta jest zwykle pewną zmienną. Będziesz korzystać z tego mechanizmu do sprawdzania rzeczy związanych ze zmien­nymi oraz arytmetyką w języku C. Tak naprawdę jest to jedyny sposób na wizualizowanie rezultatów Twoich eksperymentów w języku C. Zmienne numeryczne i arytmetyka Ostatnią rzeczą, jaką zrobiłeś, modyfikując szkic sterujący mi gającą diodą, było stopniowe zwiększanie czasu trwania błysku przy użyciu następującego kodu:
delayPeriod = delayPeriod + 100;
Przyjrzyjmy się temu kodowi. Składa się on z nazwy zmiennej, znaku równości, a na­stępnie wyrażenia delayPeri od + 100. Znak równości wykonuje działanie zwane przypi­saniem, czyli przypisuje nową wartość do zmiennej. Nowa wartość zmiennej jest określana przez to, co znajduje się pomiędzy znakiem równości a średnikiem. W omawianym przypadku nowa wartość zmiennej delayPeriod jest poprzednią wartością zmiennej delayPeriod zwiększoną o 100. Sprawdźmy działanie omówionego wcześniej mechanizmu poprzez uruchomienie po­niższego szkicu i otwarcie monitora portu szeregowego.

Kod: Zaznacz cały

void setup() {
Serial.begin(9600);
int a  = 2; 
int b  = 2; 
int c  =  a  + b; 
Serial.println (c);
} 
voidloop() {
}
Na rysunku ponizej pokazano to, co powinien wyświetlić monitor portu szeregowego po wykonaniu powyższego programu.
Rysunek9.png
Rysunek9.png (36.56 KiB) Przejrzano 2248 razy
A teraz przyjrzyjmy się bardziej złożonemu przykładowi. Aby przekształcić wartość temperatury wyrażoną w skali Celsjusza na temperaturę wyrażoną w skali Fahrenheita, należy pomnożyć podaną wartość przez 5, podzielić ją przez 9, a następnie dodać do wyni­ku 32. Działanie to przedstawia poniższy szkic:

Kod: Zaznacz cały

void setup ( ) 
{ 
Serial.beg i n (9600) ; 
intdegC = 20 ; 
intdeg F ; 
degF = degC * 9 / 5 + 32 ; 
Serial.println(degF) ; 
}
Podany szkic zawiera kilka elementów, na które powinieneś zwrócić uwagę. Zacznijmy od poniższej linii kodu:

int degC = 20 ;

Pisząc tę linię kodu, przeprowadziliśmy tak naprawdę dwie operacje. Deklarujemy zmienną typu int o nazwie degC, a jednocześnie określamy wartość początkową tej zmiennej -20. Możesz również wykonać te dwie operacje, korzystając z dwóch oddzielnych linii kodu:

int degC; degC = 20;

Zmienną musisz deklarować tylko raz. Deklarując zmienną, informujesz kompilator o jej typie -w tym przypadku zmienna była typu int. Zadeklarowanej zmiennej możesz wielo­krotnie przypisywać nowe wartości:

int degC;
degC = 20;
degC = 30;

W przykładzie dotyczącym zamiany jednostki temperatur definiujesz zmienną degC i na­dajesz jej początkową wartość -20. Natomiast definiuj ąc zmienną degF, nie nadajesz jej żad­nej wartości początkowej. W kolejnej linii kodu zmiennej tej przypisywana jest wartość zgodnie z przeprowadzonymi obliczeniami. Dopiero po ich wykonaniu wynik jest przesy­łany do monitora portu szeregowego.
Gdy przyjrzysz się obliczeniom, zauważysz, że znak gwiazdki(*) jest stosowany do ope­racji mnożenia, a znak kreski ukośnej (/) jest stosowany do operacji dzielenia. Operacje matematyczne określane przez operatory (+, -, *i/) są wykonywane w ustalonej kolejno­ści. N aj pierw wykonywane są operacje mnożenia, następnie dzielenia, a dopiero później dodawania i odejmowania. Jest to kolejność, w jakiej z reguły przeprowadza się operacje arytmetyczne. Czasem, w przypadku wyrażeń arytmetycznych, warto zastosować nawiasy. W tym celu możesz zastosować następujący zapis:

degF = ((degC * 9) / 5) + 32;

Wyrażenia tego typu mogą być dowolnie długie i dowolnie złożone. Ponadto poza pod­stawowymi operacjami matematycznymi możliwe jest stosowanie olbrzymiej liczby do­stępnych funkcji matematycznych. Funkcje te omówimy jednak później.

Wróć do „Kurs Arduino”