Zabawę w tworzenie programów dla mikrokontrolerów AVR w oparciu o język programowania Pascal należy oczywiście zacząć od zainstalowania właściwego oprogramowania. Można je bezpłatnie pobrać ze strony producenta: http://www.mikroe.com. Instalacja nie wymaga żadnych dziwnych czynności, toteż każdy może sobie zainstalować pakiet bez problemów.
Mikropascal AVR pierwszy projekt
Do uruchomienia programu do tworzenia aplikacji na mikrokontrolery AVR należy z menu Start wybrać: Mikroelektronika → mikroPascal PRO for AVR → mikroPascal PRO for AVR. Spowoduje to uruchomienie środowiska IDE do tworzenia oprogramowania dla mikrokontrolerów AVR. Po uruchomieniu można poprzez dostępny przycisk do tworzenia nowego projektu, wybór w programie opcji: Project → New Prokect lub zastosowaniu skrótu klawiszowego Shift+Ctrl+N przejść do utworzenia nowego projektu. Tworzenie projektu zaczyna się od następującej planszy: na której należy kliknąć na „Next >” w celu sprecyzowania szczegółów. W polu Project Name należy wpisać nazwę tworzonego projektu (przykładowo prog0), w polu Project folder wpisać lokalizację na wszystkie pliki projektowe (nazwę kartoteki wraz ze ścieżką dostępu). Można posiłkować się przyciskiem Browse w celu wskazania kartoteki. W dalszej kolejności należy określić docelowy mikrokontroler, na jaki tworzone jest oprogramowanie. Realizowane jest to poprzez kliknięcie „na trójkącik w celu wysunięcia całej szuflady”. Z dostępnych pozycji należy wybrać symbol docelowego mikrokontrolera. Kolejny szczegół dotyczy częstotliwości sygnału taktującego (w typowym zastosowaniu: częstotliwości rezonatora kwarcowego przyłączonego do odpowiednich wyprowadzeń mikrokontrolera). W większości przypadków stosowany jest rezonator o częstotliwości 7.3728MHz (ta częstotliwość pozwala uzyskać każdą znormalizowaną prędkość transmisji szeregowej, gdzie UART jest taktowany systemowym sygnałem zegarowym). Po określeniu wszystkich danych należy kliknąć na przycisk „Next >”. Powoduje to przejście do kolejnej planszy, gdzie istnieje możliwość dołączenia do projektu już istniejących składników. Przy tworzeniu pierwszego projektu, takich składników nie ma. Kliknięcie na przycisk „Next >” pozwala przejść do dalszego etapu tworzenia projektu. Ewentualne „zapomnienie” dodania elementu do projektu nie jest problemem i zawsze możliwa jest korekta zawartości projektu. Kolejna faza uszczegułowiania informacji dotyczy przyłączanych bibliotek. Do kolejnego etapu następuje przejście po kliknięciu na przycisk „Next >”. Zakończenie tworzenia projektu następuje po kliknięciu na przycisk „Finish”. Końcowym rezultatem jest utworzenie pliku opisującego projekt (w tym konkretnym przypadku jest to prog0.mppav) oraz startowej postaci pliku zawierającego instrukcje programu (w tym konkretnym przypadku jest to prog0.mpas). Teraz pozostało wypełnić właściwą treścią zaproponowany szablon. Biorąc pod uwagę środowisko pracy mikrokontrolera (pokazane na poniższej ilustracji), gdzie do mikrokontrolera przyłączonych jest osiem LED'ów, przykładowy program jest następujący (należy zauważyć, że włączenie diody LED do świecenia następuje przy wysterowaniu odpowiedniego wyjścia portu B do stanu logicznego zera):
Kod: Zaznacz cały
program prog0 ;
var
PortData : byte ;
begin
DDRB := 0xFF ;
PORTB := 0 ;
PortData := 0 ;
repeat
PORTB := PortData XOR 0xFF ;
inc ( PortData ) ;
Delay_ms ( 1000 ) ;
until false ;
end.
Kompilacja i generowanie wersji binarnej następuje po kliknięciu na odpowiedni przycisk, wybranie właściwego polecenia z menu: Build → Build lub poprzez użycie skrótu klawiszowego Ctrl + F9 (wszystkie metody są równorzędne). W tak prostym programie nie ma nawet gdzie się pomylić, toteż jego kompilacja przebiegła bez problemów. Informują o tym komunikaty w oknie Messages. W przypadku gdyby były błędy kompilacji, odpowiednie komunikaty również są wyświetlane w tym oknie, przykładowo: Do modyfikacji szczegółów dotyczących projektu należy kliknąć na zakładkę „Project Settings” z lewej strony ekranu. Kliknięcie na tą zakładkę powoduje wysunięcie okienek, gdzie możliwa jest modyfikacja typu mikrokontrolera oraz częstotliwości sygnału taktującego. Z drugiej strony ekranu znajdują się zakładki pozwalające na modyfikacje składników projektu. Kliknięcie na zakładkę „Project Manager” powoduje wysunięcie odpowiedniego okienka, gdzie dostępne są przyciski pozwalające dodać lub usunąć odpowiedni składnik. Przydatną funkcjonalnością jest możliwość przeglądania w asemblerze wyniku kompilacji. Przycisk „Deasemblacji modułu” pokazuje wygenerowany kod w języku asembler bieżącego modułu, z kolei „Deasemblacja całości” pozwala obejrzeć cały kod programu a języku asembler. W wydrukach tych są odnośniki do tekstu źródłowego programu co pozwala na analizę wygenerowanego kodu na poziomie pojedynczej instrukcji w języku pascal. Powyższe deasemblacje są dostępne jedynie w przypadku poprawnej kompilacji całości.
Przykładowo wracając do tekstu pierwszego programu w przypadku wariantu (we fragmencie):
begin(...)
repeat
PORTB := not PortData ;
(* PORTB := PortData xor 0xFF ;*)
inc ( PortData ) ;
(...)
wynik kompilacji jest następujący:
;prog0.mpas,10 :: repeat
L__main1:
;prog0.mpas,11 :: PORTB := not PortData ;
LDS R17, _PortData+0
MOV R16, R17
COM R16
OUT PORTB+0, R16
;prog0.mpas,13 :: inc ( PortData ) ;
MOV R16, R17
SUBI R16, 255
STS _PortData+0, R16
w sensie optymalności, to można napisać lepiej, ale ... może być. Natomiast w wariancie (we fragmencie):
begin
(...)
repeat
(* PORTB := not PortData ;*)
PORTB := PortData xor 0xFF ;
inc ( PortData ) ;
(...)
daje
;prog0.mpas,10 :: repeat
L__main1:
;prog0.mpas,12 :: PORTB := PortData xor 0xFF ;
LDS R17, _PortData+0
MOV R16, R17
LDI R27, 255
EOR R16, R27
OUT PORTB+0, R16
;prog0.mpas,13 :: inc ( PortData ) ;
MOV R16, R17
SUBI R16, 255
STS _PortData+0, R16
sposób realizacji instrukcji pascalowej jest odmienny (choć końcowy wynik jest identyczny).
Przy okazji łatwo zauważyć sposób rozwiązania instrukcji oczekiwania na upłynięcie czasu. W prezentowanym programie (we fragmencie):
repeat
(* PORTB := not PortData ;*)
PORTB := PortData xor 0xFF ;
inc ( PortData ) ;
Delay_ms ( 1000 ) ;
until false ;
wygenerowany kod jest następujący:
;prog0.mpas,14 :: Delay_ms ( 1000 ) ;
LDI R18, 38
LDI R17, 103
LDI R16, 246
L__main6:
DEC R16
BRNE L__main6
DEC R17
BRNE L__main6
DEC R18
BRNE L__main6
NOP
NOP
;prog0.mpas,15 :: until false ;
załadowana jest do rejestrów R18:R17:R16 (R18 jest najbardziej znaczącą częścią liczby) trzybajtowa jakaś liczba stała i dalej w pętli jest dekrementowana aż do osiągnięcia stanu zerowego. Zmieniając w specyfikacji projektowej częstotliwość generatora taktującego (zakładka Project Settings z lewej strony ekranu) przykładowo na 8 MHz, dokonując ponownej kompilacji oraz deasemblacji można zauważyć, że zmieniła się wartość stałej (nowa jest większa). Prowadzi to do wniosku, że kompilator na podstawie zadeklarowanej częstotliwości sygnału zegarowego oblicza liczbę koniecznych cykli pętli i rozwija instrukcję Delay_ms na ciąg asemblerowych instrukcji dekrementacji i skoków warunkowych. Biorąc pod uwagę możliwość obsługi przerwań, to rzeczywisty czas jaki upływa w wyniku realizacji instrukcji Delay_ms jest większy i właściwie jest trudny do oszacowania, gdyż nie można przewidzieć ile i jakich przerwań zostanie obsłużonych w ciągu mijającego interwału czasu. Z pewnością błąd będzie ułamkiem procenta, więc nie jest to powód do większych zmartwień.
Po wygenerowaniu kodu wynikowego dla procesora pozostaje jeszcze umieszczenie go w pamięci flash mikrokontrolera. Oczywiście w środowisku mikropascala jest taka możliwość,
ale nie została ona przetestowana. Kliknięcie na pokazany przycisk uruchamia odpowiednie oprogramowanie, które próbuje zlokalizować jakieś urządzenie programujące przyłączone do USB. Ja używam do programowania zestawu STK500 firmy Atmel, który jest obsługiwany poprzez port szeregowy. Eksperymenty w mikropascalem nie są wystarczającym powodem inwestycji w wymagany programator. W sumie istotne jest uzyskanie kodu programu w formacie Intel-hex i ten efekt jest uzyskiwany. Mając plik z kodem można zastosować dowolne rozwiązanie, przykładowo uruchomić program AVRStudio i poprzez STK500 umieścić kod programu w pamięci flash mikrokontrolera. Po zaprogramowaniu mikrokontrolera efekt jego działania jest zgodny z oczekiwaniem.
Załącznik: