W tym artykule pokażemy, jak napisać swój pierwszy, klasyczny program obsługujący diody LED oraz przyciski tact-switch.
Co potrzebujemy aby zacząć zabawę:
- zestaw uruchomieniowy produkcji Gotronik: Moduł uruchomieniowy AVR ATMEGA-16 wersja 2
- przewody połączeniowe
- środowisko programistyczne Eclipse z pluginem AVR.
- programator USBasp z zainstalowanym sterownikiem
Jeśli wszystkie powyższe warunki zostały spełnione możemy przejść do tworzenia kodu źródłowego. W tym celu uruchamiamy środowisko Eclipse i tworzymy nowy projekt oraz plik źródłowy.
Oczywiście, musimy jeszcze podłączyć programator do płytki za pomocą przewodu ISP, wybrać go w ustawieniach projektu, oraz podłączyć odpowedni pin danego portu do diody. W naszym przypadku wybrano pin 7 portu C i diodę nr 7.
Nasz program, mrugający diodą LED, musi najpierw zapalić diodę na odpowiednim pinie, odczekać określony czas, a następnie zgasić diodę. Kod programu przedstawia się następująco:
/* * migajaca_dioda.c * * Created on: 20 lip 2015 * Author: Gotronik_1 */ #include <avr/io.h> #include <util/delay.h> int main(void){ DDRC |= (1<<PC7); //włączenie pinu PC7 jako wyjście while(1){ PORTC &= ~(1<<PC7); _delay_ms(1000); PORTC |= (1<<PC7); _delay_ms(1000); }
Jeśli wszystkie kroki przeszliśmy pomyślnie, naszym oczom powinna ukazać się mrugająca dioda nr 7.
Warto przeanalizować kod źródłowy krok po kroku.
Lekka modyfikacja linii odpowiedzialnych za uruchomienie portu, i wystawianie na nim stanu wysokiego, pozwala na uruchomienie np. wszystkich pinów na raz:
/* * migajaca_dioda.c * * Created on: 20 lip 2015 * Author: Gotronik_1 */ #include <avr/io.h> #include <util/delay.h> int main(void){ DDRC = 0xff; while(1){ PORTC = ~255; _delay_ms(1000); PORTC = ~0; _delay_ms(1000); } }
Ciekawym pomysłem jest również stworzenie szlaczka, odbijającego się od skrajnych diód. W tym celu musimy zapoznać się z tym, jak wysterowywane są piny w procesorze Atmega. Podłączmy 8 diód LED, tak aby ich numery na płytce, odpowiadały numerom pinów portu C. Pinom w porcie C odpowiadają wagi, tak, jak w ciągu zerojedynkowym. Tabela wag przedstawia się następująco:
PC7 | PC6 | PC5 | PC4 | PC3 | PC2 | PC1 | PC0 |
128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
Załóżmy że chcemy zapalić diody podpięte do pinów PC2 i PC3. W tym celu wystarczy zsumować ich wagi, i wystawić stan wysoki odpowiednim poleceniem.
Kod naszego szlaczka przedstawia się następująco:
/* * LED.c * * Created on: 20 lip 2015 * Author: Gotronik_1 */ #include <avr/io.h> #include <util/delay.h> int main (void){ DDRC = 0xff; uint8_t i, diody[]={3, 6, 12, 24, 48, 96, 192, 96, 48, 24, 12, 6} ; while (1) { for(i=0; i<12; i++){ _delay_ms(500); PORTC = ~diody[i]; } } }
Filmik przedstawiający działanie:
Jak widać, utworzyliśmy sobie tablicę z wartościami wag dla odpowiednich diód. Następnie za pomocą pętli for wywoływaliśmy kolejno elementy tablicy, co skutkowało zapalaniem się diód. Zmieniając wartość opóźnienia możemy regulować szybkość przebiegania szlaczka.
Obsługa przycisków tact-switch
Pójdźmy dalej z rozbudową naszego układu, i dodajmy obsługę przycisku tact-switch. W tym celu podłączmy przycisk pod port B ( w naszym przypadku podłączono przycisk 7 pod port PB7).
Do kodu wystarczy dodać linię, ustawiającą stan wysoki na wejściach portu B, są to tak zwane rezystory podciągające pull-up. Ma to zapobiec hazardowi logicznemu, czyli pojawianiu się stanów nieustalonych na porcie mikrokontrolera. Następnie, musimy w jakiś sposób obsłużyć wciśnięcie przycisku. W tym przypadku, można posłużyć się instrukcją warunkową if, w której przewidzimy zarówno przypadek wciśniętego, jak i nie wciśniętego przycisku.
Nasz kod przedstawia się następująco:
/* * przycisk.c * * Created on: 21 lip 2015 * Author: Gotronik_1 */ #include <avr/io.h> int main(void){ DDRC = 0xff; // ustawienie wyjśc sterujących diodami PORTB = 255; //włączenie rezystorów podciągających while(1){ if (!(PINB & 128)) // warunek, jeżeli na porcie B i pin 7 { PORTC = ~128; //jeśli przycisk wciśnięty, zapal diodę nr 7 } else PORTC = 255; //jeśli przycisk nie wciśnięty, zgaś wszystkie diody } }
Jeśli wszystko przepisaliśmy poprawnie, po wciśnięciu przycisku nr 7, powinna zapalić się dioda nr 7.
A co w sytuacji, gdy chcemy obsłużyć więcej diód i więcej przycisków? Są dwa rozwiązania. Jednym z nich jest dopisanie dodatkowych warunków dla każdego przycisku. Drugim rozwiązaniem może być użycie instrukcji switch-case. Ja jednak, skorzystałem z pierwszej opcji.
Stosując ciąg instrukcji if..else jak można zobaczyć poniżej, tworzy się nam ładny tasiemiec. Ale przynajmniej jest skuteczny, bo wszystko działa prawidłowo. Oto kod źródłowy:
/* * przyciski.c * * Created on: 21 lip 2015 * Author: Gotronik_1 */ #include <avr/io.h> int main(void){ DDRC = 0xff; // ustawienie wyjśc sterujących diodami PORTB = 255; //włączenie rezystorów podciągających while(1){ if (!(PINB & 128)) PORTC = ~128; if(!(PINB & 64)) PORTC = ~64; if (!(PINB & 32)) PORTC = ~32; if (!(PINB & 16)) PORTC = ~16; if (!(PINB & 8)) PORTC = ~8; if (!(PINB & 4)) PORTC = ~4; if (!(PINB & 2)) PORTC = ~2; if (!(PINB & 1)) PORTC = ~1; else PORTC = 255; //jeśli przycisk wciśnięty, zapal diodę nr 7 } }
W tym artykule to już wszystko. Dzięki za uwagę 🙂
Dodaj komentarz
Musisz się zalogować, aby móc dodać komentarz.