Cwiczenie nr 1 Pierwszy program w języku C na mikrokontroler AVR Zadanie polega na napisaniu pierwszego programu w języku C, jego poprawnej kompilacji i wgraniu na mikrokontroler. W tym celu należy zapoznać się z częścią teoretyczną będącą wstępem do zadania znajdującego się w części drugiej. Część 1. Wiadomości teoretyczne Uruchom środowisko Eclipse i utwórz nowy projekt stosując się do instrukcji poniżej Po uruchomieniu Eclipse lub w trakcie jego uruchamiania ustaw poprawnie folder works pace na ten który należy do Ciebie. Następnie utwórz nowy projekt wg wskazówek: W oknie Project Explorer kliknij prawym klawiszem myszy i wybierz NEW -> c Project W Project name wpisz nazwę projektu i wybierz typ projektu zgodnie z tym co widać na zrzucie poniżej. Nazwa projektu nie może zawierać żadnych znaków specjalnych i spacji
Następnie wybierz konfigurację kompilatora wg zrzutu:
Następnie wybierz typ MCU na którym będziemy pracować i wpisz poprawnie częstotliwość taktowania. Tutaj będzie to ATmega644P i 16000000Mhz Następnie do projektu dodaj nowy plik źródłowy o nazwie main.c klikając kolejno prawym klawiszem myszy na projekcie: New->C source file
Rejestry MCU służące do obsługi portów we/wy Rejestr DDRx 8 bitowy rejestr konfiguracji kierunku pracy. Wpisanie na dany bit logicznej 1 ustawia dany pin na wyjście, 0 na wejście Rejestr PINx - 8 bitowy rejestr odczytu stanu portu. Rejestr PORTx - 8 bitowy rejestr ustawiający stany logiczne na porcie X jedna z liter oznaczająca porty MCU. W zależności od wyposażenia MCU od A do F Przykładowo poniższe ustawienie bitów w rejestrze DDRA: PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0 0 0 0 1 0 0 0 1 Oznacza że piny PA0 i PA4 są wyjściami pozostałe zaś pełnią rolę wejść. ZADANIE 1 Zamień liczby zapisane w kodzie dziesiętnym na odpowiadający im kod binarny. Zastanów się jakie piny portu DDRA po wpisaniu tych liczb będą wejściami a jakie wyjściami? (24)dec ( (253)Dec-( (100)Dec-( )bin )bin )bin Zapis liczb do rejestru W języku C rejestr będziemy traktować tak samo jak zmienną programową więc w zasadzie zapis do niego i odczyt realizuje się za pomocą operatora =. Przykładowo: DDRA = 244;
PORTA = 0x16; Definicja zmiennej programowej Zmienna - jest instrukcją programistyczną posiadającą takie cechy jak: nazwa symboliczna, miejsce przechowywania i wartość. Nazwa odnosi się w całym programie do konkretnego miejsca w pamięci gdzie ta zmienna jest przechowywana. Każda zmienna ma jeszcze swój typ po którym kompilator wie ile miejsca owa zmienna będzie zabierała miejsca w pamięci. O typach zmiennych na następnych zajęciach. Wartość z kolei to liczba przechowywana we wskazanym przez nazwę miejscu. Przykład deklaracji zmiennej w języku C: int liczba = 10; //deklaracja zmiennej typu integer(całkowita) o nazwie l iczba i zapisanie do niej wartości 10 Dyrektywy kompilatora Preprocesor jest jednym z modułów kompilatora. Działa on zwykle w ukryciu, przez co nie każdy zdaje sobie sprawę z jego istnienia. Zanim jeszcze ruszy do pracy kompilator kod programu jest przeglądany przez preprocesor. Preprocesor bada cały kod w poszukiwaniu specjalnych komend. Owe komendy to właśnie dyrektywy. Za ich pomocą można niejako sterować przebiegiem kompilacji. Dyrektywy można umieszczać w dowolnym miejscu programu. Każda dyrektywa rozpoczyna się znaczkiem płotka #. Za koniec dyrektywy uważa się koniec wiersza. Zatem nie trzeba już stosować średnika kończącego. Poniżej przedstawione zostały jedynie wybrane dyrektywy. #define - Ta dyrektywa służy do definiowania makrodefinicji. Makrodefinicje stosuje się w celu uproszczenia i skrócenia zapisu. Zamiast za każdym razem pisać długie i skomplikowane wyrażenia można to zrobić jednokrotnie. Wystarczy wówczas owe wyrażenie zapisać, jako makrodefinicje i wywoływać w stosownym momencie. Przypuśćmy, że masz pewien fragment kodu, który stosujesz wielokrotnie w programie. Zajmuje on jedną linijkę, ale jest dość skomplikowany. Wielokrotne wklepywanie lub kopiowanie tego samego tekstu jest trochę męczące. Aby sobie uprzyjemnić życie można zapisać powtarzający się kod, jako
makrodefinicję. Makrodefinicja raz zdefiniowane nie może zostać użyta ponownie. #undef odwołanie makrodefinicji w celu zwolnienia jej nazwy (choćby nawet po to by za chwilę zdefiniować nowe makro pod tą samą nazwą) #if, #elif, #else i #endif - Wszystkie te dyrektywy służą do kompilacji warunkowej. Załóżmy, że piszesz bardzo uniwersalny program, działający na kilku różnych platformach. W zależności od sprzętu poszczególne moduły programu będą nieco inne. Chcesz teraz sprawdzić działanie programu. Wprowadzasz więc pomocniczą zmienną, której wartość będzie zależna od systemu, na którym kompilujesz program. Za pomocą dyrektyw kompilacji warunkowej możesz określić, która część kodu zostanie skompilowana. #include - Dyrektywa include jest stosowana chyba najczęściej. Krótko mówiąc jej działanie skupia się na dołączeniu do kompilowanego pliku zawartości innego pliku. Jest przydatna w sytuacjach, kiedy chcemy skorzystać z funkcji bibliotecznych. Funkcje biblioteczne to najzwyklejsze funkcje dostarczone przez producenta kompilatora. Są one skompilowane i gotowe do pracy. Aby z nich skorzystać należy dołączyć do programu określony plik nagłówkowy zawierający deklaracje interesujących nas funkcji. Wstępnie o funkcjach w języku C Każdy fragment programu w języku C jest zorganizowany w tzw funkcje. Dotyczy to także tego fragmentu który piszesz aby MCU wykonywał zlecone zadanie. Funkcja główna programu w języku C nazywa się main a jej definicja i użycie w programie wygląda jak niżej: /* * main.c * * Created on: 04-10-2015 * Author: xemax */ #include <avr/io.h> #include <util/delay.h> int main(void) { } //tutaj piszemy kod naszego programu Komentarz blokowy Dołączenie plików nagłówkowych Definicja funkcji main i kod programu
Część 2 praktyczna ZADANIE 2 (realizacja wspólna) Napisać program który pozwoli na sterowanie diodami LED podłączonymi do portu PA wg instruktażu do zadania. Pamiętaj o poprawnej inicjalizacji rejestrów ZADANIE 3 Zmodyfikuj napisany program tak aby diody LED mrugały niezależnie w dowolnej wymyślonej przez Ciebie kolejności.