68
0 POLITECHNIKA WARSZAWSKA WYDZIAL ELEKTRYCZNY INSTYTUT ELEKTROENERGETYKI LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ IMPLEMENTACJA JĘZYKA C W SYSTEMIE MIKROPROCESOROWYM DSM-51 Instrukcje laboratoryjne dla studiów dziennych magisterskich Ćwiczenia: M21, M22, M23, M24 Warszawa, 2004

LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

0

POLITECHNIKA WARSZAWSKAWYDZIAŁ ELEKTRYCZNY

INSTYTUT ELEKTROENERGETYKI

LABORATORIUM PODSTAW TECHNIKI

MIKROPROCESOROWEJ

IMPLEMENTACJA JĘZYKA C W SYSTEMIE MIKROPROCESOROWYMDSM-51

Instrukcje laboratoryjne dla studiów dziennych magisterskichĆwiczenia: M21, M22, M23, M24

Warszawa, 2004

Page 2: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

1

1. Wstęp

W instrukcjach pokazano przykłady wykorzystania języka C do programowaniamikrokontrolerów z rodziny 8051. Przedstawione przykłady dotyczą podstaw wykorzystania,osobom zainteresowanym dokładniejszym zapoznaniem się z językiem C oraz budowąmikrokontrolerów sugeruje się sięgnięcie do literatury [1,2,3,4,5]. Do wykonania ćwiczeń zniniejszego rozdziału konieczne jest korzystanie z systemu dydaktycznego DSM-51.

1.1. Zwięzły opis języka C

W technikach programowania od lat widoczny jest trend upraszczania językówprogramowania, które ponadto stają się coraz łatwiejsze do opanowania, oferując wielegotowych i zrozumiałych procedur. Ułatwienie programowania powoduje jednak, żetworzony w trakcie kompilacji kod wynikowy stawia dużo większe wymagania w stosunkudo urządzenia na którym ma być uruchomiony, niż kod powstający z programu napisanego wjęzyku Asembler. Asembler jest językiem bardzo dobrym, uczy programowania praktycznieod podstaw. Jest przy tym bardzo szybki i umożliwia wieloraką optymalizację koduprogramu. Jednak każdy, kto kiedykolwiek napisał program w tym języku wie, że bardzotrudno szuka się w nim błędów, a rzeczy nawet pozornie proste, trzeba wykonać używającwielu rozkazów. Jednym słowem – programy pisane w asemblerze pochłaniają mnóstwoczasu, który nie zawsze jest do dyspozycji. Większości wad asemblera pozbawiony jest językC: język o zwartej i czytelnej składni oraz kodzie źródłowym, bardzo oszczędny kodwynikowy oraz łatwa lokalizacja błędów umożliwiają zaoszczędzenie dużej ilości czasupodczas uruchamiania programu.

Istnieje wiele odmian języka C. Niniejszy rozdział został napisany z myślą owykorzystaniu tej wersji języka C która została zaimplementowana w pakiecie programówopracowanych przez firmę Keil Gmbh dla procesora 8051. W pakiecie tym program napisanyw języku C jest tłumaczony do postaci języka asemblera i następnie do postaci kodumaszynowego.

Ogólnie program źródłowy napisany w języku C składa się z wielu elementów w tym z:• identyfikatorów• dyrektyw preprocesora• komentarzy• deklaracji• instrukcji

1.1.1. Identyfikatory

Identyfikatory to słowa, którymi oznaczamy obiekty programu źródłowego, takie jaknazwy zmiennych, funkcje oraz definicje struktur itp. W języku C identyfikator składa się zliter, cyfr oraz znaku podkreślenia: _ (underline), przy czym musi zaczynać się od litery lubznaku podkreślenia. Niektóre kompilatory dopuszczają stosowanie znaku dolara (dollar sign)w nazwach identyfikatorów, ale nigdy na pierwszym miejscu. Jednak nie jest to powszechniestosowane przez programistów (kod programu nie jest kompatybilny z innymi kompilatorami:non-portable TT), toteż w przykładach nie będzie używany.

Przy konstruowaniu identyfikatorów musimy pamiętać o dwóch podstawowych zasadach:• Litery małe i wielkie uważa się za różne z tego powodu identyfikatory INDEX, index,

InDeX nie są zatem tożsame. Możemy ich użyć w jednym programie do nazwania trzechróżnych zmiennych (nie jest to jednak zalecane ponieważ nazwy powinny różnić się odsiebie znaczeniem adekwatnym do sytuacji).

• Standardowo za znaczące uważa się pierwsze 32 znaki nazwy identyfikatora. Większośćkompilatorów dopuszcza stosowanie dłuższych nazw, lecz znaki po 32 mogą być

Page 3: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

2

zignorowane przez kompilator. Warto dodać, że nigdy nie ma potrzeby używania takdługich identyfikatorów

1.1.2. Dyrektywy preprocesora

Dyrektywy preprocesora zajmują pełne wiersze i zaczynają się od znaku # (hash).Najczęściej spotykaną dyrektywą jest linia postaci:

#include <nazwa_pliku>,

gdzie nazwa_pliku jest nazwą pliku np.:

#include <reg51.h>

Wymieniony plik zostaje przed kompilacją w całości włączony do programu i najczęściejzawiera deklaracje funkcji.

1.1.3. Komentarze

Komentarz jest opisem tekstu źródłowego programu ignorowanym przez kompilator.Istnieją dwa rodzaje identyfikatorów:

/* Komentarz */

lub

// Komentarz

W pierwszym przypadku tekst komentarza może być jedno- lub wielowierszowymnapisem nie zawierającym dwu znaku */ (gwiazdka, ukośnik) np.:

/***************************************************************************Program Przykład, zerowanie linii mikrokontrolera***************************************************************************/

Natomiast po dwóch ukośnikach komentarz jest napisem mieszczącym się w jednymwierszu np.:

void write_control(unsigned char a_1){ //zapis rozkazu

Ta ostatnia metoda jest bardzo powszechna i wygodna (większość kompilatorów jąakceptuje), mimo że nie jest częścią standardu ANSI C.

1.1.4. Przykładowy program w języku C

Poniżej przedstawiono jeden z najprostszych przykładowych programów w języku C. Poskompilowaniu i uruchomieniu ustawia on bit o adresie 97h na wartość 0, a następniewykonuje niekończącą się pętlę pustych instrukcji.

1. ***************************************************************************2. Program Przykład, zerowanie linii mikrokontrolera3. ***************************************************************************/4. sbit led = 0x97; /*definicja adresu portu P1_7 */5. /*****************Funkcja główna ****************************************/6. int main (void) 7. {8. led=0;9. while (1){}10. }11. //Koniec programu

W pierwszych trzech liniach umieszczono komentarz zaczynający się dwoma znakami /* ikończący się dwoma znakami */. W linii 4 znajduje się definicja zmiennej o nazwie led. Przypomocy kwalifikatora pamięci sbit identyfikatorowi zmiennej zostaje przyporządkowanyadres miejsca w pamięci w postaci 1 bitu o adresie 97h. W linii 6 znajduje się bardzo ważnesłowo main. Jest to główna funkcja programu, która musi wystąpić w programie dokładniejeden raz. Od tej funkcji rozpoczyna się wykonywanie programu. Oczywiście nie musi ona

Page 4: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

3

wystąpić zaraz na początku kodu, lecz należy pamiętać, że jest to punkt początkowy dlacałego programu. Deklaracja funkcji zamieszczonej w przykładzie nazywana jest definicjąfunkcji. Wewnątrz funkcji głównej przy pomocy wskaźnika o nazwie led zostaje przypisanystan niski do bitu o adresie 97h. W linii 9 wywołana zostaje pętla while(1). Pętla whilesprawdza na początku warunek i jeśli jest on prawdziwy =1 pętla się wykonuje. W tymprzypadku warunek zawsze jest równy 1, dlatego pętla będzie się wykonywała wnieskończoność.

1.1.5. Funkcje

Funkcje to podprogramy mające wykonać pewne określone zadanie. Funkcja zaczyna się ikończy nawiasem klamrowym. Znajdujący się wewnątrz zestaw poleceń nazywany jestciałem funkcji. Znajdują się tam deklaracje zmiennych oraz instrukcje języka C.

Definicja funkcji wygląda następująco:

<typ rezultatu> <nazwa funkcji>( ){<deklaracja typów, definicja zmiennych, deklaracje><wyrażenia>}

Deklaracja funkcji ma następującą formę:

<typ rezultatu> <nazwa funkcji>(<definicja parametrów>);

Wywołanie funkcji jest następujące:

<nazwa funkcji>(<argumenty>)

W przykładowym programie nagłówek może mieć postać:

int main(void),

lecz można w nim pominąć zarówno słowo int, jak i słowo void. Jeśli przed nazwą funkcjinie ma określenia jej typu, funkcja jest domyślnie typu int, tzn. jej rezultat jest liczbącałkowitą (integer). Funkcja może wymagać pewnych parametrów w celu właściwegowykonania. Listę tych parametrów umieszcza się w nawiasach okrągłych (parentheses) zanazwą funkcji. Puste nawiasy oznaczają, że funkcja jest bezparametrowa, co możnapodkreślić słowem kluczowym void. Z tego powodu np. cztery poniższe nagłówki są sobierównoważne: int main(void), int main(), main(void), main().

Ciało funkcji

Ciało funkcji jest ujęte w klamry {braces}. Całość kodu wewnątrz klamr odnosi się dofunkcji (w programie przykładowym delay). W zamieszczonym poniżej przykładzieprzedstawiono fragment programu zawierający deklarację oraz wywołanie przykładowejfunkcji nie będącej funkcja main. Każda linia polecenia w ciele funkcji jest zakończonaśrednikiem. Wewnątrz funkcji deklarowane są zmienne pomocnicze oraz wywoływane sądwie pętle for().

void delay (unsigned char del) //deklaracja funkcji innej niż main{unsigned int i,j;for (j=0;j<del;j++)for (i=0;i<3000;i++);}

delay(5); //wywołanie funkcji

1.1.6. Systemy liczbowe

W procesie programowani mikrokontrolerów należy sprawnie przeliczać wartościpomiędzy systemami liczbowymi takimi jak:

Page 5: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

4

• System dwójkowy• System heksadecymalny• System dziesiętny

System binarny (dwójkowy)

Jest to system pozycyjny o postawie 2, używający cyfr 0 i 1. Wszelkie dane w układachcyfrowych reprezentowane są w tym systemie. Podobnie jak w systemie dziesiętnym, cyfrazapisana po prawej stronie ma najmniejszą wartość, a kolejne mają wartości będąceiloczynem danej cyfry i kolejnej potęgi podstawy systemu (dwójki). Liczby zapisane w tymsystemie oznacza się dodając za liczbą cyfrę 2 w indeksie dolnym lub literę b. Poszczególnecyfry każdej liczby w systemie binarnym, nazywane są bitami. Liczby ujemne można zapisaćna kilka sposobów:• zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o

znaku liczby (0 - dodatnia, 1 - ujemna), natomiast pozostałe bity decydują bezpośrednio wwartości liczby, np. -4 zapisujemy jako 1100.

• Zapis w uzupełnieniu do jedności (tzw. U1). Najstarszy bit pełni podobną rolę jak wprzypadku zapisu znak-moduł. Aby otrzymać liczbę ujemną w tym zapisie należyzanegować (zamienić na przeciwne) wszystkie bity liczby dodatniej, np. 4 = 0100b, -4 =1011b. Ponieważ występuje tu problem zera dodatniego i ujemnego (zero możnaprzedstawić w postaci: +0 = 0000b lub -0 = 1111b) system ten jest rzadko stosowany.

• Zapis w uzupełnieniu do dwóch (tzw. U2). Liczby ujemne w tym systemie otrzymujemypoprzez zanegowanie odpowiedniej liczby dodatniej i dodanie 1. Ponieważ nie występujątu dwie reprezentacje zera i działania na liczbach ujemnych są znacznie łatwiejsze niż wsystemie znak-moduł, U2 jest powszechnie stosowanym w urządzeniach cyfrowychsystemem zapisu liczb ujemnych.

System heksadecymalny (kod HEX)

Jest to system pozycyjny o postawie 16, używający cyfr 0..9 i liter A..F. Podobnie jak wsystemie dziesiętnym, cyfra zapisana po prawej stronie ma najmniejszą wartość, a kolejnemają wartości będące iloczynem danej cyfry i kolejnej potęgi podstawy systemu (16). Liczbyzapisane w systemie heksadecymalnym oznacza się dodając za liczbą cyfrę 16 w indeksiedolnym lub literę h.

Przekształcenie liczby w systemie binarnym na liczbę heksadecymalną

Przekształcając liczbę binarną na liczbę heksadecymalną należy ja najpierw podzielić na 4cyfrowe grupy, zaczynając od prawej strony. Gdy w efekcie takiego podziału ostatnia grupanie ma 4 cyfr należy uzupełnić ją zerami. Następnie dla każdej takiej grupyprzyporządkowuje się wartości heksadecymalne według tabl. 7.1.

Tablica 7.1. Tablica zamiany kodów binarnych na heksadecymalne.

Grupa cyfra heksadecymalna grupa cyfra heksadecymalna0000 0 1000 80001 1 1001 90010 2 1010 A0011 3 1011 B0100 4 1100 C0101 5 1101 D0110 6 1110 E0111 7 1111 F

Następnie tak uzyskane kody grup utworzą liczbę w zapisie heksadecymalnym.

Page 6: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

5

Przykład:Liczba binarna: 1101101101b. Na wstępie dokonywany jest podział na cztero cyfrowe

grupy, zaczynając od prawej strony, co w efekcie daje: 11 0110 1101.Ponieważ pierwsza grupa nie jest pełna, uzupełniamy ją do 4 cyfr zerami dostając: 0011

0110 1101. Następnie każdej grupie zostaje przyporządkowany kod heksadecymalny (cyfraszesnastkowa) wg tabl.7.1.

0011 0110 1101 3 6 DW związku z powyższym po przekształceniach liczba przybierze postać 36Dh.

Przekształcenie liczby w systemie szesnastkowym na liczbę binarną

Przekształcając liczbę heksadecymalną na liczbę binarna należy każdej z cyfr liczbyszesnastkowej przyporządkować cztery cyfry liczby binarnej wg tabl.7.1.

Przykład:Liczba szesnastkowa: 4C26Fh. Każdej z cyfr liczby szesnastkowej należy

przyporządkować cztery cyfry liczby binarnej wg tabeli 8.2.: 4 C 2 6 F0100 1100 0010 0110 1111Następnie należy łączyć otrzymane grupy cyfr i pominąć zera na początku liczby nie

mające wpływu na jej wartość. Przekształcana liczba przybierze więc postać:1001100001001101111b.

Przekształcenie liczby w systemie binarnym na liczbę dziesiętną

Przekształcając liczbę binarna na liczbę dziesiętną należy posłużyć się pojęciem wagipozycji. Każda cyfra zależnie od pozycji posiada określoną wagę wg poniższego zestawienia:

... 62 , 52 , 42 , 32 , 22 , 12Jedynka na danej pozycji oznacza, że wagę dla danej pozycji należy uwzględnić w sumie

będącej liczbą wynikową, 0 oznacza, że nie należy jej uwzględniać.

Przykład:Liczba binarna: 10110101b. Ponieważ występuje 8 cyfr, kolejne (od lewej) będą miały

następujące wagi: 72 =128, 62 =64, 52 =32, 42 =16, 32 =8, 22 =4, 12 =2, 02 =1 (potęgi liczby 2). Ztego względu wartość dziesiętna przedstawionej liczby binarnej wyniesie:

1*128 + 0*64 + 1*32 + 1*16 + 0*8 + 1*4 + 0*2 + 1*1 = 128+32+16+4+1 = 181

1.1.7. Zmienne, stałe, tablice i ich deklaracje oraz reprezentacja

Nazwa zmienna określany jest pewien obszar w pamięci mikrokontrolera, w którym mogąbyć przechowywane dane. Z punktu widzenia osoby piszącej program, zmienna posiadanastępujące cechy podstawowe: nazwa, identyfikator, typ, wartość.

Nazwa zmiennej pozwala wskazać w programie, fragment pamięci, w którymprzechowywana jest zmienna. Łatwiej jest posługiwać się nazwą niż adresem liczbowym(łatwiej zrozumieć napis imię niż *0x12342. Kompilator dokonując tłumaczenia napisanegoprogramu zamienia wszystkie nazwy zmiennych na odpowiadające im adresy w pamięci.Wszystkie nazwy zmiennych przed użyciem muszą być zadeklarowane.

Wartość zmiennej jest tym, co przechowujemy w obszarze pamięci określanym przeznazwę. Wartość może się zmieniać w dowolnym momencie w czasie wykonania programu.Wartością może być liczba całkowita, zmiennoprzecinkowa (ułamek dziesiętny), adres wpamięci komputera (tzw. wskaźnik), tekst itp. W momencie deklaracji wartość zmiennejlokalnej (zadeklarowanej wewnątrz funkcji) jest nieokreślona tzn. jej wartość jestprzypadkowa, natomiast zmienne globalne (deklarowane poza funkcjami) są inicjowane nazero.

Page 7: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

6

Typ zmiennej określa jaką wartość można wpisać do obszaru wskazywanego przez nazwę(czy będzie to liczba całkowita, zmienno-przecinkowa itp., czy też inny rodzaj danej). Wzależności od rodzaju wartości (typu zmiennej), inny będzie rozmiar pamięci potrzebny do jejzapamiętania. Poniżej w tabl. 7.2 pokazano typy zmiennych występujące w języku C wraz zliczbą bitów jaką zajmują (Rozmiar) oraz zakresem zmienności liczby jak może zostać w niewpisana (Zakres).

Tablica 7.2. Tablica zmiennych języka C

RozmiarTyp –słowo kluczowe

bit BajtZakres

char 8 1 -127 to 127unsigned char 8 1 0 to 255int 16 2 -32767 to 32767Unsigned int 16 2 0 to 65535Signed short 16 2 -32767 to 32767Unsigned short 16 2 0 to 65535long int 32 4 -2147483647 to 2147483647unsigned long int 32 4 0 to 4294967295*sbit 1 --- 0 lub 1*sfr 8 1 0 do 255float 32 4 6 cyfrowa precyzjadouble 64 8 10 cyfrowa precyzjalong double 80 10 16 cyfrowa precyzja

* Typy charakterystyczne dla mikrokontrolera 8051 i kompilatora Keil.

Kompilator na podstawie typu określa jaką ilość pamięci należy przydzielić zmiennej ijakie operacje są na niej dopuszczalne, np.:

int x;

oznacza deklarację zmiennej całkowitej (typu int) o nazwie x. Słowo int jest w języku Csłowem zarezerwowanym (reserved word) słowem kluczowym.

Słowa kluczowe mają ściśle określone funkcje programowe i nie mogą być używane winnych celach; np. nie można ich użyć jako identyfikatora zmiennej. Rodzaj operacjidopuszczalny dla danej zmiennej oraz przyjęty sposób reprezentacji danej zależą odprzyjętego dla niej systemu liczbowego.

System liczbowy to sposób reprezentacji wartości liczbowej. Podstawowymi cechamikażdego systemu są:• pozycyjność (lub nie) - w systemach pozycyjnych wartość cyfry zależy od jej pozycji w

liczbie ilość cyfr• podstawa systemu - liczba, której kolejne potęgi wyznaczają wartości (wagi) kolejnych

cyfr w liczbiePowszechnie używany system dziesiętny jest systemem pozycyjnym o podstawie 10,

wykorzystującym 10 cyfr. Jednakże w układach cyfrowych znacznie wygodniejszy jestsystem binarny oparty na liczbie 2. System ten ma jednak zasadniczą wadę - do zapisu dużychliczb potrzebna jest bardzo duża ilość cyfr, a ponadto takie długie ciągi zer i jedynek sąbardzo trudne do zapamiętania. Stąd człowiek używa systemu o podstawie 2, głównie wpostaci zapisu heksadecymalnego (szesnastkowego), rzadko oktalnego (ósemkowego).System szesnastkowy ma tę cechę, że zapis dużych liczb nie stanowi problemu poza tymzamiana danej na system binarny i odwrotnie jest bardzo prosta.

1.1.8. Typy zmiennoprzecinkowe

Specjalnego opisu wymagają niezwykle ważne zmienne umożliwiające wykorzystywanieobliczeń zmiennoprzecinkowych. Procesor mikrokontrolera wykorzystuje liczby całkowite ztego względu pojawia się duży problem w przypadku konieczności użycia liczb

Page 8: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

7

rzeczywistych tj. liczb o postaci: 243.75 lub większych np.12300055446684316545.65468166546. W takich przypadkach pomocny jestzmiennopozycyjny zapis liczb. Liczby zapisane w ten sposób charakteryzują się tym, żeniezależnie od wielkości liczby jej zapis zajmuje taką samą, stałą liczbę komórek pamięci.Obiekty typu float (ang. floating point number) to liczby zmiennoprzecinkowe (z pływającymprzecinkiem), np.: 5.21 czy -3.0. Zajmują one 4 bajty pamięci, co oznacza, że tego rodzaju wliczba może mieć co najmniej 6 cyfr po przecinku.

Tworzenie liczb zmiennoprzecinkowych:Rozpatrując strukturę każdej liczby należy stwierdzić, że można ją przedstawić w postaci:

m*10c, gdzie:• m – mantysa,• c – cecha (całkowita)) 1 < c < 10.

np. liczba 12 341 220 000 000 000 000 = 1.234122*1019.Analogicznie dowolna liczba może być sprowadzona do postaci m*2c , gdzie:

• 1 < m < 2,• c jest całkowite),co umożliwia już prowadzenie działań na liczbach binarnych.

W tabl.7.3 przedstawiono sposób zamiany liczby 243.75d = 11110011.11b na liczbęzmiennoprzecinkową typu float (4 bajtową).

Tablica 7.3. Przedstawienie liczby 243.75d w formacie zmiennoprzecinkowym float72 62 52 42 32 22 12 02 . 12− 22−

128 64 32 16 8 4 2 1 . 0,5 0,251 1 1 1 0 0 1 1 . 1 1

Aby otrzymać mantysę tej liczby, należy ją odpowiednio przesuwać w lewo lub w prawo(pomnożyć lub podzielić przez dwa) do momentu, w którym po lewej stronie przecinkaotrzymana zostanie jedna jedynka.

W przedstawionym przykładzie mantysa wynosi więc:m = 1.111001111b.Liczba przesunięć stanowi wtedy cechę liczby. Cecha posiada znak zależny od kierunku

przesuwania:• + w przypadku przesuwania w lewo,• - w przypadku przesuwania w prawo.

W analizowanym przykładzie c wynosi +7, ponieważ w celu uzyskania mantysy m zzakresu 1<m<2 należało dokonać siedem przesunięć liczby w lewo. Tak więc liczba 243.75d= m*2c, gdzie: c = 111b, zaś m = 1.11100111b.

Zapis liczby rzeczywistej typu float zajmuje 4 bajty (32 bity) i podzielony jest na trzyczęści.

Pierwsza z nich jest to jeden bit znaku. Przyjmuje się, że przy ujemnych liczbach bit tenjest równy 1, w przeciwnym przypadku jest on równy zero.

Kolejną częścią jest osiem bitów przeznaczonych na cechę liczby (cecha zajmuje 7najmłodszych bitów z pierwszego bajtu i jeden najstarszy bit drugiego bajtu).

Trzecią część stanowią pozostałe bity przeznaczone na mantysę (jest ich 23).W sumie daje to 1+8+23 = 32 bity. Położenie opisanych części liczby float pokazuje

rys.7.1.

Bajt 4 Bajt 3 Bajt 2 Bajt 1

Znak 1bit Cecha 8 bitów Mantysa 23 bity

Rys. 7.1. Budowa zmiennej typu Float

Page 9: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

8

Po wyznaczeniu wtedy cechy i mantysę oraz znając znak liczby, możemy ją zakodować.W trakcie kodowania przyjmuje się, że:• Jeżeli Gdy liczba jest dodatnia, wtedy bit znaku będzie ustawiony na 0. Zapisując cechę,

przyjęto, że zwiększa się ją o 127 w celu uwzględnienia znaku (nie stosuje się kodu U2).• Ponieważ każda mantysa zaczyna się od „1”, zapisywanie jej byłoby marnotrawstwem,

dlatego też przyjęto, że mantysa zostaje zapisana bez tej jedynki.Tak więc dla naszej liczby 243.75d:

● w miejsce bitu znaku należy wstawić 0;● w miejsce cechy należy wstawić wartość: 7+127=10000110b.● w miejsce mantysy należy wstawić 1110 0111 1000 0000 0000 000b = 23 bity;Ostatecznie zapis liczby zmiennopozycyjnej 243.75d przedstawia się następująco:01000011 01110011 11000000 00000000 43h 73h C0h 0Dla liczba –243.75d różni się od analizowanej jedynie znakiem, czyli jednym bitem, w

związku z tym jej zapis wygląda następująco:11000011 01110011 11000000 00000000 C3h 73h C0h 0

1.1.9. Stałe

Poza zmiennymi w języku C istnieją również stałe, każda stała posiada typ, określonyprzez jej wartość i sposób zapisu. Stałe mogą być kilku typów: numeryczne, znakowe,tekstowe.

Stałe numeryczne

Stałe numeryczne dzielą się na całkowite i zmiennoprzecinkowe. Stała całkowita składa sięz dowolnej liczby cyfr. Na początku może znajdować się znak '-'. W języku C na początkuliczby może znajdować się również znak + oznaczający liczbę dodatnią. Stałe całkowite, jeślimieszczą się w zakresie zmiennych typu int, są traktowane jako int. W przypadku, gdy stałanie mieści się w zakresie typu int, a mieści się w zakresie typu long lub na końcu znajduje sięlitera 'l' - jest traktowana jako long. Jeśli stała nie mieści się w zakresie typu long - jesttraktowana jako stała zmiennoprzecinkowa typu double. Stałe bez znaku definiuje siędopisując na końcu literę 'u'. Poniżej pokazano kilka przykładów stałych numerycznych:

1234 -198 12lu 123u -1956l

Stała zaczynająca się od litery 'O' oznacza stałą ósemkową, np.:

O12 0777

Stała zaczynająca się od znaków „0x” oznacza stałą heksadecymalną (szesnastkową). Wprzypadku stałej szesnastkowej liczby 10-15 są zastępowane literami 'a'-'f', np.:

0xffff 0x12fe

Stała zmiennoprzecinkowa składa się z opcjonalnej części całkowitej, znaku '.', częściułamkowej oraz opcjonalnej definicji wykładnika. Część ułamkowa jest stałą całkowitą niezawierająca znaków '+' i '-'. Część określająca wykładnik jest poprzedzona znakiem 'e', poktórym występuje liczba całkowita, np.:

1.23 .23 0.23 1. 1.01.2e10 = 1.2 * 1010

.23e-15 = 0.23 * 10-15

Stałe znakowe

Stałe znakowe w języku C składają się z pojedynczych znaków zamkniętych w apostrofy;np.: ”a”, ”0”. Stałe znakowe są w rzeczywistości stałymi całkowitymi. Ich wartość jest równakodowi znaku na maszynie, na której kompilowany jest program. Jeśli program jest

Page 10: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

9

kompilowany na maszynie pracującej w kodzie ASCII, to wartość stałej ”0” jest równa 48, awartość stałej ”A” - 65. Użycie stałych znakowych zamiast kodów powoduje, że program jestbardziej przenośny.

Niektóre kody nie mają drukowalnych odpowiedników, dlatego wprowadzono konstrukcjęzaczynającą się od znaku '\'. Znak znajdujący się po znaku '\' jest traktowany w sposóbspecjalny. W tabl. 7.4 przedstawiono stałe znakowe występujące w języku C.

Tablica 7.4 Stałe znakowe języka C

Zapis Symbol Opis\n NL(LF) nowa linia (new line)\t HT tabulacja pozioma (horizontal tab)\v VT tabulacja pionowa (vertical tab)\b BS skasowanie znaku na lewo (backspace)\r CR powrót karetki (carriage return)\f FF wysunięcie strony (form feed)\a BEL sygnał dźwiękowy (alert)\\ \ Backslash\? ? znak zapytania\' ' Apostrof\" " Cudzysłów\0 NUL znak o kodzie 0\ooo ooo znak w kodzie ósemkowym\xhh hh znak w kodzie szesnastkowym

Poniżej w tabl. 7.5 przedstawiono tabelę zawierającą kody ASCII.

Tabela 7.5. Tabela kodów ASCII

0 1 2 3 4 5 6 7 8 930 ! „ # $ % & ‘40 ( ) * + , - . / 0 150 2 3 4 5 6 7 8 9 : ;60 < = > ? @ A B C D E70 F G H I J K L M N O80 P Q R S T U V W X Y90 Z [ \ ] ^ _ ` a b c100 d e f g h I j k l M110 n o p q r s t u v w120 x y z { | } ~

Stałe tekstowe

Stała tekstowa jest ciągiem znaków zamkniętych w cudzysłowy, np.: "To jest stałatekstowa". Każda stała tekstowa kończy się znakiem o kodzie 0 (zawiera zawsze o jeden znakwięcej). Stała tekstowa jest tablicą znaków zawierającą odpowiednią liczbę elementów. Np."asdf" jest typu char[5]. Zapis ze znakiem ”\” może być również używany wewnątrz stałychtekstowych. Stała tekstowa może zawierać znak: ”\0”, ale większość programów i funkcjibibliotecznych nie będzie jej poprawnie obsługiwać.

1.1.10. Tablice

Tablica jest zbiorem elementów tego samego typu. Każdy element tablicy ma numer.Numer pierwszego elementu w tablicy jest zawsze równy zero. W języku C nie możnadeklarować tablic wielowymiarowych, jest jednak możliwa deklaracja tablic zawierającychtablice, co odpowiada tablicom wielowymiarowym w innych językach. Deklaracja tablicy mapostać:

<typ_elementu><nazwa_zmiennej>[rozmiar];

Przykład:

Page 11: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

10

int arr[10];

Każdy element deklarowanej tablicy będzie typu typ_elementu, pierwszy element będziemiał numer 0, drugi - 1, ... , ostatni - rozmiar-1. Tablicę można inicjować podając w deklaracjipo jej nazwie i znaku równości listę wartości oddzielonych przecinkami i zamkniętych wnawiasach klamrowych. Jeśli tablica jest inicjowana w deklaracji, to nie jest koniecznepodawanie jej rozmiaru. Możliwość ta jest dostępna we wszystkich kompilatorach ANSI C.

Przykład:

int a1[5] = {1,5,3,4,2};int a2[] = {1,5,6,3,4,5,6};

Tablic używa się w programie podając nazwę zmiennej tablicowej oraz numer elementu,którego operacja ma dotyczyć ujęty w nawiasy kwadratowe. Jako numer elementu możesłużyć stała całkowita, zmienna typu całkowitego lub dowolne wyrażenie, którego wynikiemjest liczba całkowita. Nawiasy kwadratowe zawierające numer elementu tablicy nazywane sąoperatorem indeksowania, np.:

int a[10];int i;i = 5;a[5] = 10;a[a[5] - 5] = 4;

Możliwe jest zadeklarowanie tablicy tablic (odpowiadającej tablicy dwu- lub więcejwymiarowej), np.:

int a[10][15];

Powyższa instrukcja deklaruje 10-cio elementową tablicę a, której polami są 15-stoelementowe tablice zmiennych typu int. Odwołanie do elementów tablicy następuje w sposóbnaturalny - najpierw podaje się numer tablicy, potem numer elementu wewnątrz tej tablicy:

a[4][5] = 10;

1.1.11. Wskaźniki

Wskaźnik to zmienna, która zawiera adres innej zmiennej. Użycie wskaźników prowadzido bardziej efektywnego kodu niż otrzymywany innymi metodami. Jedną z niepożądanychcech wskaźników jest to, że w przypadku nieostrożnego ich stosowania przyczyniają cię dotworzenia niezrozumiałych programów. Łatwo jest utworzyć wskaźnik, który będziewskazywał na bliżej nieokreślone miejsca. Kompilator języka C dedykowany dlamikrokontrolera 8051 umożliwia użycie 2 typów wskaźników. Pierwszy to wskaźnik doobszaru pamięci deklarowanego przy pomocy kwalifikatorów (takich jak CODE czy DATA)opisanych w rozdziale 7.2.1. dotyczącym kompilatora języka C dla mikrokontrolera 8051.Drugi umożliwia wskazanie dowolnej danej w dowolnym obszarze adresowaniamikrokontrolera. Ważne jest to, że jeśli wskaźnik przypisany jest do obiektuzakwalifikowanego do określonego obszaru pamięci, to również zostaje przypisany do tegowłaśnie obszaru pamięci, w którym umieszczony jest wskazywany obiekt. Drugi wskaźniknosi nazwę generic. Wskaźnik typu generic zawiera dodatkowo 1 bajt przeznaczony na kodwskazywanego obszaru pamięci. W związku z tym wskaźnik kwalifikowany do pewnegoobszaru pamięci zajmuje 2 bajty a wskaźnik generic zajmuje 3 bajty.

Poniżej przedstawiono przykłady deklaracji różnych wskaźników.

data char[10] Tablica = {0,1,2,3,4,5,6,7,8,9}char generic *Tablica; //wskaźnik do obszaru DATA, wskazuje elementy

//zmiennej Tablicachar generic *p1; / //wskaźnik do dowolnego obszaru danychpdata char *klawiatura; //wskaźnik do 8 bit. adresu urządzeniazewnętrznegoxdata char *pamiec_danych; //wskaźnik do zewnętrznej pamięci

Page 12: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

11

W powyższym przykładzie użyto operatora adresowania pośredniego ”*” zastosowany dowskaźnika podaje zawartość wskazywanego obiektu y=*wskaźnik. W języku C istniejejeszcze inna metoda przypisania wskazań do określonej zmiennej. Użyciejednoargumentowego operatora ”&” zwraca adres zmiennej (Uwaga: można go stosowaćtylko do obiektów zajmujących pamięć zmiennych oraz tablic).

Char x=1, y=2, z=[5];Char *wskaźnik; //deklaracja wskaźnikawskaźnik=&x; //zmienna wskaźnik wskazuje na xY=*wskaźnik; //teraz zmienna y ma wartość 1wWskaźnik=0; //teraz zmienna x ma wartość 0wskaźnik=&z[0]; //zmienna wskaźnik wskazuje na 1 element tablicy z

1.1.12. Operatory

Kolejnym elementem języka C są operatory, np.: dodawanie, odejmowanie, dzielenia itd.Kompilator języka C może przebudować wyrażenia. W szczególności możliwa jest zmiana

łączności operatorów dodawania, odejmowania, mnożenia i dzielenia. W przypadkachwątpliwych lepiej jest odpowiednie wyrażenia ująć w nawiasy. W poniższej tabl. 7.5 przezwartość należy rozumieć wyrażenie, które mogłoby wystąpić po lewej stronie operatoraprzypisania (najczęściej zmienna lub wyłuskanie wskaźnika). L-wartość musi posiadać adres.Nawiasy nie mają wpływu na to czy wyrażenie jest l-wartością.

Uwaga: kompilator oblicza wyrażenia stałe na etapie kompilacji i w ich miejsce wstawiaobliczoną wartość.

Tablica 7.5. Operatory arytmetyczne

OperacjaOperator

Przykład OpisOperand Typ rezultatu

* X*Y Mnożenie arytmetyczny arytmetyczny/ X/Y Dzielenie arytmetyczny arytmetyczny% X%Y Reszta z dzielenia liczba całkowita liczba całkowita+ X+Y Dodawanie Arytmetyczny lub ptr liczba całkowita lub ptr- X-Y Odejmowanie Arytmetyczny lub ptr liczba całkowita lub ptr++ X++ Inkrementacja Arytmetyczny lub ptr liczba całkowita lub ptr-- X-- Dekrementacja Arytmetyczny lub ptr liczba całkowita lub ptr

Tablica 7.6. Operatory porównania

OperacjaOperator

Przykład OpisOperand Typ rezultatu

< If(X<Y) Mniejszy niż arytmetyczny lub ptr liczba całkowita> If(X>Y) Większy niż arytmetyczny lub ptr liczba całkowita<= If(X<=Y) Mniejszy lub równy arytmetyczny lub ptr liczba całkowita>= If(X>=Y) Większy lub równy arytmetyczny lub ptr liczba całkowita== If(X==Y) Równy arytmetyczny lub ptr liczba całkowita!= If(X!=Y) Różny od arytmetyczny lub ptr liczba całkowita

Tablica 7.7. Operatory bitowe

OperacjaOperator

Przykład OpisOperand Typ rezultatu

<< X=X<<2 Przesunięcie w lewo 2 razy liczba całkowita taki sam jak operand>> X=X>>4 Przesunięcie w prawo 4 razy liczba całkowita taki sam jak operand& P1=P1&0xF0 Bitowe and liczba całkowita liczba całkowita^ P1=P1^0xAA Bitowe xor liczba całkowita liczba całkowita| P1=P1|0xF0 Bitowe or liczba całkowita liczba całkowita~ ~0x77 Dopełnienie jedynkowe liczba całkowita liczba całkowita

Uwaga: 0 jest wstawiane do nowych bitów (po przesunięciu) chyba, że wystąpiła operacjaprzesunięcia w prawo liczby ze znakiem (SIGNED) - wtedy na nowe miejsce kopiowanyjest znak.

Page 13: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

12

Tablica 7.8. Operatory logiczne

OperacjaOperator

Przykład OpisOperand Typ rezultatu

&& If(x&&0x80=0) Iloczyn logiczny and arytmetyczny lub ptr liczba całkowita|| If(x||0x11=0x11) Suma logiczna or arytmetyczny lub ptr liczba całkowita

Tablica 7.9. Wywoływanie funkcji, operatory selekcji

Operator Składnia Opis() funcname() Wywołanie funkcji[] arrayptr[] Wywołanie tablicy. struct.member Bezpośrednia selekcja członka-> structptr-> Pośrednia selekcja członka

1.1.13. Operator przypisania

Operatorem przypisania w języku C jest znak ”=” lub w przypadkach złożonychoperatorów znak ”= oraz znak działania”. Wszystkie operatory przypisania zwracają wartość,która została przypisana do danej zmiennej. Ponadto operatory przypisania są prawostronniełączne tzn. wykonują się one od prawej do lewej. Możliwe są więc zapisy:

int a, b, c;a = b = c = 5;

Poza prostym operatorem przypisania, w języku C można wykorzystać złożone operatoryprzypisania przedstawione w tabl. 7.10.

Tablica 7.10. Złożone operatory przypisania

OperacjaOperator

Zapis Obraz OpisOperatory

+= X+=10 X=X+10 Dodawanie arytmetyczny-= X-=10 X=X-10 Odejmowanie arytmetyczny*= X*=5 X=X*5 Mnożenie Arytmetyczny/= X/=2 X=X/2 dzielenie by Arytmetyczny%= X%=3 X=X%3 modulo liczba całkowita>>= X>>=2 X=X>>2 przesunięcie bitów w prawo liczba całkowita<<= X<<=4 X=X<<4 przesunięcie bitów w lewo liczba całkowita&= X&=0xF0 X=X&0xF0 bitowe AND liczba całkowita^= X^= 0xF0 X=X^0xf0 bitowe XOR liczba całkowita|= X|= 0xAA X=X|0xAA bitowe lub liczba całkowita

1.1.14. Operacja rzutowania

Kolejną ważną operacją jest operacja rzutowania czyli zmiany typu danych.Operator rzutowania służy do zmiany typu danych na inny, np.:

(typ_danych)x;

gdzie typ_danych oznacza ten typ danych, na który ma zostać zamieniona wartośćzmiennej x.

Np. deklaracja:

y=(float)a;

W przypadku gdy a jest liczba całkowitą (typu int) o wartości 5 spowoduje jej zmianę naliczbę zmiennoprzecinkową 5.0 (typu float).

1.1.15. Instrukcje warunkowe

Instrukcja warunkowa umożliwia wykonanie pewnej instrukcji w zależności od wartościwyrażenia. Wszystkie wartości różne od 0 są w języku C traktowane jako prawda, równe 0jako fałsz. Wyrażenia logiczne są liczone tylko do momentu, w którym można określić jegowartość.

if (wyrażenie) instrukcja

Page 14: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

13

lub

if (wyrażenie) instrukcja1 [else instrukcja2]

W obu rozkazach instrukcja może być instrukcją złożoną. Wyrażenie musi być typuskalarnego (wartość wyrażenia równa fałsz ”0” lub prawda ”1”). W pierwszej kolejnościwyznaczana jest wartość wyrażenia.

W pierwszym przypadku instrukcja wykonuje się, jeśli wartość wyrażenia jest prawdą.Jeżeli wartość wyrażenia jest fałszem instrukcja jest pomijana.

W drugim wypadku instrukcja1 wykonuje się, jeśli wartość wyrażenia jest prawdą. Jeżeliwartość wyrażenia jest fałszem wykonuje się instrukcja2. W tym przypadku wykonuje sięinstrukcja1 lub instrukcja 2, nigdy obie.

Przykład:

if (a > 5) printf("a jest większe od 5\n");else printf("a jest mniejsze lub równe 5\n");

1.1.16. Instrukcja wyboru - switch

Instrukcja switch służy do wybierania jednego przypadku z wielu. Wartość wyrażeniainstrukcji switch jest porównywana ze stałymi związanymi z etykietami case. Jeżeli wynikiemtego wyrażenia jest stała związana z którąś z etykiet case, wykonywanie programu jestkontynuowane począwszy od tej właśnie etykiety. Jeżeli nie jest dostępna żadna pasującaetykieta, wykonywanie programu przechodzi do etykiety domyślnej - default (o ile jest onadostępna). Chcąc wyjść z instrukcji switch należy użyć rozkazu break - napotkanie kolejnegocase lub default nie powoduje wyjścia z instrukcji switch.

Składnia instrukcji wyboru jest następująca:

switch (wyrażenie){etykieta1: wyrażenia-1etykieta2: wyrażenia-2etykietan: wyrażenia-ndefault-case: wyrażenia-defaultowe

}

Na przykład:

enum dni {pon, wt, sr, czw, pt, sob, ndz};{switch(dzien){ case pon: case wt: printf("Nie lubię początku tygodnia \n"); break; case sob: case ndz: printf("Lubię weekend!\n"); default: printf("Środek tygodnia jest taki sobie, ale weekend jest świetny \n"); break;}}

1.1.17. Instrukcje pętli programowych

Pętle programowe służą do powtarzania tych samych instrukcji wielokrotnie, aż do chwiligdy zostaną spełnione określone warunki. Język C umożliwia wykorzystanie dwu rodzajówpętli: while, for.

Page 15: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

14

Instrukcja pętli while

Instrukcja while jest pętlą sterowaną z góry – co oznacza, że najpierw wyznaczana jestwartość warunku pętli (czyli jej wyrażenia sterującego) Jeżeli jest on prawdziwy czyli równy”1”, to następnie wykonywane jest ciało funkcji, po czym wyrażenie sterujące obliczane jestponownie. Rozkaz umieszczony w pętli „while” (może to być instrukcja złożona!) jestpowtarzany aż do momentu, gdy wartość wyrażenia będzie fałszem czyli równa 0. Wprzypadku, gdy wartość wyrażenia od razu będzie równa 0, instrukcja nie wykona się anirazu. Jeśli wyrażenie nie przyjmie nigdy wartości 0, instrukcja będzie się wykonywaćnieskończoną ilość razy. Jeżeli wartość warunku jest fałszywa czyli równa 0, to wykonywanieprogramu jest kontynuowane od pierwszej instrukcji następującej po ciele pętli.

Składnia instrukcji while jest następująca:

while(wyrażenie)instrukcja

Instrukcja pętli do...while

Pętla „do” jest podobna do pętli „while”, z tą różnicą, że najpierw wykonywane jestinstrukcja, a następnie wyznaczana jest wartość wyrażenia sterującego (instrukcja sterowana zdołu). Oznacza to, że instrukcja wykona się przynajmniej jeden raz.

Ciało pętli (instrukcja lub instrukcje) jest powtarzane aż do chwili, gdy wyrażenie sterującebędzie fałszywe.

Składnia instrukcji do...while jest następująca:

do instrukcja while(wyrażenie);

Przykład:

{do{ printf(„Zakończyć program? \n"); }while (getchar() != 't');}

Podstawową różnicą w stosunku do instrukcji while jest to, że ciało pętli do...while jestwykonywane przynajmniej jednokrotnie. Ciało pętli while może nie zostać w ogólewykonane, ponieważ jego wyrażenie sterujące już na samym początki może być fałszywe.

Instrukcja pętli for

Instrukcja for jest pętlą sterowaną z dołu – co oznacza, że najpierw wykonywana jestinstrukcja, a następnie wyznaczana jest wartość wyrażenia sterującego.

Składnia instrukcji jest następująca:

for (wyrażenie1;wyrażenie2;wyrażenie3) instrukcja

Wszystkie pokazane wyrażenia są opcjonalne. Wyrażenie1 jest obliczane przed wejściemdo pętli (UWAGA: tylko raz). Wyrażenie1 może być również deklaracją, a zasięg takzadeklarowanej zmiennej ograniczony jest tylko do pętli for. Następnie obliczane jestwyrażenie2 (wyrażenie sterujące które musi być typu skalarnego) i sprawdzany jest warunekczy jest ono różne od 0 (prawdziwe). Jeśli tak, wykonywana jest instrukcja i obliczane jestwyrażenie3. Następnie sprawdzana jest wartość wyrażenia2. Pętla jest wykonywana aż domomentu, gdy wartość wyrażenia2 będzie równa 0 (wyrażenie będzie fałszywe). Wyrażenie3jest zawsze obliczane po wykonaniu instrukcji. Jeśli wszystkie trzy wyrażenia w pętli for sąpuste (pętla postaci: for(;;) instrukcja), to jest to bezwarunkowa pętla nieskończona.Instrukcja w pętli for może nie wykonać się ani razu, jeśli wyrażenie2 będzie od razu równe0. Pętla for może być pętlą nieskończoną, jeśli wyrażenie2 nigdy nie przyjmie wartości 0.Wyrażenie pierwsze będzie zawsze obliczone (dokładnie jeden raz). Pętla for umożliwia

Page 16: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

15

zgrupowanie instrukcji inicjującej pętlę, warunku kontynuacji i instrukcji wykonanej pozakończeniu pętli w jednym miejscu w programie.

Poniżej pokazano przykład instrukcji for:

{int i;char txt[10];for (i = 0; i < 10; i ++) txt[i] = 'A';}

1.1.18. Skoki bezwarunkowe

Instrukcje skoku służą do bezwarunkowego przejścia w określone miejsce programu. Wjęzyku C występują poniższe rodzaje skoków bezwarunkowych: goto, break, continue, return.

Instrukcja skoku do etykiety goto

Instrukcja skoku goto powoduje bezwarunkowe przekazanie sterowania do instrukcjiopatrzonej etykietą. Etykieta musi znajdować się w tej samej funkcji, z której zostaławykonana instrukcja skoku.

Składnia instrukcji:

goto etykieta;

Etykietę definiuje się w dowolnym miejscu programu wewnątrz funkcji, w następującysposób:

etykieta;

Etykiet nie trzeba deklarować.Poniżej pokazano przykład wykorzystania instrukcji skoku do etykiety:

int f(){int l;scanf("%d", &l");if (l < 0) goto err;printf("%d! = %d\n", l, silnia(l));return 1;err:printf("Nie mozna obliczyc silni liczby mniejszej od 0\n");return 0;}

Instrukcja break

Instrukcja break mogąca wystąpić tylko wewnątrz pętli lub instrukcji switch powodujewyjście z najbardziej zagnieżdżonej pętli lub instrukcji switch.

Składnia instrukcji jest następująca:

break;

Poniżej pokazano dwa przykłady wykorzystania instrukcji break:Przykład 1:

int i;...switch (i){ case 1: case 2: printf("1 lub 2\n"); break; default : break;}...

Page 17: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

16

Przykład 2:

int i, l;for (i = 0; i < 10; i ++){ scanf("%d", &l); if (l < 0) break; printf("%d! = %d\n", l, silnia(l));}...

Instrukcja continue

Instrukcja continue może wystąpić tylko wewnątrz instrukcji pętli i powoduje przejście doinstrukcji położonej za ostatnią instrukcją w pętli (czyli do instrukcji sprawdzającej warunekkontynuacji pętli).

Jej składnia jest następująca:

continue;

Poniżej pokazano przykład wykorzystania instrukcji continue:

int i, l;for (i = 0; i < 10; i ++){scanf("%d", &l);if (l < 0) continue;printf("%d! = %d\n", l, silnia(l));}...

Instrukcja return

Instrukcja return powoduje wyjście z aktualnie wykonywanej funkcji. Instrukcja returnmoże wystąpić w dowolnym miejscu w ciele funkcji. Opisywany rozkaz może być wywołanyz podaniem wyrażenia lub bez. Jeśli wyrażenie zostanie podane, to jego wartość zostanieobliczona przed wyjściem z funkcji i zwrócona na zewnątrz.

Składnia instrukcji return może być następująca:

return;

lub

return wyrażenie;

Poniżej przedstawiono przykład wykorzystania instrukcji return:

long silnia(int n){long wynik;int i;if (n <= 0) return 1;wynik = 1;for (i = 1; i <= n; i ++)wynik *= i;return wynik;}

1.1.19. Instrukcja pusta

Instrukcja pusta jest stosowana tam, gdzie składnia języka wymaga wystąpienia instrukcji,a osoba pisząca program nie chce wprowadzać w tym miejscu jakichkolwiek poleceń.

Instrukcja pusta ma następująca formę:

;

Page 18: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

17

Takim miejscem są często instrukcje pętli, np.:

{for(;;;);}

1.1.20. Preprocesor i dyrektywy preprocesora

Przed kompilacją tekst programu poddawany jest preprocessingowi. W wyniku działaniapreprocesora otrzymuje się zmodyfikowany tekst programu, który stanowi źródło dlakompilatora. Polecenia preprocesora są nazywane dyrektywami. Wiersze programurozpoczynające się znakiem '#' oznaczają dyrektywy preprocesora. Składnia dyrektywpreprocesora jest niezależna od składni reszty języka. Wiersze zawierające dyrektywypreprocesora mogą wystąpić w dowolnym miejscu w programie.

Oprócz wspomnianych wcześniej dyrektyw, preprocesor dokonuje pewnychstandardowych konwersji tekstu programu, np.:• Wszystkie wystąpienia znaków '\' (lewy ukośnik, backslash) i bezpośrednio po nim nowej

linii są usuwane - tzn. następny wiersz jest łączony z tym, w którym znajdował się znak '\'.• Tekst programu jest dzielony na symbole leksykalne i spacje, oraz usuwane są wszystkie

komentarze (komentarz jest zamieniany na pojedynczą spację).• Sekwencje specjalne w stałych znakowych i tekstowych są zastępowane ich

równoważnikami (np. znaki "\n" zamieniane są na znak o kodzie ASCII 13).• Sąsiednie stałe tekstowe łączone są w jedną stałą tekstową (tzn. napisy "Ala " "ma kota"

po preprocessingu zostaną połączone w jeden napis: "Ala ma kota").

Makrodefinicja - #define

Do tworzenia makrodefinicji służy dyrektywa #define o następującej składni:

#define identyfikator ciąg_symboli

lub

#define identyfikator(identyfikator, ..., identyfikator) ciąg_symboli

Instrukcja w pierwszej postaci zleca preprocesorowi zastępowanie dalszych wystąpieńidentyfikatora wskazanym ciągiem symboli. Spacje otaczające ciąg symboli są usuwane, np.w przypadku:

#define BOK 8...char txt[BOK][BOK];

deklaracja tablicy txt zostanie zamieniona w następujący sposób:

char txt[8][8];

Druga postać dyrektywy #define służy do definicji tzw. makra funkcyjnego. W tejdyrektywie pomiędzy identyfikatorem i nawiasem otwierającym ” (” nie może być spacji.

Dalsze wystąpienie pierwszego identyfikatora, po którym następuje nawias oraz ciągisymboli oddzielone przecinkami i zakończone nawiasem zamykającym sąmakrowywołaniami. Makrowywołanie zastępuje się ciągiem symboli podanym wmakrodefinicji. Spacje otaczające ciąg symboli są usuwane. W podanym ciągu każdewystąpienie identyfikatora z listy parametrów formalnych makrodefinicji (umieszczonego wnawiasach) zastępuje się symbolami reprezentującymi odpowiadający mu argument aktualnymakrowywołania. Liczba parametrów w makrodefinicji musi być taka sama jak liczbaargumentów w makrowywołaniu.

Page 19: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

18

Dla przykładu:

#define min(x, y) (((x) < (y)) ? (x) : (y))...a = min(i, j);

ostatnie przypisanie zostanie zastąpione przez:

a = (((i) < (j)) ? (i) : (j);

Przy definiowaniu makrodefinicji funkcyjnych należy wszystkie argumenty ujmować wnawiasy ponieważ makrodefinicje są rozwijane tekstowo przed kompilacją, co możespowodować nieoczekiwaną zmianę znaczenia pewnych zapisów, np. przypadku:

#define sqr(x) x*x...res = sqr(a+4);

przypisanie zostanie rozwinięte do postaci:

res = a+4*a+4;

pomimo tego, że oczekujemy:

res = (a+4)*(a+4);

Przyjęło się, że identyfikatory w makrodefinicjach są pisane dużymi literami.Po rozwinięciu makrowywołania preprocesor przegląda powstały w ten sposób tekst w

poszukiwaniu kolejnych identyfikatorów do rozwinięcia. Nie są jednak możliwe rozwinięciarekursywne. Nie jest również możliwe potraktowanie rozwiniętego tekstu jako nowejdyrektywy preprocesora.

Dyrektywa #undef

Dyrektywa #undef służy do unieważniania poprzedniej definicji makra.Jej składnia jest następująca:

#undef identyfikator

Dyrektywa #include

Dyrektywa #include służy do włączania pliku o podanej nazwie do tekstu źródłowegopoddawanego kompilacji.

Dyrektywa ta ma jedną z dwóch postaci:

#include <nazwa_pliku>

lub

#include ”nazwa_pliku”

W pierwszej postaci plik o podanej nazwie jest poszukiwany w katalogach zależnych odkompilatora. W drugiej postaci plik jest najpierw poszukiwany w katalogu aktualnym i byćmoże innych zdefiniowanych katalogach. Jeśli tam nie zostanie znaleziony to poszukiwaniejest kontynuowane tak samo jak w przypadku pierwszej postaci, czyli w katalogachsystemowych kompilatora.

1.1.21. Zastrzeżone słowa kluczowe

Niektóre identyfikatory zostały zastrzeżone przez twórców języka C. Służą one do zapisukonstrukcji jakie są dopuszczalne w tym języku. Dlatego nazywa się je słowami kluczowymi.Słowa kluczowe można podzielić na grupy:• instrukcje• typy danych i ich specyfikatory• specyfikatory rodzaju pamięci

Page 20: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

19

Do instrukcji zaliczane są następujące słowa kluczowe:• break - przerwij,• case - wariant,• continue - kontynuuj,• do - wykonuj,• else - jeśli nie to,• for - dla,• goto - idź do,

• if - jeśli,• return - zwróć,• switch - przełącz,• typedef - definiuj typ,• while - dopóki,• default - domyślna,• sizeof - wielkość

Poniżej zostały wymienione typy danych i ich specyfikatory:• char - znak,• double - podwójna,• enum - wyliczeniowa,• float - zmiennoprzecinkowa,• int - całkowita,• long - długa,• short - krótki,

• signed - ze znakiem,• struct - struktura,• union - unia,• unsigned - bez znaku,• void - nieokreślony,• const - stała,• volatile - ulotna,

Specyfikatory klas pamięci są następujące:• auto - automatyczna,• register - rejestrowa,• static - statyczna,• extern - zewnętrzne,

Należy zauważyć, że słowa kluczowe nie mogą być użyte jako nazwy zmiennych, typówlub funkcji i nie są poprawnymi identyfikatorami w sensie składni języka C.

1.1.22. Funkcja printf

Funkcja printf umożliwia formatowane wyprowadzanie danych: W tym celu analizujenajpierw przekazany jako pierwszy argument tekst, a następnie na podstawie informacjizawartych w tym tekście, wypisuje kolejne wartości. Wypisywanie wartości prowadzone jestna standardowe wyjście którym w przypadku mikrokontrolera 8051 jest zwykle portszeregowy. Liczba wyprowadzonych wartości musi być taka jak wynika z przekazanegoformatu. W szczególnym przypadku do funkcji printf może zostać przekazany tylko format.Tekst przekazywany jako format, składa się z tekstu, który zostanie wypisany tak jak zostałprzekazany oraz informacji o koniecznych konwersjach. Informacja o konwersji rozpoczynasię znakiem '%'. Każda informacja tego rodzaju odpowiada jednej wartości przekazanej jakokolejny argument. W wypisywanym tekście, kolejne wartości pojawiają się w miejscuodpowiednich konwersji '%'. Same znaki '%' nie są wypisywane. W przypadku, gdy chcemywypisać na ekranie znak '%' w podanym tekście należy wpisać "%%". W tabl. 7.11 pokazanowszystkie specyfikatory funkcji printf().

Tablica 7.11. Specyfikatory funkcji printf

Opis Typ operandu Typ%d,i Dziesiętna notacja int%ld długa liczba całkowita dziesiętna int%o ósemkowa bez znaku int%x,X szesnastkowa bez znaku int%u dziesiętna bez znaku unsigned int%c Znak int lub char%s Ciąg char[] char *%f Dziesiętna notacja double lub float%e,E Notacja naukowa double lub float%g,G Krótkie %e lub %f double lub float

Page 21: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

20

%p Wskaźnik void *%% Znak % n/a

Poniżej przedstawiono przykłady użycia funkcji printf():

printf("Dzisiaj jest wtorek!\n"); wynik: Dzisiaj jest wtorekprintf("120 %% 10 = 0\n"); wynik: 120 % 10 = 0

Przykłady specyfikatorów użycia funkcji printf():

%3d wyświetli 3 cyfry wyrównane do prawej%3.0f nie wyświetli przecinka i liczby po nim%3.1f wyświetli jedną cyfrę po przecinku%.1f wyświetli tylko cyfrę po przecinku

1.2. Implementacja języka C na mikroprocesor rodziny ‘51

1.2.1. Podział pamięci mikrokontrolera 8051

Mikrokontroler 8051 posiada kilka różnych obszarów pamięci zaczynających się od tegosamego adresu. Dostęp do tych segmentów pamięci możliwy jest różnymi technikami.

Poniżej na rys.7.2 pokazano podział obszaru pamięci mikrokontrolera 8051.

0x0000

0xFFFF

0xFF

Pamięć

programu

Zewnętrzna pamięć

danych

0x00

Sygnał

zewnetrzny PSEN

Sygnał zewnetrzny

RD WR

XDATACODE

PDATA

256b

PDATA

256b

PDATA

256b

Wewnetrzna

pamięć danych

0x00

0x1F

IDATA

DATA

SFR

0x7F

REG

0x2F

0x20BDATA

MOVC A,@DPTR MOVX A,@Ri

MOVX @Ri,A

MOVC A,@DPTR

MOVC @DPTR,A

MOV A,@Ri

MOV @Ri,A

MOV A,direct

MOV direct,A

MOV A,Rr

MOV Rr,A

Instrukcje

Adresowania

Bezpośredniego

Instrukcje

Adresowania

Rejestrowego

Instrukcje

Adresowania

Pośredniego

Rys. 7.2 Podział obszaru pamięci mikrokontrolera 8051

W celu zrozumienia zasad użycia poszczególnych rodzajów pamięci oraz modelikompilacji, należy przyjrzeć się bliżej podziałowi pamięci w mikrokontrolerze 8051.

Od adresu 0x00, do adresu 0xFF, rozciąga się obszar pamięci wewnętrznej RAM o nazwieIDATA, która może być adresowana wyłącznie pośrednio, tzn. przy wykorzystaniu adresówzawartych w rejestrach R0 i R1 z aktualnie wybranego banku. Do tego są wykorzystywaneinstrukcje asemblera: MOV A,@Ri oraz MOV @Ri,A. Obszar wewnętrznej pamięci danychmoże być zaadresowany w inny sposób (bezpośrednio), ale jest on wtedy kompilatorze językaC traktuje go jako dwa niezależne obszary o nazwach DATA i SFR. Przestrzeń o nazwieDATA zawierająca dane użytkownika leży pomiędzy adresami 0x00 a 0x7Fi jest onadresowany bezpośrednio rozkazami MOV A,direct oraz MOV direct,A, gdzie directoznacza adres leżący wewnątrz wewnętrznego rozpatrywanego obszaru pamięci. Główneprzeznaczenie tego segmentu pamięci to przechowywanie zmiennych wykorzystywanychprzez program w czasie pracy. Od adresu 0x80 do 0xFF umieszczony został rejestr funkcjispecjalnych (SFR) mikrokontrolera, który może być adresowany bezpośrednio. W obrębieobszaru (segmentu) DATA znajdują się obszary o nazwach BDATA i REG. Obszar BDATA

Page 22: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

21

to szesnaście bajtów (128 bitów) zajmujących przestrzeń adresową od 0x20 do 0x2F wobszarze adresowania bezpośredniego. Specjalną cechę tego obszaru stanowi fakt, że opróczinstrukcji MOV mają tutaj zastosowanie instrukcje operujące na pojedynczych bitach (SETBB_ADRES, gdzie B_ADRES to adres bitu) i wykorzystujące specjalny tryb adresowaniapojedynczych bitów (warto zaznaczyć że obszar SFR jest również obszarem dostępnymbitowo). Kolejnym obszarem pamięci mikrokontrolera jest obszar REG składający się z 4banków po 8 rejestrów (R0-R7) zajmujący przestrzeń adresowa od adresu 0x00 do 0x1F. Jeston dostępny przez adresowanie rejestrowe wykorzystując instrukcje asemblera MOV A,Rroraz MOV Rr,A (gdzie Rr to rejestry R0–R7). Pozostałe obszary danych kompilatora językaC dotyczą pamięci zewnętrznych, do których adres liczy 16 bitów. Pierwszym z takichsegmentów jest segment o nazwie CODE. Przeznaczony na pamięć programu. Obszar tenzajmuje adresy od 0x0000 do 0xFFFF (65536 bajtów). Segment pamięci programu dostępnyjest przez instrukcje wykorzystujące do adresowania licznik rozkazów PC oraz 16-bitowyrejestr DPTR. W segmencie CODE poza instrukcjami programu mogą być przechowywanedane, ale o wyłącznie stałych wartościach takie, jak tablice współczynników, stałe itp. Obszarten dostępny jest przy wykorzystaniu instrukcji asemblera MOVC A,@DPTR. Kolejnymobszarem danych jest obszar zewnętrznej pamięci danych nazywany XDATA lub XRAM.Zaczyna się on od adresu 0x0000 i kończy pod adresem 0xFFFF. Dostępny jest przywykorzystaniu instrukcji asemblera MOVX A,@DPTR oraz MOVX @DPTR,A. Ten samobszar zewnętrznej pamięci danych może być adresowany przy wykorzystaniu dwu innychinstrukcji : MOVX A,@Ri oraz MOVX @Ri,A, gdzie Ri to R0 lub R1. Wtedy jednak wjęzyku C nazywany jest on PDATA. W takim przypadku rejestr Ri wskazuje 8 bitowa dolnączęść 16 bitowego adresu, podczas gdy górna cześć (8 bitów) jest wskazywana przezzawartość rejestru P2. Z tego powodu adresowanie to można nazwać stronicowym, ponieważw rejestrze P2 umieszczony jest numer strony pamięci, a w rejestrze Ri jedynie 8 bitowyadres danej znajdującej się na wskazanej stronie.

Uwaga: omawiając przestrzeń adresową pamięci CODE czy XDATA opisano możliwośćjej fizycznego rozszerzenia a nie przymus zajmowania całego dostępnego obszaru przezdane urządzenie podłączone w tej przestrzeni adresowej.

Zewnętrzna pamięć ROM (segment CODE) jest sterowana sygnałem odczytu PSEN(Program Store Enable). Zmiana poziomu tego sygnału na niski uaktywnia pamięć programu.

Dostępem do obszaru XDATA sterują zewnętrzne sygnały RD (odczyt) i WR (zapis), którepozycjonują w czasie odczyt lub zapis danych.

Reasumując kompilator C używa następujących adresowanych obszarów pamięcioznaczonych kolejno:

00-Data, 01-Idata, 02-Xdata, 03-Pdata, 04-Bdata, 05-Code

• DATA – bezpośrednio adresowany obszar wewnętrznej pamięci RAM (128 bajtów),• IDATA – pośrednio adresowany obszar wewnętrznej pamięci RAM mikrokontrolera (128

lub 256 bajtów),• XDATA – zewnętrzna pamięć danych, adres dostępu 16 bitowy (64kB),• PDATA – tak samo, jak XDATA z tym, że adres dostępu do pamięci zewnętrznej jest 8

bitowy,• BDATA – obszar pamięci RAM, w którym możliwe jest adresowanie pojedynczych bitów

rejestrów specjalnych SFR, na przykład sbit OV = PSW^2,• CODE – pamięć programu; może być albo wewnętrzny, albo zewnętrzny ROM

mikrokontrolera,• SFR – obszar rejestrów specjalnych położony w pamięci RAM,• SBIT – obszar pojedynczego bitu położony w obszarze bitowym wewnętrznej pamięci

RAM.

Page 23: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

22

Wyżej wymienione słowa kluczowe języka C noszą nazwę kwalifikatorów obszarupamięci.

1.2.2. Modele kompilacji

Język C opracowany przez firmę Keil dla mikrokontrolera 8051 umożliwia dokonaniekompilacji dostosowującej wyjściowy kod maszynowy do 3 różnych modeli pamięci.Krótkiego wyjaśnienia wymaga sam problem modeli pamięci. Rolą każdego kompilatorajęzyka programowania tak zwanego wysokiego poziomu, jest przetłumaczenie koduprogramu z postaci zrozumiałej dla człowieka, do postaci zrozumiałej dla mikroprocesora,czyli w uproszczeniu z postaci języka C do kodu maszynowego. Niektóre rozkazy asembleradla mikrokontrolera 8051 (który jest językiem najbardziej zbliżonym do kodu maszynowego)o zbliżonym działaniu, zajmują różne wielkości pamięci. Na przykład rozkazy skoków mogązajmować w pamięci 2 lub 3 bajty (AJMP i LJMP). Podobnie z rozkazami wywołaniapodprogramów LCALL i ACALL. Rozkazy 2-bajtowe wykorzystywane są wówczas, gdy adresdocelowy znajduje się w obrębie tego samego 2kB bloku pamięci programu, natomiast 3-bajtowe – gdy leży w obrębie 64kB. Można stąd wysnuć wniosek, że jeśli pamięć jest mała,to rozkazy skoków mogą być krótsze, co pozwala zmniejszyć wielkość programuwynikowego. Dodatkowo mikrokontroler może wykorzystywać do przechowywaniazmiennych obszar pamięci wewnętrznej oraz zewnętrznej. W przypadku wykorzystywaniapamięci wewnętrznej dostęp do zmiennych jest szybki a kod potrzebny do zapisu lub odczytudanej mały. Tego rodzaju rozumowanie leży u podstaw stworzenia różnych modeli kompilacjii różnych modeli pamięci. Dzięki nim kompilator „orientuje się” jaki kod tworzyć, w jakisposób go optymalizować, gdzie umieszczać zmienne globalne i lokalne. Pisząc program dlamikrokontrolera 8051 pierwszą decyzją, którą trzeba podjąć jest decyzja dotycząca wyborumodelu pamięci.

Kompilator języka C firmy Keil umożliwia wybór trzech modeli pamięci: Small, Compact,Large. W modelu SMALL pamięć RAM służąca do przechowywania zmiennych ma jedynie128 bajtów umieszczonych w obszarze pamięci mikrokontrolera, dostępnych jako obszarIDATA. Używając modelu SMALL, należy więc zredukować do minimum liczbę zmiennychglobalnych używanych w programie. Pozwoli to programowi linkera na kompilowaniefunkcji w taki sposób, aby aplikacja pracowała efektywnie. Model SMALL można takżestosować przy kompilacji nawet bardzo dużych programów, umieszczając obiekty duże itakie, do których nie jest wymagany bardzo szybki dostęp, w zewnętrznej pamięci RAM. Tenmodel najlepszy jest również dla aplikacji o krytycznym czasie wykonywania, jako żegwarantuje on najszybszy dostęp do zmiennych i parametrów przez funkcje, podczas gdyduże obszary danych mogą zostać umieszczone poza układem mikrokontrolera.

W modelu COMPACT kompilator przygotowuje kod programu w taki sposób aby doprzechowywania zmiennych oprócz 128 bajtów pamięci wewnętrznej RAMwykorzystywanych było 256 bajtów zewnętrznej pamięci RAM dostępnej jako obszarPDATA. COMPACT to model pamięci dostosowany do programów, gdzie dla przykładuwewnętrzny RAM mikrokontrolera przeznaczony jest na zmienne systemu operacyjnego.Model ten jest rzadko używany dla całego programu. Najbardziej użyteczna kombinacja tojego połączenie z modelem SMALL używanym lokalnie dla procedur obsługi przerwań.COMPACT stosuje się przede wszystkim do programów zawierających dużą liczbęzmiennych, które nie wymagają krótkiego czasu dostępu, ponieważ odwołanie się dozmiennych odbywa za pomocą instrukcji MOVX A,@Ri lub MOVX @Ri,A wykorzystującejtryb adresowania pośredniego przy pomocy rejestru R0 lub R1. COMPACT może być równieżbardzo użyteczny dla aplikacji wymagających stosu o dużym rozmiarze, co może oznaczaćkonieczność umieszczenia go w zewnętrznej pamięci RAM.

W modelu LARGE kompilator umożliwia dostęp do całej zewnętrznej pamięci RAM(64kB). Poza tym w dalszym ciągu można wykorzystywać 128 bajtów pamięci wewnętrznejmikrokontrolera. Model LARGE pozwala na niezbyt szybki dostęp do bardzo dużego obszaru

Page 24: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

23

pamięci RAM. Dostęp do tej pamięci odbywa się za pomocą instrukcji MOVX @DPTR,A lubMOVX A,@DPTR. Podobnie jak poprzednio, niezbyt często używa się go w odosobnieniu –raczej w połączeniu z modelem SMALL. Należy pamiętać, że niezależnie od wybranegomodelu pamięci użytkownik ma możliwość bezpośredniego przydziału zmiennych do różnychobszarów pamięci wymuszając ich przypisanie. Przykładowe sposoby wymuszaniaprzypisania zmiennych do obszarów pamięci pokazano poniżej:

data int x; //umieść zmienna i w obszarze dataidata int x,y; //umieść zmienne x oraz y w obszarze idataxdata floata x; //umieść zmienna x w obszarze xdatacodeint con; //umieść zmienna con w obszarze codepdata int x; //umieść zmienna x w obszarze stronicowanym przez port //P, a dane w zakresie 0...255 bajtów na stronie //wskazanej przez P2bdata char y; // umieść zmienna y w obszarze adresowanym bitowo

1.2.3. Porty mikrokontrolera

Korzystając z portów wejścia wyjścia mikrokontrolera w programach napisanych w językuC, należy kierować się tymi samymi zasadami, co w języku asembler, co oznacza, że porty,które wymagają ustawienia w stan wysoki przed odczytem z nich danych, muszą być w tenstan ustawione. Mając to na uwadze, korzystanie z portów jest bardzo proste. Można testowaćstany bitów, przypisywać zmienne i stałe, wykonywać różne inne operacje. Podobnie jak wasemblerze, jeśli operacja wymaga zmian stanu portu (przesunięć bitów i podobnych), lepiejjest utworzyć zmienną będącą kopią stanu portu i na niej wykonywać działania. Potemwystarczy tylko przypisać do danego portu stan zmiennej. W ten sposób można uniknąćzakłóceń mogących się pojawić na wyprowadzeniach portu, w momencie bezpośredniowykonywania na nim działań. Poniżej przedstawiono przykładowy program wykonujący tegorodzaju zmianę stanu portu P1.

zmienna = P1 //(0..3 – w zależności od mikrokontrolera),P1 = P1 | 0xFF; //gdy port pracuje jako wejściowy, dobrze jest jego bity //ustawić na „1”P1 = 0xAA; // numer portu zależny od aplikacjiP1 = P1 | 0x01; // ustawienie bitu P1.0P1 = P1 & 0xFE; // wyzerowanie bitu P1.0P1^0 = 1; // odpowiednik rozkazu SETB P1.0P1^0 = 0; // odpowiednik rozkazu CLR P1.0P1 = P1 | 0x01 // ustawienie P1.0 na „1”if (P1^0 = 1 .... // jeden ze sposobów testowania stan bitu P1.0

1.2.4. Przerwania

Słowo kluczowe interrupt powoduje, że funkcja traktowana jest przez kompilator jakoobsługująca przerwanie. Przy jej definiowaniu wymagana jest znajomość numeru przerwania– kolejności w tablicy wektorów przerwań. Na podstawie tego kompilator wylicza adresobsługi. Odpowiedni wektor przerwania obliczany jest jako 3 + (numer przerwania x 8).Wartości 3 i 8 są przyjmowane jako domyślne dla rodziny 8051. Poniżej pokazano fragmentprogramu zawierający przykładową definicję obsługi przerwania generowanego przez Timer0.

void Przerwanie_Timera0 (void) interrupt 1:{TR0 = 0; // zatrzymanie timera 0TH0 = 0; // odświeżenie zawarto ś ci rejestrówTL0 = 0x1F;licznik++; // zwiększenie zmiennej licznik o 1TR0 = 1; // ponowne uruchomienie timera 0}

Page 25: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

24

Funkcja, która wykonywana jest po stanie RESET procesora nosi nazwę main i na niązawsze wskazuje wektor przerwania o numerze 0. Treść tej funkcji to program główny.Kompilator sam dba o to, aby wektor przerwania numer 0 zawsze wskazywał na miejsce wpamięci programu, gdzie umieszczony jest kod wynikowy funkcji main.

Jaki skutek dla funkcji z przykładu ma umieszczenie słowa kluczowego interrupt? Popierwsze instrukcja „LJMP Przerwanie_Timera0” umieszczana jest w tablicy wektorówprzerwań pod adresem 0BH. Po drugie, w przypadku wywołania tej funkcji, przedwykonaniem pierwszej znajdującej się instrukcji na stos odkładane są zawartości rejestrów A,B, PSW, DPH, DPL. Po trzecie, po odłożeniu danych następuje wykonanie instrukcjizawartych w ciele funkcji. Realizowane jest to przez skok pod wspomniany adres obsługiprzerwania leżący w obszarze CODE wskazywany przez nazwę funkcji (w tym przypadkuprzerwanie od Timera0). Z tego względu deklarując podprogram przerwania musimypoinformować kompilator że podprogram jest typu interrupt i że zaczyna się od określonegomiejsca w pamięci, miejsce w pamięci zostanie określone dzięki zadeklarowaniu źródłaprzerwania.

Poniżej w tabl. 7.12 pokazano wszystkie źródła przerwań mikrokontrolera 8051 wraz z ichnazwami w języku C oraz adresami obsługi.

Tablica 7.12. Źródła przerwań w mikrokontrolerze 8051

Źródło Nazwa przerwania w języku C Adres obsługi przerwaniaIT0 Interrupt 0 0x0003Timer T0 Interrupt 1 0x000BIT1 Interrupt 2 0x0013Timer T1 Interrupt 3 0x001BSIO Interrupt 4 0x0023

1.3. Podstawy posługiwania się pakietem Keil C-51

Pakiet µVision2 firmy Keil Elektronik Gmbh to zbiór narzędzi umożliwiających pisanie iuruchamianie programów w języku C i asemblera dla mikrokontrolerów rodziny ’51.

Składa się on z wielu programów narzędziowych w tym między innymi:• C51 Optimizing C Cross Compiler – kompilator języka C,• A51 Macro Assembler- asembler,• 8051 Utilities (linker, object file converter, library manager) – zbiór programów

dodatkowych w tym: linker łączący plik wynikowy asemblera z bibliotekami orazkonwerter tak powstałego pliku na kod wynikowy w formacie HEX.

• dScope for Windows™ Source-Level Debugger/Simulator- program symulatoramikrokontrolera 8051,

Keil C51 jest kompilatorem języka C dla procesorów rodziny 8051 zgodnych zespecyfikacją ANSIC. W skład µVision 2 wchodzi edytor tekstu umożliwiający pisanieprogramu z wcięciami tekstu zgodnie ze standardami przyjętymi dla języka C. Kod źródłowyprogramu jest wyświetlany w różnych kolorach, co pozwala na wyróżnienie słów kluczowychod opisu oraz od pozostałej części programu. Program dla mikrokontrolera nie różni sięzasadniczo od zwykłego programu w języku C, co umożliwia przy znajomości języka orazwiedzy o budowie mikrokontrolera pisanie programów. Pakiet µVision 2 firmy Keil Gmbhznacznie ułatwia prace programisty i umożliwia przeprowadzenie dokładnej analizyprogramu. Wersję demonstracyjna pakietu dostępna jest na stronie internetowej producentawww.keil.com.

1.3.1. Instalacja i uruchomienie pakietu

Pakiet programów zainstaluje się automatycznie. Po zainstalowaniu jest gotowy do pracybez żadnych dodatkowych ustawień, czy też restartowania komputera. Aby łatwiej czytaćpewne informacje zalecane jest ustawienie rozdzielczości ekranu na 800x600. Przypierwszym uruchomieniu widoczne jest tylko menu główne które zostało pokazane na rys.7.3.

Page 26: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

25

Rys. 7.3. Widok okna głównego

Okno główne programu zostało podzielone na trzy mniejsze okna:• Okno projektu - służy do zarządzania projektem,• Okno edytora - służy do wpisywania programu,• Okno wyjściowe - służy do odczytywania komunikatów kompilatora.

Z poziomu okna głównego widoczne są paski narzędziowe pozwalające na szybki dostępdo wybranych, kluczowych opcji programu. Pasek edytora również widoczny w okniegłównym ma formę przejętą z klasycznych edytorów systemu Windows. Pozostałe paskinarzędziowe zawierają funkcje charakterystyczne dla programu kompilatora.

1.3.2. Korzystanie z pakietu

Korzystanie z pakietu Keil należy rozpocząć od jego uruchomienia, czyli uruchomieniapliku o nazwie Uv2.exe znajdującego się zwykle w katalogu \...\keil\UV2\Uv2.exe.

Po jego uruchomieniu pojawi się menu główne pokazane na rys.7.3. Do napisaniapierwszego programu w języku C należy wybrać z menu głównego opcję Project >New

Project, wskazać katalog docelowy dla plików danego projektu oraz wpisać nazwęutworzonego projektu. Po wykonaniu tych czynności pokaże się okno wyborumikrokontrolera pokazane na rys. 7.4. Wyboru mikrokontrolera dokonuje się na podstawieznajomości producenta oraz typu. Niezwykle przyjaznym i pomocnym elementem tej opcji sąopisy pojawiające się po zaznaczeniu wybranego mikrokontrolera. Zawierają onepodstawowe informacje dotyczące budowy wewnętrznej mikrokontrolera. Każdy utworzonyprojekt jest obiektem, dla którego indywidualnie można określić właściwości. Późniejszeotwarcie zapamiętanego projektu powoduje przywrócenie cech środowiska, dla któregoprogram został napisany.

Page 27: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

26

Rys. 7.4. Wybór mikrokontrolera

W celu rozpoczęcia pisania programu w edytorze pakietu Keil C51 wystarczy wybrać zmenu File opcje New File lub też z paska narzędziowego edytora pokazanego na rys. 7.5wybrać ikonę New File (Nowy plik). Co pozwala na otwarcie nowego pliku w edytorze izapisanie tam tworzonego programu. Zapisując plik otwarty w edytorze zawierający programnależy pamiętać o zapisaniu go z rozszerzeniem *.c co pozwoli na automatyczne rozpoznanietego pliku przez edytor, jako pliku zawierającego program w języku C. W takim przypadkuużyte zostaną opcje wyświetlania tekstowej zawartości pliku z wyróżnieniem podstawowychelementów programu takich jak: słowa kluczowe, instrukcje, komentarze, nazwy plików itd.

Rys. 7.5. Widok paska narzędziowego edytora

Utworzenie nowego pliku i zapamiętanie go na dysku nie powoduje dodania go doprojektu. Aby dodać plik do projektu należy posłużyć się poleceniem z menu głównegowywołanym w następujący sposób: opcja Project> Targets, Groups, Files.. wtedy na ekraniepojawi się okno dialogowe pokazane na rys. 7.6.

Page 28: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

27

Rys. 7.6. Dodawanie plików do projektu Rys. 7.7. Ikony kompilacji i opcji projektu

Po wybraniu zakładki Groups/Add Files w oknie o nazwie Available Groups należywskazać grupę, do której należy przyłączyć plik. Jeżeli opcje środowiska nie były zmieniane,to jedyną grupą do wyboru będzie grupa o nazwie Source Group. Po wskazaniu grupy należyużyć przycisku: Add Files to Group w celu wywołania okna wyboru plików. Po dodaniu plikumożliwe jest już kompilowanie tak przygotowanego projektu.

Dla użytkownika pakietu DSM-51 ważne jest by kod wyjściowy programu zapisany był wpliku wyjściowym o formacie *.hex, ustawienie tego formatu pliku można wykonaćnaciskając na pasku narzędziowym ikonę Opcje Projektu pokazana na rys. 7.7.

Na rys. 7.8 pokazano okno pojawiające się po kliknięciu wspomnianej ikony. W tym oknienależy wybrać zakładkę Output i w niej zaznaczyć opcje o nazwie Create HEX File orazwybrać HEX-80.

Page 29: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

28

Rys. 7.8. Zakładka „Output” okna Options for Target (opcje projektu)

Ważną opcją z punktu widzenia analizy utworzonego kodu, jest możliwość podglądu plikuzawierającego listing kodu powstającego w wyniku kompilacji kodu źródłowego do zapisu wjęzyku asembler. Można tego dokonać wybierając w tej samej Opcji Projektu zakładkę„Listing”. Wygląd pojawiającego się w tym przypadku okna pokazano na rys.7.9.

Rys. 7.9. Zakładka „Listing” okna Options for Target

Tak przygotowany kompilator umożliwia przygotowanie i analizę programu na poziomiewystarczającym dla celów edukacyjnych. W celu zapoznania się z pozostałymi funkcjaminależy zapoznać się z podręcznikiem użytkownika, który jest dołączony do kompilatora i

Page 30: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

29

dostępny z menu „Help”. Wywołanie kompilacji projektu odbywa się przy pomocy ikony„kompilacja” pokazanej na rys. 7.7.

1.4. System DSM –51

Nauka programowania mikrokontrolerów bez możliwości faktycznego uruchomienianapisanych programów i obserwacji ich działania jest niezwykle trudna. Obserwując działanienawet najprostszego programu na programowym symulatorze mikroprocesora nie można wpełni zaobserwować jakie tak naprawdę będą efekty działania programu na rzeczywiściedziałającym systemie. Aby w pełni ocenić działanie programu i mikrokontrolera koniecznyjest kontakt z realnym działającym systemem. Ze względu na edukacyjne przeznaczeniemodelu system DSM-51 jest zabezpieczony przed przypadkowymi uszkodzeniami od górypłytką pleksi. Pozwala to również na zobaczenie elementów urządzenia co jest szczególniecenne w przypadku urządzenia edukacyjnego. Rolę takiego systemu może pełnić urządzenieDSM-51 którego wygląd pokazano na rys.7.10. DSM-51 jest uniwersalnym sterownikiemrozbudowanym o szereg elementów zewnętrznych, które są zarówno układami komunikacji zużytkownikiem, jak i układów dodatkowych np.: przetwornika A/C.

Rys 7.10. Widok płyty czołowej DSM-51

DSM-51 umożliwia między innymi zapoznanie się z działaniem, metodamiprogramowania różnych elementów mikroprocesorowych w tym:• wyświetlacza 7-segmentowego wymagającego sekwencyjnego sterowania• wyświetlacza ciekłokrystalicznego sterowanego przez wbudowany sterownik,• klawiatury przeglądanej sekwencyjnie• klawiatury matrycowej odczytywanej równolegle,• wej/wyj cyfrowych sterowanych bezpośrednio przez porty mikrokontrolera oraz linii

obsługiwanych przez układ 8255,• łącza szeregowego RS232 sterowanego sprzętowo przez 8051 oraz łącza obsługiwanego

programowo.System jest wyposażony w szereg złącz służących do podłączenia urządzeń zewnętrznych

takich jak:

Page 31: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

30

• wej/wyj cyfrowych,• wej/wyj analogowych,• wej/wyj izolowanych galwanicznie,• dwu kanałów RS232,• Ma również wyprowadzona na złącze szynę systemową (sygnały magistral: danych,

adresów, sygnałów sterujących).Złącza te umożliwiają sterowanie modelami różnych urządzeń, komunikowanie się z

innymi systemami mikroprocesorowymi i komputerami, rozbudowę systemu (złącze szynysystemowej). Dydaktyczny System Mikroprocesorowy DSM-51 umożliwia wykonywaniezadań o różnorodnym poziomie trudności: od krótkich programów obsługujących diodęświecącą, poprzez obsługę wyświetlaczy i klawiatur, aż do złożonych programów, sterującychmodele rzeczywistych urządzeń. System jest w całości przykryty przeźroczystą płytka,wykonaną z pleksi, co zabezpiecza go przed przypadkowym uszkodzeniem orazniepożądanymi manipulacjami ze strony "dociekliwych" uczniów, umożliwiając jednocześnieswobodną obserwację elementów systemu. Umieszczenie wszystkich układów scalonych wpodstawkach ułatwia natomiast wymianę układu w przypadku jego uszkodzenia.

W skład systemu DSM-51 wchodzi:• mikrokontroler 80C51 (zegar 11.059 MHz),• układ watchdog,• układ RAM 32 kB,• układ EPROM 32kB,• dekoder adresów – układ GAL16V8,• sterownik przerwań – układ GAL16V8,• sygnalizatory: LED, buzzer,• wyświetlacz LED (6 cyfr),• wyświetlacz LCD (2 x 16),• klawiatura przeglądana sekwencyjnie – 6 klawiszy,• klawiatura matrycowa - 2 x 8 klawiszy,• łącze RS232 sterowane z wewnętrznego układu UART z mikrokontrolera 8051,• dodatkowe łącze RS232 sterowane programowo• 24 linie we/wy cyfrowych zgrupowane w układzie 8255,• 2 linie wejść cyfrowych izolowanych galwanicznie,• 2 linie wyjść cyfrowych izolowanych galwanicznie,• 8 linii wejść analogowych,• 1 linia wyjścia analogowego,• buforowana szyna systemowa.

1.4.1. Mikrokontroler 8051, pamięć RAM, pamięć EPROM, dekoder adresów

Schemat sterownika DSM-51 pokazano na rys.4.2. Jako główny element sterujący wsystemie DSM-51 zastosowany został mikrokontroler rodziny ’51 w wersji pozbawionejpamięci ROM (8031). Budowa oraz działanie mikrokontrolera omówione zostało w rozdziale3 niniejszej pracy. Mikrokontrolery z rodziny ‘51 komunikują się z elementamizewnętrznymi przy pomocy szyny systemowej. W szynie systemowej mikrokontrolera możnawyodrębnić następujące części składowe:• szyna adresowa - 16 linii oznaczonych jako A0 do A15. Na tę szynę podawany jest

adres. Pod każdym adresem może znajdować się komórka pamięci lub jeden 8 bitowyport we/wy. Ustawienie adresu polega na ustawieniu 0 lub 1 na poszczególnej liniiadresowej. Maksymalnie można w ten sposób zaadresować 65 536 komórek.(64kB).

• szyna danych - 8 linii oznaczonych jako D0 do D7. Po szynie danych przesyłana jestzawartość komórki pamięci lub portu. Szyna danych jest dwukierunkowa umożliwiaprzesyłanie danych z i do mikrokontrolera. Przesyłanie danych to ustawianie

Page 32: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

31

poszczególnych linii danych w stan 0 lub 1, przez urządzenie zewnętrzne (odczyt) lubprzez mikrokontroler (zapis).

• szyna sterująca - składa się z trzech linii sterujących przesyłaniem danych (wmikrokontrolerze 8051). Są to linie:• PSEN - odczyt pamięci programu,• RD - odczyt pamięci danych,• WR - zapis pamięci danych,Do szyny systemowej podłącza się zarówno urządzenia we/wy jak i pamięć programu i

pamięć danych. W pamięci programu umieszczony jest program główny systemu jest topamięć EPROM 27C256 (U3). W czasie pracy mikrokontroler 8051 pobiera z pamięciprogramu kolejne rozkazy i je realizuje. Ponieważ ta pamięć jest tylko odczytywana do jejobsługi przewidziano tylko jedna linie PSEN. Pamięć danych służy do przechowywaniainformacji niezbędnych w trakcie wykonywania programu. Mikrokontroler 8051 posiadawewnętrzną pamięć RAM. W pewnych przypadkach konieczne jest zwiększenia pamięciRAM, można wtedy podłączyć do szyny systemowej zewnętrzna pamięć RAM 62256 (U4)(pamięć która jest zapisywana i odczytywana), do jej obsługi przewidziano dwie liniesterujące RD (odczyt pamięci danych ) i WR (zapis pamięci danych). Ponieważ do szynysystemowej podłączonych może być kilka układów pamięci i wiele portów we/wy, układy tesą wyposażone w wejście wyboru układu. Wejście to jest oznaczone jako CS (Chip Select)Zapis do pamięci następuje przy jednoczesnym wystąpieniu sygnałów CS i WR a odczyt przysygnałach CS i RD.

Do rozdzielenia sygnałów CS służą układy dekoderów adresów Mają one za zadaniewystawić sygnał CS tylko do jednego układu, uzależnionego od wysłanego przezmikrokontroler adresu. W systemie DSM-51 konieczne było umożliwienie zapisu do pamięciprogramu przesłanego z komputera kodu (programu) i uruchomienie go. Posłużył do tegodekoder adresów.

Dekoder adresów został zbudowany w oparciu o układ GAL 16V8 (U6), który jest matrycąlogiczną składająca się z wielu bramek. Wzajemne połączenia wewnętrzne pomiędzybramkami dokonywane są na drodze programowania układu GAL. Dekoder adresów wsystemie DSM 51 może pracować w jednym z dwu trybów:• TRYB0 - W tym trybie w zewnętrznym obszarze pamięci programu znajduje się układ

pamięci EPROM. Kod programu w tym trybie jest czytany z pamięci EPROM. Wobszarze zewnętrznej pamięci danych znajduje się układ pamięci RAM (32kB). Zapisdanych do obszaru zewnętrznej pamięci danych powoduje ich wpisanie do pamięci RAM

• TRYB1 - W tym trybie w obszarze zewnętrznej pamięci programu znajduje się pamięćRAM. Kod programu jest czytany w tym trybie z pamięci RAM. Jedynie obszarzewnętrznej pamięci programu o adresie powyżej 0x8000 jest czytany z pamięci EPROM.

Dzięki takiej pracy dekodera adresów w trybie 0 możliwy jest zapis kodu programu zkomputera PC przez łącze szeregowe RS232 do mikrokontrolera i dalej do pamięci RAM (wtym przypadku program obsługi łącza szeregowego, zapisu do pamięci RAM itp. Znajdują sięw obszarze 0x0000...0x8000 układu EPROM). Pozostałe układy systemu DSM-51 są bezwzględu na tryb pracy dekodera adresów umieszczone pod tymi samymi adresami w obszarzezewnętrznej pamięci danych.

Zostało to zrealizowane przez doprowadzenie do dekodera adresów sygnałów RD i PSEN ina ich podstawie oraz na podstawie linii adresowych wygenerowanie sygnałów sterującychdla układów pamięci:• CSE - wybór i odczyt pamięci EPROM• CSR - wybór pamięci RAM• RDR - odczyt pamięci RAM

Sygnał PSEN (odczyt pamięci programu) trafia do pamięci EPROM lub RAM zależnie odadresu i trybu pracy dekodera.

Page 33: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

32

W tabl. 7.13 pokazano wszystkie te układy wraz z ich adresami opisem oraz adnotacjapokazująca jakiego rodzaju operacje (zapis /odczyt) jest możliwa w ich przypadku.

Tablica 7.13. Urządzenia we/wy DSM-51 oraz ich adresy w pamięci

Adres Adres hex SymbolMożliweoperacje

Urządzenie

0000 0xxx B 00 H CSIC WR Sterownik przerwań0000 1xxx B 08 H CSDA WR Przetwornik C/A0001 0xxx B 10 H CSAD RD/WR Przetwornik A/C0001 1xxx B 18 H CSMX RD Multiplekser analogowy0010 0x01 B 21 H CSKB0 WR Klawiatura matrycowa: klawisze od 0 do 70010 0x10 B 22 H CSKB1 WR Klawiatura matrycowa: klawisze od 8 do ...0010 1x00 B 28 H CS55A RD/WR Układ 8255 – rejestr portu A0010 1x01 B 29 H CS55B RD/WR Układ 8255 – rejestr portu B0010 1x10 B 2A H CS55C RD/WR Układ 8255 – rejestr portu C0010 1x11 B 2B H CS55D RD/WR Układ 8255 – rejestr sterujący0011 0xxx B 30 H CSDS WR Bufor wyboru wskaźnika 7-segmentowego0011 1xxx B 38 H CSDB WR Bufor danych wskaźnika 7-segmentowego01xx xxxx B 40 H CSMOD RD/WR Tryb dekodera adresów10xx xx00 B 80 H LCDWC WR HD44780 – wpis rozkazów10xx xx01 B 81 H LCDWD WR HD44780 – wpis danych10xx xx10 B 82 H LCDRC RD HD44780 – odczyt stanu10xx xx11 B 83 H LCDRD RD HD44780 – odczyt danych11xx xxxx B C0 H CSX RD\WR Zewnętrzna magistrala systemowa

1.4.2. Sygnalizatory Led i Buzzer

Najprostszymi urządzeniami jakimi można sterować z mikrokontrolera są sygnalizatorydwustanowe. Bezpośrednio pokazują one stan linii wyjściowej mikrokontrolera. SystemDSM-51 został wyposażony w dwa sygnalizatory:• Optyczny - dioda LED podłączona do linii 7 portu P1 (bit 7 rejestru P1) - pin 8

mikrokontrolera 8051• Dźwiękowy - brzęczyk (buzzer) podłączony do linii 5 portu P1 (bit 5 rejestru P1) –

pin 6 mikrokontrolera 8051.Sposób ich podłączenia do portu P1 mikrokontrolera 8051 został pokazany na rys.7.11.

Urządzenia te działają (dioda led jest w stanie zapalonym, brzęczyk emituje dźwięk) gdystany linii do których zostały podłączone są niskie.

Rys. 7.11 Schemat podłączenia sygnalizatorów LED i BUZZER do mikrokontrolera 8051

Sygnał TTL pojawiający się np. na linii 5 portu P1 jest podawany na wejście inwerteraHC14, który przez rezystor steruje diodą LED. Wysoki poziom 5V pojawiający się na linii 5portu P1 wymusza pojawienie się niskiego stanu na wyjściu bramki, co powoduje że przezdiodę nie płynie prąd i w związku z tym dioda ta nie świeci. W odwrotnym przypadku gdy na

Page 34: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

33

linii 5 portu P1 pojawi się stan 0V, to na wyjściu bramki pojawi się napięcie 5V wymuszająceprzepływ prądu przez diodę LED. Rezystor R2 będzie w tym przypadku pełnił rolęogranicznika prądu płynącego przez diodę. W podobny sposób działa obwód sterujący pracąsygnalizatorem akustycznym.

1.4.3. Wyświetlacz LED i klawiatura przeglądana sekwencyjnie

System DSM-51 został wyposażony w 7-segmentowy wyświetlacz LED oraz klawiaturęprzeglądana sekwencyjnie. Schemat podłączenia tych elementów pokazany został w formieblokowej na rys. 7.12, a w postaci pełnego schematu elektrycznego na rys.7.13.

Rys. 7.12 Sterowanie wyświetlaczem 7-segmentowym

Wyświetlacz 7-segmentowy LED składa się 6 modułów wskaźników 7-segmentowychD350PA (W1 do W6). Każdy z tych modułów to 8 diod LED przy pomocy których możnaprzedstawić dowolna cyfrę. Wyświetlacz 7 segmentowy sterowny jest przez dwa bufory,bufor wyboru wskaźnika sterowany sygnałem CSDS oraz bufor danych wskaźnika sterowanysygnałem CSDB. Oba sygnały są wytwarzane w dekoderze adresów na podstawie adresówpodanych przez mikrokontroler na szynę adresową.Zamiast 7 wskaźnika do bufora wyboru wskaźnika zostały podłączone diody led (D13 doD18). Dane umieszczone w buforze CSDB przy wybranych w buforze wskaźnika diodachLed decydują które diody będą zapalone. Ułożenie diod LED pokazuje tabl. 7.14.• Linia 6 portu P1 (bit P1.6) mikrokontrolera 8051 podaje zasilanie na wszystkie wskaźniki

oraz na zestaw diod LED.• Bufor wyboru wskaźnika - dane wpisane do tego bufora określają który wskaźnik w

danym momencie ma być aktywny. Do wyboru mamy 6 wskaźników oraz diody LED,zatem każdy bit ustawiony na 1 decyduje o świeceniu jednego wskaźnika.

• Bufor danych wskaźnika - dane umieszczone w tym buforze, decydują które segmentywskaźnika będą zapalone w wybranym wskaźniku.

Ułożenie segmentów wskaźnika oraz diod LED zostało pokazane w tabl. 7.14.

Tablica 7.14. Opis segmentów wskaźnika i diod led

Bufor danych wskaźnika Bufor wyboru wskaźnikaBit danychwskaźnika

Segment Led Bit wyboruwskaźnika

Wskaźnik

0 A F1 0 W11 B F2 1 W22 C F3 2 W33 D F4 3 W44 E OK 4 W55 F ER 5 W66 G --- 6 LED

Page 35: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

34

7 DP --- 7 ---

W systemie DSM-51 do linii 5 portu P3 (bit P3.5) podłączono kilka klawiszy klawiaturyprzeglądanej sekwencyjnie. Jest ona zbudowana z 6 klawiszy o oznaczeniach [↵], [Esc], [←], [→], [↑], [↓], sterowanych z bufora wyboru wskaźnika (sygnałem CSDS), połączonychrównolegle przez diody do wspomnianej linii 5 portu P3. O tym, który klawisz możnaaktualnie odczytać decyduje bufor wyboru wskaźnika, który jest jednocześnie buforemwyboru klawisza. Dla przykładu: jeżeli na jedynkę logiczna w buforze wyboru wskaźnika jestustawiony bit oznaczony na rys.7.13 jako C0 (bit nr 0), wtedy można odczytać stan klawiszaoznaczonego jako [↵]. Sposób przyporządkowania wszystkich klawiszy odpowiednim bitombufora wyboru wskaźnika przedstawia tabl.7.15.

Tablica 7.15. Sposób wyboru klawisza

Bit wyboru wskaźnika Odczytany klawisz0 [↵]

1 [Esc]2 [→]3 [↑]4 [↓]5 [ ←]

Page 36: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

35

Rys. 7.13. Schemat wyświetlacza 7-segmentowego oraz klawiatury sekwencyjnej

1.4.4. Wyświetlacz LCD

Oprócz wyświetlacza LED oraz klawiatury przeglądanej sekwencyjnie, w systemie DSM-51 istnieje również wyświetlacz LCD oraz klawiatura matrycowa. Blokowy schematpodłączenia obu tych urządzeń pokazano na rys.7.14.

Page 37: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

36

Rys. 7.14. Podłączenie wyświetlacza LCD oraz klawiatury matrycowej

Wyświetlacz podłączony w systemie DSM jest wyświetlaczem uniwersalnymwyświetlającym 2 linie po 16 znaków. Znak zdefiniowany jest w polu 5x7 punktów.Wyświetlacz ten jest wyposażony w uniwersalny sterownik HITACHI HD 4478.Mikrokontroler wysyła do takiego sterownika tylko dane które mają zostać wyświetlone irozkazy w jaki sposób te dane mają być wyświetlone, a sterownik zajmuje się zamianądanych na punkty oraz realizacja rozkazów, zatem to sterownik zajmuje się procesemwyświetlania. Sterownik ten jest sterownikiem uniwersalnym może obsługiwać wyświetlaczeo ilości znaków 2*16, 2*20, 2*40 i 1*80, niestety posiada on jeden zasadniczy mankamentmianowicie bufor wyświetlanych znaków posiada 80 komórek pamięci których obraz jestwyświetlany, jeżeli wyświetlacz nie posiada 80 pól to obraz części komórek nie może zostaćwyświetlony. Niestety wyświetlacz systemu DSM-51 posiada tylko 2*16 pól.

Wygląd wyświetlacza LCD oraz sposób adresowania wyświetlanych znaków w pamięciDD RAM przez wyświetlacz LCD pokazuje rys. 7.15.

0x020x00 0x01 0x0E 0x0F 0x10

0x4E 0x4F0x40 0x41 0x42 0x50

Rys. 7.15. Wygląd wyświetlacza LCD wraz z adresami wyświetlanych danych (rejestry DD RAM)

We wnętrzu każdej komórki pamięci DD RAM można umieścić dowolny kod znakuzgodnego w zakresie 0x20 do 0x7f z kodami ASCII. Tablicę kodów które mogą być widocznena wyświetlaczu LCD przedstawiono w tabl. 7.16.

Tablica 7.16. Tablica znaków wyświetlacza LCD

LCD x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF0x (0) (1) (2) (3) (4) (5) (6) (7) (0) (1) (2) (3) (4) (5) (6) (7)1x2x ∇ ! ” # $ % & ‘ ( ) * + , - . /3x 0 1 2 3 4 5 6 7 8 9 : ; < = > ?4x @ A B C D E F G H I J K L M N O5x P Q R S T U V W X Y Z [ ψ ] ^ -6x ` a b c d e f g h i j k l m n o7x p q r s t u v w x y z { | } ← →8x...ExFx

Znaki alfabetu japońskiego

Jak już wspomniano pamięć CG RAM zawiera znaki definiowane przez użytkownika. Jestona zorganizowana w ten sposób, że poczynając od adresu 0x00 osiem kolejnych komórekzawiera definicje bitów, które maja być uwidocznione po to, aby uzyskać kształt znaku. Znakiwyświetlane są w postaci matrycy punktów o rozmiarach 5x8. Na rys. 7.16 pokazano wyglądmatrycy pojedynczego znaku.

Page 38: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

37

v

v

VCC

VCC

A[0...15]

R59470

D[0...7]

LCD

U7

LM16A21

231

45

6 7891011121314

VCCV0GND

RSR/W

E D0D1D2D3D4D5D6D7

R5810K

A0

A1

D0D1D2D3

D5D4

D6D7

LCD

KONTRAST

LCD

Rys. 7.16. Wygląd matrycy pojedynczegoznaku

Rys. 7.17. Schemat podłączenia wyświetlacza LCD

Wyświetlacz LCD podłączony jest w sposób pokazany na rys. 7.14. Zajmuje on wprzestrzeni adresowej zewnętrznej pamięci danych cztery kolejne komórki pamięci:• 0x02ff80 – LCDWC Zapis instrukcji• 0x02ff81 – LCDWD Zapis danych• 0x02ff82 – LCDRC Odczyt stanu• 0x02ff83 – LCDRD Odczyt danych

Po wysłaniu do wyświetlacza LCD instrukcji lub danej, musi minąć pewien czas potrzebnyby sterownik wykonał rozkaz lub umieścił daną pod wskazanym adresem. W tym czasiesterownik jest zajęty i nie przyjmuje kolejnych poleceń. Możliwe jest tylko odczytanie jegostanu. Przed wysłaniem kolejnego polecania trzeba więc każdorazowo sprawdzić czysterownik nie jest zajęty. Schemat podłączenia wyświetlacza LCD na rys.7.17. W tabl. 7.17pokazano zestawienie rozkazów sterujących sterownikiem HD44780 wyświetlacza LCD.

Tablica 7.17. Rozkazy wyświetlacza LCD

Rozkaz Opis0000 000 1 Kasuj dane wyświetlacza i ustaw kursor po adres0.0000 00 1 X Ustaw kursor pod adres 0. Ustaw dane o adresie 0 na pozycji 1

wyświetlacza0000 0 1 I/D S Ustaw kierunek przesunięcia kursora oraz włącz lub wyłącz przesuwanie

danych wyświetlaczaI/D= 1 zwiększaj o 1 adres kursora po każdym wpisie lub odczycie danychI/D= 0 zmniejszaj o 1 adres kursora po każdym wpisie lub odczyciedanychS=1 jednoczesny obrót danych wyświetlacza

0000 1 D C B Włączenie i wyłączenie wyświetlacza.1 = włączony 0= wyłączonyD- cały wyświetlaczC- tylko kursorB- mruganie znaku w pozycji kursora

000 1 S/C R/L XX S/C=1 obrót danych wyświetlaczaS/C=0 przesunięcie kursoraR/L=1 obrót/ przesuniecie w prawoR/L=0 obrót/ przesuniecie w lewo

00 1 DL N F XX Ustawienia:DL=1 8 bitowa szyna sterującaDL=0 4 bitowa szyna sterującaN=1 2 linie wyświetlaczaN=0 1 linia wyświetlaczaF=1 znaki 5x10 punktówF=0 znaki 5x7 punktówDla DSM-51 należy ustawić 0011 10XX

0 1 A5 A4 A3 A2 A1 A0 Ustawienie adresu generatora znaków(A5..A0) w liczniku adresów. Po tejoperacji można pisać lub czytać generator znaków z pamięci RAM.

Page 39: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

38

1 A6 A5 A4 A3 A2 A1 A0 Ustawienie adresu danych (A6...A0) w liczniku adresów.

1.4.5. Klawiatura matrycowa

System DSM-51 wyposażony jest w 16 klawiszową klawiaturę matrycowa. Schemat jejpodłączenia pokazany został w formie blokowej na rys.7.14, a w postaci pełnego schematuelektrycznego na rys.7.18. Stan klawiatury odzwierciedlają dwa 8-bitowe bufory CSKB0 iCSKB1. Pod każdym z nich można odczytać stan ośmiu klawiszy, co daje nam liczbę 16klawiszy. W tabl.7.18 przedstawiono układ klawiszy w rejestrach CSKB0 i CSKB1. Wybórodczytywanego zestawu klawiszy jest dokonywany przy pomocy dwu linii adresowych A0 iA1 (stan 0 uaktywnia związany z linią zestaw klawiszy).

Tablica 7.18. Odzwierciedlenie klawiatury matrycowej w buforach CSKB0 i CSKB1

Bit CSKB0=21H CSKB1=22H

0 0 81 1 92 2 ←3 3 →4 4 ↑5 5 ↓6 6 Esc7 7 Enter

Rys. 7.18. Schemat podłączenia klawiatury matrycowej

1.4.6. Przetwornik analogowo–cyfrowy A/C

W zastosowaniach praktycznych okazuje się że mikrokontroler musi mieć niejednokrotniemożliwość pomiaru wielkości analogowych. Dotyczy to zwłaszcza mikrokontrolerówwykorzystywanych do sterowania procesami technologicznymi. Parametrami takich procesówsą zazwyczaj różnego rodzaju wielkości nieelektryczne. Wielkości takie jak np. ciśnienie,temperatura są przetwarzane przy wykorzystaniu przetworników pomiarowych na sygnałyelektryczne, a następnie przetwarzane na wartości liczbowe co pozwala na uzależnienie od

Page 40: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

39

nich procesu sterowania. Proces przetwarzania napięcia na wielkość liczbową nosi nazwęprzetwarzania analogowo/cyfrowego.

Urządzenie DSM-51 wyposażone zostało w jeden 8 bitowy przetwornik ADC0804 (U17).Najważniejsze parametry przetworników A/C to:

• Długość słowa: liczba bitów, na których podawany jest wynik np. 8 bitów,• Czas przetwarzania: np. 150 µs,• Zakres napięcia wejściowego np.: 0-5 V.

Sygnały do przetwornika A/C w systemie DSM-51 podawane są przy pomocy 8-wejściowego multipleksera analogowego, który umożliwia podłączenie jednego ośmiu zwejść do wejścia przetwornika ADC0804. Multiplekser jest sterowany buforemumieszczonym pod adresem ff18h (CSMX) w przestrzeni adresowej zewnętrznej pamięcidanych. Do bufora należy wpisać numer wejścia (0 do 7), które ma zostać podłączone doprzetwornika. Wartość napięcia z zakresu 0-5V zostaje przetworzona na wartości liczbowe zzakresu 00h do ffh. Przetwornik ADC0804 jest umieszczony pod adresem ff10h (CSAD) wprzestrzeni adresowej zewnętrznej pamięci danych. Zapis dowolnej wartości pod ten adrespowoduje start przetwarzania. W momencie zakończenia przetwarzania generuje onprzerwanie. Wyjście sygnału przerwania jest podłączone do systemu przerwań DSM-51(sygnał IAD) Odczytanie wyniku przetwarzania (z adresu CSAD) można zrealizować jakoreakcję na przerwanie lub po odczekaniu odpowiedniego czasu potrzebnego na dokonanieprzetworzenia.

Page 41: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

40

Rys. 7.19. Schemat układu z przetwornikiem A/C

1.4.7. Przetwornik cyfrowo –analogowy C/A

Przetworniki cyfrowo-analogowe to układy przetwarzające dyskretny sygnał cyfrowy narównoważny mu sygnał analogowy. Przetwornik ma n wejść i jedno wyjście. Liczba wejśćzależy od liczby bitów słowa podawanego na wejście przetwornika (np. dla słowatrzybitowego – trzy wejścia a1, a2, a3). Natomiast na jego wyjściu pojawia się sygnał

analogowy (np. w postaci napięcia). Napięcie na wyjściu przetwornika jest proporcjonalne donapięcia odniesienia oraz do liczby (n- bitowe słowo) zapisanej w kodzie dwójkowym.Urządzenie DSM-51 wyposażone jest w 8 bitowy przetwornik cyfrowo/analogowy DAC08(U14). Schemat podłączenia przetwornika w systemie pokazano na rys.7.20.

Page 42: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

41

Rys. 7.20. Schemat układu z przetwornikiem C/A

Page 43: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

42

2. Ćwiczenia laboratoryjne

Ćwiczenie M21. Linie wejść i wyjść mikrokontrolera

Mikrokontroler 8051 wyposażony jest w cztery ośmiobitowe porty wejścia/wyjścianazywane P0, P1, P2, P3. Stan portów odzwierciedlają 4 ośmiobitowe rejestry umieszczone wprzestrzeni SFR, w których stan każdego bitu odpowiada stanowi dokładnie 1 linii portu.Każda linia to jedno wyprowadzenie mikrokontrolera, które może stać się sygnałemsterującym urządzenia zewnętrznego lub sygnałem wejściowym dla mikrokontrolera 8051.Rejestry odpowiadające za stan portów można zaadresować bitowo i bajtowo. W tabl. 8.1pokazano adresy bajtowe i bitowe wszystkich rejestrów specjalnych mikrokontrolera 8051położonych w obszarze SFR.

Tablica 8.1. Adresowanie bitów w przestrzeni SFR

Adresy bajtówrejestrówspecjalnych

Adresy bitów rejestrów specjalnych Oznaczeniarejestrówspecjalnych

240 (F0H) F7 F6 F5 F4 F3 F2 F1 F0 B

224 (E0H) E7 E6 E5 E4 E3 E2 E1 E0 ACCCY AC F0 RS1 RS0 OV P

208 (D0H) D7 D6 D5 D4 D3 D2 D1 D0 PSWPS PT1 PX1 PT0 PX0

184 (B8H) - - - BC BB BA B9 B8 IP176 (B0H) B7 B6 B5 B4 B3 B2 B1 B0 P3

EA ES ET1 EX1 ET0 EX0168 (A8H) AF - - AC AB AA A9 A0 IE160 (A0H) A7 A6 A5 A4 A3 A2 A1 A0 P2

SM0 SM1 SM2 REN TB8 RB8 T1 R1152 (98H) 9F 9E 9D 9C 9B 9A 99 98 SCON144 (90H) 97 96 95 94 93 92 91 90 P1

TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0136 (88H) 8F 8E 8D 8C 8B 8A 89 88 TCON128 (80H) 87 86 85 84 83 82 81 80 P0

Sterowanie liniami portu odbywa się przez przypisanie konkretnemu bitowi rejestru portuwartość 0 lub 1. Efektem takiego działania będzie pojawienie się stanu niskiego (0V) lubwysokiego (5V) na konkretnej linii portu. W tej lekcji przedstawione zostaną metodysterowania poszczególnymi liniami portu mikrokontrolera. W celu zaobserwowania zmianystanu linii wykorzystane będą elementy sygnalizacyjne typu LED i brzęczyk (buzzer).

Schemat podłączenia elementów sygnalizacyjnych przedstawiono na rys. 8.1.

Rys. 8.1 Podłączenie diody led i brzęczyka do mikrokontrolera 8051

Page 44: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

43

Przykład 1Najprostszym elementem jaki można podłączyć do mikrokontrolera jest dioda LED.

Odzwierciedla ona dokładnie stan linii gdyż tak jak ona może przyjąć tylko dwa stany.Poniżej na rys. 8.2 przedstawiono schemat blokowy algorytmu realizowanego w pierwszymprzykładzie.

ZEROWANIE

BITU 0x97

WHILE(1)

BIT O ADRESIE BITOWYM

0x97 ODPOWIADA 7

BITOWI PORTU P1

START

Rys. 8.2. Algorytm programu z przykładu 1

W poniższym przykładzie zmiana stanu bitu 7 w rejestrze portu P1 z wysokiego na niskiwywoła zapalenie się diody LED [TEST], podłączonej do mikrokontrolera w sposóbpokazany na rys. 8.1. Na początku programu źródłowego umieszczono pomiędzy znakami /**/ komentarze. Następnie zmiennej o nazwie led przypisano obszar w postaci jednego bitu oadresie 0x97 (patrz tabl. 8.1). Z tego powodu zmienna led (typu bitowego) może przekazywaćtylko wartości 0 i 1. W dalszej części programu deklarowana jest funkcja main czyli główna,od której rozpoczyna się zawsze wykonanie programu. Każdy program w języku C musiposiadać dokładnie jedną taka funkcję. Słowo zastrzeżone void umieszczone przed funkcjąoznacza, że nie będzie ona zwracała żadnej wartości. Wszystko co jest zawarte pomiędzynawiasami { } deklaruje nam ciało funkcji main. W momencie resetu procesor ustawiawszystkie bity portu na 1 oraz rozpoczyna wykonanie procedury main. W celu zmiany stanubitu P1.7 ze stanu wysokiego na niski należy ustawić w związku z tym przy pomocy zmiennejLED wskazywany bit na wartość 0. Efektem działania programu będzie zapalenie diody LEDoznaczonej w systemie DSM-51 jako TEST. Aby spowodować zatrzymanie się algorytmu poustawieniu bitu w programie wywołana jest nieskończona pętla while(1). Która powoduje, żeprocesor ciągle realizuje skok do instrukcji while(1) (patrz rys.8.2).

Poniżej pokazano program realizujący powyższe czynności. Został on zapisany w pliku onazwie p1.c, umieszczonym w katalogu o nazwie L1.

/**************************************************************************Lekcja 1 - Linie wejść i wyjść mikrokontroleraPrzykład 1 - zerowanie linii mikrokontrolera**************************************************************************/sbit led = 0x97; //definicja zmiennej LED i przypisanie jej adresu

//7 bitu portu P1/*********************program główny**************************************/void main (void){ /*definicja funkcji głównej*/ led=0; /*zmiana stanu bitu 7 portu P1 na 0*/

while (1){} /*wywołanie pętli nieskończonej*/}

Page 45: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

44

Przykład 2Program z Przykładu 1 ustawia stan niski bitu 7 portu P1 i właściwie kończy swoje

działanie. W kolejnym przykładzie zostanie przedstawiony program cyklicznie zmieniającystan linii portu, według algorytmu przedstawionego na rys. 8.3.

START

WHILE(1)

ZEROWANIE

BITU 0X97

USTAWIANIE

BITU 0X97

Rys. 8.3. Algorytm działania programu z przykładu 2

Poniższy przykład wykonując się w pętli zmienia kolejno stan linii portu z wysokiego naniski. Efektem pracy programu będzie miganie diody TEST.

Na początku programu deklarowany jest wskaźnik do bitu 7 portu P1. Następniedeklarowana jest funkcja main. Wewnątrz funkcji main, umieszczono nieskończoną pętlęwhile(1). Konstrukcja tej pętli powoduje wykonywanie pętli w przypadku gdy warunek jestprawdziwy czyli =1, co zawsze ma miejsce. Wewnątrz pętli umieszczono instrukcjecyklicznie zmieniające stan bitu 7 portu P1. Efektem takich zmian jest naprzemiennezapalanie i gaszenie diody TEST.

Poniżej pokazano program realizujący powyższe czynności. Został on zapisany w pliku onazwie p2.c, umieszczony w katalogu o nazwie L1.

/**************************************************************************Lekcja 1 - Linie wejść i wyjść mikrokontroleraPrzykład 2 - cykliczne zerowanie i ustawianie linii**************************************************************************/sbit led = 0x97; //definicja zmiennej LED i przypisanie jej adresu

//7 bitu portu P1/*********************program główny**************************************/void main (void){

while (1) //wywołanie pętli nieskończonej{led=0; //zerowanie bitu 7 portu P1led=1; //ustawianie stanu wysokiego bitu 7 portu P1}

}

Poniżej zamieszczono zawartość pliku p2.lst z listingiem programu w języku C oraz wasemblerze. Załączony listing daje możliwość porównania kodu napisanego w języku C zkodem „przetłumaczonym” na język Asembler. Dodatkowym ułatwieniem jest zaznaczenie wkodzie asemblerowym numeru linii, do której odwołuje się przetłumaczony blok kodu.

Page 46: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

45

C51 COMPILER V7.01 P2 12/30/2003 23:32:33 PAGE1

C51 COMPILER V7.01, COMPILATION OF MODULE P2OBJECT MODULE PLACED IN p2.OBJCOMPILER INVOKED BY: C:\51\KEIL\C51\BIN\C51.EXE p2.c BROWSE DEBUG OBJECTEXTENDCODEstmt level source 1/************************************************************************** 2 Lekcja 1 - Linie wejść i wyjść mikrokontrolera 3 Przykład 2 - cykliczne zerowanie i ustawianie linii 4**************************************************************************/ 5 sbit led = 0x97; //definicja zmiennej LED i przypisanie jejadresu 6 //7 bitu portu P1 7 /******************program główny***************************/ 8 void main (void) 9 { 10 1 while (1) //wywołanie pętli nieskończonej 11 1 { 12 2 led=0; //zerowanie bitu 7 portu P1 13 2 led=1; //ustawianie stanu wysokiego bitu 7 portu P1 14 2 } 15 1 } 16

C51 COMPILER V7.01 P2 12/30/2003 23:32:33 PAGE2ASSEMBLY LISTING OF GENERATED OBJECT CODE ; FUNCTION main (BEGIN) ; SOURCE LINE # 8 ; SOURCE LINE # 90000 ?C0001: ; SOURCE LINE # 10 ; SOURCE LINE # 11 ; SOURCE LINE # 120000 C297 CLR led ; SOURCE LINE # 130002 D297 SETB led ; SOURCE LINE # 140004 80FA SJMP ?C0001 ; FUNCTION main (END)

MODULE INFORMATION: STATIC OVERLAYABLE CODE SIZE = 6 ---- CONSTANT SIZE = ---- ---- XDATA SIZE = ---- ---- PDATA SIZE = ---- ---- DATA SIZE = ---- ---- IDATA SIZE = ---- ---- BIT SIZE = ---- ----END OF MODULE INFORMATION.

C51 COMPILATION COMPLETE. 0 WARNING(S), 0 ERROR(S)

Listing składa się z nagłówka, w którym podano wersje kompilatora, datę kompilacji orazwymienione zostają programy wykorzystywane w kompilacji. Następnie załączany jestźródłowy kod programu w języku C oraz jego tłumaczenie na język Asembler. Nazakończenie załączona jest statystka dotycząca kompilacji.

Page 47: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

46

Przykład 3W programie z przykładu 2 wobec dużej szybkości wykonywania instrukcji przez

mikrokontroler zmiany stanu linii 7 portu P1 odbywają się tak szybko, że ludzkie oko nie jestw stanie ich zauważyć (widoczne jest jedynie świecenie diody). W celu zaobserwowaniazmian linii w postaci migotania diody LED, należy wydłużyć czasy trwania stanu załączenia iwyłączenia.

W tym celu mikrokontroler można zająć wykonywaniem operacji np.: odliczania. Wprzykładzie 3 użyto do tego celu pętli for, wewnątrz której następuje przypisanie zmiennej jwartości 0, sprawdzenie warunku czy j <50, i jeśli jest on spełniony wykonanie operacji j++

(inkrementacja zmiennej j) oraz następnej pętli for wykorzystującej zmienną i. Kolejna pętlajest wykonywana 300 razy. Poniżej na rys. 8.4 przedstawiono schemat algorytmurealizowanego w programie.

START

WHILE(1)

ZEROWANIE

BITU 0X97

USTAWIANIE

BITU 0X97

Opóźnienie

for( ; ; )

Opóźnienie

for( ; ; )

Rys. 8.4. Algorytm działania programu z przykładu p.3

Na początku programu deklarowany jest wskaźnik do bitu 7 portu P1, a w głównej funkcjiprogramu dwie zmienne pomocnicze typu int (16 bitów bez znaku). Zasięg zmiennychzadeklarowanych w tym miejscu jest ograniczony zasięgiem funkcji main. Wewnątrznieskończonej pętli while(1) następuję zmiana stanu bitu 7 portu P1 z wysokiego na niski,oddzielona wywołaniami instrukcji pętli for wykonującej się 50x300 razy w celu opóźnieniamikrokontrolera na czas potrzebny do zauważenia zmiany świecenia diody. Następniezmieniany jest stan bitu 7 portu P1 z niskiego na wysoki (dioda TEST zostaje wyłączona). Powyłączeniu ponownie wykorzystana jest pętla for do zajęcia procesora.

Poniżej pokazano program realizujący powyższe czynności. Został on zapisany w pliku onazwie p3.c, umieszczonym w katalogu o nazwie L1.

Page 48: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

47

/**************************************************************************Lekcja 1 - Linie wejść i wyjść mikrokontroleraPrzykład 3 - miganie diody**************************************************************************/sbit led = 0x97; //definicja adresu bitu 7 w porcie P1/*********************program główny**************************************/void main (void){ //definicja funkcji głównejunsigned int i,j; //deklaracja zmiennych pomocniczych

while (1) //pętla nieskończona{led=0; //zeruj linie 7 portu P1for (j=0;j<50;j++) //pętla opóźnienia

for (i=0;i<300;i++);led=1; //ustaw linie 7 portu P1for (j=0;j<50;j++) //pętla opóźnienia

for (i=0;i<300;i++);}

}

Przykład 4W poprzednich przykładach gdy istniała potrzeba odwołania się do adresu w przestrzeni

rejestrów specjalnych mikrokontrolera należało taki adres najpierw zdefiniować (służy dotego deklaracja sbit led = 0x97). Istotną cechą języka C jest możliwość posługiwania sięplikami nagłówkowymi, wewnątrz których są definiowane funkcje, wskaźniki i inneelementy, które można następnie załączać do programu. Jednym z tego rodzaju plików jestplik nagłówkowy o nazwie reg51.h zawierający definicje rejestrów specjalnych (bitów orazbajtów) mikrokontrolera 80x51.

W pliku tym wykorzystano następujące określenia obszarów:• sfr - kwalifikator przestrzeni umożliwiający powiązanie poszczególnych bajtów

położonych w obszarze rejestrów specjalnych SFR z nazwami symbolicznymi.• sbit- kwalifikator przestrzeni umożliwiający powiązanie poszczególnych bitów obszaru

rejestrów specjalnych SFR z ich nazwami symbolicznymi.Zawartość pliku reg51.h zaprezentowano poniżej.

Page 49: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

48

/*--------------------------------------------------------------------------REG51.HHeader file for generic 80C51 and 80C31 microcontroller.Copyright (c) 1988-2001 Keil Elektronik GmbH and Keil Software, Inc.All rights reserved.--------------------------------------------------------------------------*//* BYTE Register */sfr P0 = 0x80; sfr P1 = 0x90; sfr P2 = 0xA0; sfr P3 = 0xB0;sfr PSW = 0xD0; sfr ACC = 0xE0; sfr B = 0xF0; sfr SP = 0x81;sfr DPL = 0x82; sfr DPH = 0x83; sfr PCON = 0x87; sfr TCON = 0x88;sfr TMOD = 0x89; sfr TL0 = 0x8A; sfr TL1 = 0x8B; sfr TH0 = 0x8C;sfr TH1 = 0x8D; sfr IE = 0xA8; sfr IP = 0xB8; sfr SCON = 0x98;sfr SBUF = 0x99;/* BIT Register *//* PSW */sbit CY = 0xD7; sbit AC = 0xD6; sbit F0 = 0xD5; sbit RS1 = 0xD4;sbit RS0 = 0xD3; sbit OV = 0xD2; sbit P = 0xD0;/* TCON */sbit TF1 = 0x8F; sbit TR1 = 0x8E; sbit TF0 = 0x8D; sbit TR0 = 0x8C;sbit IE1 = 0x8B; sbit IT1 = 0x8A; sbit IE0 = 0x89; sbit IT0 = 0x88;/* IE */sbit EA = 0xAF; sbit ES = 0xAC; sbit ET1 = 0xAB; sbit EX1 = 0xAA;sbit ET0 = 0xA9; sbit EX0 = 0xA8;/* IP */sbit PS = 0xBC; sbit PT1 = 0xBB; sbit PX1 = 0xBA; sbit PT0 = 0xB9;sbit PX0 = 0xB8;/* P3 */sbit RD = 0xB7; sbit WR = 0xB6; sbit T1 = 0xB5; sbit T0 = 0xB4;sbit INT1= 0xB3; sbit INT0= 0xB2; sbit TXD = 0xB1; sbit RXD = 0xB0;/* SCON */sbit SM0 = 0x9F; sbit SM1 = 0x9E; sbit SM2 = 0x9D; sbit REN = 0x9C;sbit TB8 = 0x9B; sbit RB8 = 0x9A; sbit TI = 0x99; sbit RI = 0x98;/* Definicje bitów portów WE/WY *//*Port 0*/sbit P0_0=P0^0; sbit P0_1=P0^1; sbit P0_2=P0^2; sbit P0_3=P0^3;sbit P0_4=P0^4; sbit P0_5=P0^5; sbit P0_6=P0^6; sbit P0_7=P0^7;/*Port 1*/sbit P1_0=P1^0; sbit P1_1=P1^1; sbit P1_2=P1^2; sbit P1_3=P1^3;sbit P1_4=P1^4; sbit P1_5=P1^5; sbit P1_6=P1^6; sbit P1_7=P1^7;/*Port 2*/sbit P2_0=P2^0; sbit P2_1=P2^1; sbit P2_2=P2^2; sbit P2_3=P2^3;sbit P2_4=P2^4; sbit P2_5=P2^5; sbit P2_6=P2^6; sbit P2_7=P2^7;/*Port 3*/sbit P3_0=P3^0; sbit P3_1=P3^1; sbit P3_2=P3^2; sbit P3_3=P3^3;sbit P3_4=P3^4; sbit P3_5=P3^5; sbit P3_6=P3^6; sbit P3_7=P3^7;

Korzystając z tego pliku nie trzeba definiować wskaźników do bajtów, bitów i flagumieszczonych w pamięci SFR mikrokontrolera 8051. Zbiór reg51.h w przedstawionejpostaci zawierającej definicję wszystkich adresów w pamięci rejestrów specjalnychmikrokontrolera 8051 i dostarczany jest przez producenta kompilatora. Mając możliwośćskorzystania z pliku definicji przestrzeni SFR załączono go na początku programu przypomocy definicji preprocesora #include. Kolejnym elementem odróżniającym przykład 4 od 3jest wykorzystanie możliwości definiowania funkcji (podprogramów), do których można sięodwoływać w programie głównym.

Na rys. 8.5 przedstawiono schemat algorytmu realizowanego w programie.

Page 50: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

49

START

WHILE(1)

ZMIANA STANU

P1_7

Procedura

opóźnienia 1ms

delay( )

Rys. 8.5 Algorytm działania programu z przykładu 4

Na początku przy pomocy instrukcji preprocesora #include załączany jest pliknagłówkowy reg51.h zawierający definicje rejestrów specjalnych mikrokontrolera. Następniedefiniowana jest funkcja opóźnienia delay(). W języku C obowiązuje naczelna zasada: przedużyciem zmiennej czy funkcji trzeba ją najpierw zdefiniować. Definicja funkcji delay()wygląda następująco:

void delay (unsigned int del)

• pierwsza cześć definicji funkcji (ta przed nawiasem) oznacza, że nie zwraca ona żadnejwartości po wykonaniu (void delay),

• druga cześć (ta wewnątrz nawiasów) jest definicją zmiennej del typu unsigned int ioznacza, że przy wywołaniu funkcji przekazywany jest do niej parametr typu unsignedint, zapisywany następnie do zmiennej del.

Poznana w przykładzie 3 konstrukcja wykorzystująca pętlę for pełni rolę opóźnienia.Wewnątrz funkcji zdefiniowano dwie zmienne typu int służące jako zmienne pomocniczeprzy realizowaniu opóźnienia. Wywołując funkcję delay(n) zamiast n wpisuje się wartośćopóźnienia (unsigned int od 0 do 65536). Przy częstotliwości zegara 11.0592MHz i modelupamięci Small pojedyncze opóźnienie wynosi ok. 1 ms. Następnie wewnątrz nieskończonejpętli while(1) dokonywane są zmiany stanu bitu P1.7. Wykorzystano do tego instrukcjęnegacji bitowej. Dalej wywoływana jest funkcja opóźnienia delay(100). Zmienna o nazwieP1_7 wskazująca na 7 bit rejestru P1 zdefiniowana jest w pliku o nazwie reg51.h. Efektemdziałania programu jest cykliczna zmiana stanu linii P1_7.

Poniżej pokazano program realizujący powyższe czynności. Został on zapisany w pliku onazwie p4.c, umieszczony w katalogu o nazwie L1.

Page 51: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

50

/**************************************************************************Lekcja 1 - Linie wejść i wyjść mikrokontroleraPrzykład 4 - miganie diody - zmiana stanu linii***************************************************************************/#include <reg51.h> //dołączenie pliku nagłówkowego/******************Funkcja opóźnienia**************************************/void delay (unsigned int del) { //definicja funkcji opóźnienia 1ms

unsigned int i,j; //deklaracja zmiennych pomocniczychfor (j=0;j<del;j++) //pętla opóźnienia for (i=0;i<144;i++);}

/******************Program główny******************************************/void main (void){ //definicja funkcji głównej

while (1) { //wywołanie pętli nieskończonejP1_7=!P1_7; //zmiana stanu bitu P1_7delay(100); //opóźnienie czasowe 100*1ms}

}

Ćwiczenia:

1. Posługując się schematem z Rys. 8.1 oraz zdobytymi wiadomościami zmienić wprogramie 1 urządzenie zewnętrzne z diody LED na brzęczyk oznaczony w systemieDSM-51 jako BUZZER.

2. Zmienić działanie programu 3 w taki sposób by czas świecenia diody TEST byłdwukrotnie dłuższy od czasu przerwy.

3. Zmienić w programie 4 urządzenie zewnętrzne z diody LED na brzęczyk.

Page 52: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

51

Ćwiczenie M22. Porty mikrokontroleraW poprzedniej lekcji sterowano poszczególnymi bitami portu P1 mikrokontrolera. Obecna

lekcja, dotyczy działań wykonywanych na całych ośmiobitowych portach. Operowaniecałymi portami to również operowanie całymi bajtami, co może być niezwykle przydatne wpóźniejszych programach, gdzie nie będzie możliwości odwołania się do poszczególnychbitów. Do testowania programów przykładowych wykorzystane zostaną te same elementy cow Lekcji 01 (dioda oraz brzęczyk) podłączone do portu P1.

Przykład 1W przykładzie 1 wykonywane są zmiany stanu linii 7 portu P1 poprzez zmianę wartości

całego portu P1 mikrokontrolera 8051 w taki sposób, że wywoływana zamiana dotyczywyłącznie linii 7. Na wstępie zmiennej o nazwie led przypisano obszar pamięcimikrokontrolera w postaci jednego bajtu o adresie 0x90 (patrz Tabl.8.1). Zmienna led jesttypu sfr i przekazuje 1 bajt danych. Wewnątrz programu głównego main definiowana jestzmienna pomocnicza x typu char (1bajt) do której wpisana zostaje maska, przy pomocy którejustawiony zostanie stan 0 na linii 7 poru P1. Maska ta w zapisie bitowym ma postać 01111111 (w zapisie szesnastkowym 0x7f). Zdefiniowana zmienna pomocniczą x służy dowysyłania maski do poru P1. W efekcie zmieniany jest stanu bitu 7 z wysokiego na niski.Następnie wywoływana jest nieskończona pętla while(1). Efektem działania programu jestzapalenie diody TEST.

Poniżej pokazano program realizujący powyższe czynności. Został on zapisany w pliku onazwie p1.c, umieszczonym w katalogu o nazwie L2.

/**************************************************************************Lekcja 2 - Porty mikrokontroleraPrzykład 1 - zerowanie portu mikrokontrolera**************************************************************************/sfr led = 0x90; /*definicja adresu portu P1*//*********************program główny**************************************/void main (void) { //deklaracja funkcji głównej

char x; //deklaracja zmiennej x (8 bitów)x=0x7f; //do zmiennej x wpisz wartość 0111

1111led = x; //wpisz do portu P1 wartość xwhile (1); //pętla nieskończona

}

Przykład 2W kolejnym przykładzie modyfikacje bitu P1.7 będą wykonywane na całym porcie P1 w

sposób cykliczny Aby zaobserwować zmiany stanów bitów portu należy wydłużyć czas jakiupływa pomiędzy tymi zmianami. Efektem działania programu jest cykliczna zmiana stanubitu P1_7, a w rezultacie zapalenie i gaszenie diody TEST.

Na początku programu dołączany jest plik nagłówkowy z definicjami rejestrówspecjalnych mikrokontrolera. Następnie definiowana jest funkcja opóźnienia delay(). Funkcjadelay() przyjmuje przy wywołaniu parametr w postaci liczby bez znaku typu int którywskazuje na czas opóźnienia w ms. Dalszym krokiem jest zdefiniowanie funkcji głównej iwewnątrz niej dwu zmiennych zapal i gas typu char, do których przypisane zostają wartościdwu masek. Zapalanie diody TEST odbywa się poprzez wpisanie do rejestru portu P1 maski owartości 0x7f (w zapisie bitowym 0111 1111). Natomiast gaszenie diody TEST odbywa siępoprzez wpisanie do rejestru portu P1 maski o wartości 0xff (w zapisie bitowym 1111 1111).Ta część programu umieszczona jest wewnątrz nieskończonej pętli while(1), gdzie kolejnonastępują przepisania do rejestru P1 wartości zmiennej zapal i gas. Pomiędzy przypisaniamiwywoływana jest funkcja opóźnienia delay(100).

Page 53: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

52

Poniżej pokazano program realizujący powyższe czynności. Został on zapisany w pliku onazwie p2.c, umieszczonym w katalogu o nazwie L2.

/**************************************************************************Lekcja 2 - Porty mikrokontroleraPrzykład 2 - zerowanie portu mikrokontrolera**************************************************************************/#include <reg51.H> //załączenie pliku nagłówkowego/*********************podprogram opóźnienia ******************************/void delay (unsigned int del){

unsigned int i,j;for (j=0;j<del;j++)for (i=0;i<144;i++);}

/*********************program główny**************************************/void main (void){ //definicja funkcji głównejchar zapal, gas; //deklaracja zmiennych pomocniczychzapal=0x7f; //przypisanie zmiennej zapal wartości 0111 1111gas=0xff; //przypisanie zmiennej gas wartości 1111 1111

while (1){ //wywołanie pętli nieskończonejP1=zapal; //przepisanie maski zapal do rejestru P1delay(100); //wywołanie funkcji opóźnieniaP1=gas; //przepisanie maski gas do rejestru P1delay(100); //wywołanie funkcja opóźnienia}

}

Zaprezentowane w powyższym przykładzie zapisanie wartości do portu zmienia nie tylkostan bitu 7 portu P1, ale również niszczy poprzedni stan pozostałych bitów, co niekiedy możebyć niewłaściwe.

Przykład 3W kolejnym przykładzie dokonano jednej bardzo ważnej zmiany, która jest jedną z

istotniejszych cech języka C polegającej na umieszczeniu definicji funkcji opóźnienia delay()w pliku o nazwie delay.c. Umożliwi to późniejsze załączanie definicji tej funkcji do programuw postaci pliku nagłówkowego, czyli biblioteki.

Poniżej pokazano zawartość pliku o nazwie delay.c zawierającego definicję funkcjiopóźnienia delay().

void delay (unsigned int del){unsigned int i,j;for (j=0;j<del;j++)for (i=0;i<144;i++);}

Efektem działania programu z niniejszego przykładu jest cykliczna zmiana stanu bituP1_7, a w rezultacie zapalenie i gaszenie diody TEST. Na początku programu plik delay.czostaje załączony razem z plikiem nagłówkowym reg51.h zawierającym definicje przestrzenirejestrów specjalnych mikrokontrolera. Zapis delay.c informuje program preprocesora, że plikdelay.c położony jest w tym samym katalogu co pliki źródłowe tworzonego programu.

Modyfikacje bitu 7 rejestru P1 będą wykonywane na całym porcie P1 w sposóbanalogiczny do przykładu 2. W celu wydłużenia czasu świecenia diody TEST wywoływanajest funkcja delay().

Poniżej pokazano program realizujący powyższe czynności. Został on zapisany w pliku onazwie p3.c, umieszczonym w katalogu o nazwie L2.

Page 54: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

53

/**************************************************************************Lekcja 2 - Porty mikrokontroleraPrzykład 3 - zerowanie portu mikrokontrolera**************************************************************************/#include <reg51.H> //załączenie pliku definicji obszaru SFR#include ”delay.c” //załączenie pliku z definicją funkcji delay/*********************program główny**************************************/void main (void){ //definicja funkcji głównejchar zapal, gas; //deklaracja zmiennych pomocniczychzapal=0x7f; //przypisanie zmiennej zapal wartości 0111 1111gas=0xff; //przypisanie zmiennej gas wartości 1111 1111while (1){ //wywołanie pętli nieskończonej

P1=zapal; //przepisanie maski zapal do rejestru P1delay(100); //wywołanie funkcji opóźnieniaP1=gas; //przepisanie maski gas do rejestru P1delay(100); //wywołanie funkcja opóźnienia}

}

Przykład 4W kolejnym przykładzie do zmiany stanu portu P1 zostaną wykorzystane operacje

iloczynu oraz sumy bitowej. W pierwszym przypadku operacja iloczynu binarnego rejestru P1z maską o wartości 0111 1111 w zapisie binarnym wygląda następująco:

1111 1111 & 0111 1111= 0111 1111W wyniku tej operacji jedynie bit 7 wyniku zostanie ustawiony na 0.W drugim przypadku operacja sumy binarnej rejestru P1 z maską o wartości 1000 0000 w

zapisie binarnym wygląda następująco: 0111 1111 & 1000 0000= 1111 1111W wyniku tej operacji jedynie bit 7 wyniku zostaje ustawiony w stan 1. Obserwowalnym

efektem działania programu będzie miganie diody TEST.Na początku do programu zostają dołączone pliki nagłówkowe z definicjami rejestrów

specjalnych mikrokontrolera oraz plik z definicją funkcją opóźnienia. Wewnątrz funkcjigłównej main wywołana zostaje nieskończonej pętla while(1), w której kolejno będąwykonywane operacje iloczynu i sumy binarnej oddzielone wywołaniami funkcji delay().

Poniżej pokazano program realizujący powyższe czynności. Został on zapisany w pliku onazwie p2.c, umieszczonym w katalogu o nazwie L4.

/**************************************************************************Lekcja 2 - Porty mikrokontroleraPrzykład 4 - zerowanie portu mikrokontrolera***************************************************************************/#include <reg51.H> //załączenie pliku definicji obszaru SFR#include ”delay.c” //załączenie pliku z definicją funkcji del/*********************program główny***************************************/void main (void){while (1){ //wywołanie pętli nieskończonej

P1=P1&0x7f; //bitowe anddelay(100); //wywołanie funkcji opóźnieniaP1=P1|0x80; //bitowe ordelay(100); //wywołanie funkcji opóźnienia.}

}

Zmieniając wartości zmiennych w operacji iloczynu bitowego można zmieniać standowolnych linii portu P1. Poniżej zamieszczono zawartość pliku p4.LST wewnątrz któregoznajduje się listing programu z przykładu 4. Analizując kod programu w asemblerze widaćdziałania iloczynu i sumy bitowej jakie przeprowadzane są na rejestrze P1 przy pomocyinstrukcji ANL i ORL.

Page 55: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

54

C51 COMPILER V7.01 P4 12/31/2003 14:20:25 PAGE 1

C51 COMPILER V7.01, COMPILATION OF MODULE P4OBJECT MODULE PLACED IN p4.OBJCOMPILER INVOKED BY: C:\51\KEIL\C51\BIN\C51.EXE p4.c BROWSE DEBUG OBJECTEXTENDCODEstmt level source 1 /************************************************************ 2 Lekcja 2 - Porty mikrokontrolera 3 Przykład 4 - zerowanie portu mikrokontrolera 4 *************************************************************/ 5 #include <reg51.H> //załączenie pliku definicji obszaru SFR 6 #include "delay.c" //załączenie pliku z definicją funkcji del 7 /*********************program główny*************************/ 8 void main (void){ 9 1 while (1){ //wywołanie pętli nieskończonej 10 2 P1=P1&0x7f; //bitowe and 11 2 delay(100); //wywołanie funkcji opóźnienia 12 2 P1=P1|0x80; //bitowe or 13 2 delay(100); // wywołanie funkcji opóźnienia. 14 2 } 15 1 } 16C51 COMPILER V7.01 P4 12/31/2003 14:20:25 PAGE 2

ASSEMBLY LISTING OF GENERATED OBJECT CODE ; FUNCTION _delay (BEGIN) ; SOURCE LINE # 1;---- Variable 'del' assigned to Register 'R6/R7' ---- ; SOURCE LINE # 2 ; SOURCE LINE # 4;---- Variable 'j' assigned to Register 'R4/R5' ----0000 E4 CLR A0001 FD MOV R5,A0002 FC MOV R4,A0003 ?C0001:0003 C3 CLR C0004 ED MOV A,R50005 9F SUBB A,R70006 EC MOV A,R40007 9E SUBB A,R60008 5015 JNC ?C0007 ; SOURCE LINE # 5;---- Variable 'i' assigned to Register 'R2/R3' ----000A E4 CLR A000B FB MOV R3,A000C FA MOV R2,A000D ?C0004:000D 0B INC R3000E BB0001 CJNE R3,#00H,?C00110011 0A INC R20012 ?C0011:0012 EB MOV A,R30013 6490 XRL A,#090H0015 4A ORL A,R20016 70F5 JNZ ?C00040018 ?C0003:0018 0D INC R50019 BD0001 CJNE R5,#00H,?C0012001C 0C INC R4001D ?C0012:001D 80E4 SJMP ?C0001 ; SOURCE LINE # 6

Page 56: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

55

001F ?C0007:001F 22 RET ; FUNCTION _delay (END)

; FUNCTION main (BEGIN) ; SOURCE LINE # 80000 ?C0008: ; SOURCE LINE # 9 ; SOURCE LINE # 100000 53907F ANL P1,#07FH ; SOURCE LINE # 110003 7F64 MOV R7,#064H0005 7E00 MOV R6,#00H0007 120000 R LCALL _delay ; SOURCE LINE # 12000A 439080 ORL P1,#080H ; SOURCE LINE # 13000D 120000 R LCALL _delay ; SOURCE LINE # 140010 80EE SJMP ?C0008 ; FUNCTION main (END)C51 COMPILER V7.01 P4 12/31/2003 14:20:25 PAGE 3

MODULE INFORMATION: STATIC OVERLAYABLE CODE SIZE = 50 ---- CONSTANT SIZE = ---- ---- XDATA SIZE = ---- ---- PDATA SIZE = ---- ---- DATA SIZE = ---- ---- IDATA SIZE = ---- ---- BIT SIZE = ---- ----END OF MODULE INFORMATION.

C51 COMPILATION COMPLETE. 0 WARNING(S), 0 ERROR(S)

Ćwiczenia:

1. Zmienić w programie z przykładu 4 wykorzystywane operacje iloczynu „&” oraz sumy „|”na operacje przesunięcia bitowego w lewo „<<” i w prawo „ >>”.2. Zmienić w programie 4 urządzenie zewnętrzne z diody LED na brzęczyk oraz wykorzystaćdziałanie bitowej alternatywy „^”.

Uwaga. Operatory przesunięć (<<) i (>>) przesuwają ciąg bitów argumentu znajdującegosię po ich lewej stronie o liczbę pozycji określona przez argument znajdujący się po ichprawej stronie, np.:

P1<<1; //przesuniecie bitowe w lewo o 1 pozycjeP1>>2; //przesuniecie bitowe w prawo o 2 pozycje

Pozycje bitów zwolnione po prawej stronie w wyniku użycia operatora przesunięcia wlewo (<<), są zawsze wypełniane zerami. Wartości bitów przesuniętych w lewo są nazawsze tracone. Podobnie dzieje się podczas operacji przesunięcia bitowego w prawo.

Page 57: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

56

Ćwiczenie M23. Pamięć mikrokontroleraJęzyk C jako język wysokiego poziomu znacznie ułatwia programiście wykorzystanie

pamięci i w zasadzie przejmuje konieczność organizacji jej przestrzeni. Nadal jednak wpewnych przypadkach może okazać się niezbędne umieszczanie zmiennych w jej ściśleokreślonych miejscach. Jest to szczególnie ważne np. przy podłączaniu dodatkowych portówdo szyny systemowej systemu mikroprocesorowego czy przy korzystaniu z pamięcizewnętrznych. Kompilator Keil wyposażony jest w instrukcje umożliwiające swobodneumieszczanie zmiennych i stałych w określonych miejscach pamięci danych i programu.Utrudnieniem może być fakt, że nie ma tutaj obowiązującego standardu i komendy działającew kompilatorze firmy Keil nie muszą koniecznie działać w kompilatorach innychproducentów.

Aby uzyskać dostęp do komórki pamięci o podanym adresie należy zdefiniować wskaźnikdo tej komórki pamięci przy pomocy kwalifikatora _at_, np.:

xdata CSDA _at_ 0x0ff08;//wskaźnik do rejestru w pamięci zewnętrznej XDATA xdataCSDB _at_ 0x0ff38;xdata CSX _at_ 0x0ffC0;

Składnia definicji wskaźnika jest następująca :• XDATA - określenie obszaru pamięci• CSDA - nazwa symboliczna obszaru• _at_ - kwalifikator• 0xffco - adres obszaru

Inne obszary pamięci używane przez kompilator języka C to:00-Data, 01-Idata, 02-Xdata, 03-Pdata, 04-Bdata, 05-Code

• DATA – bezpośrednio adresowany obszar wewnętrznej pamięci RAM (128 bajtów),• IDATA – pośrednio adresowany obszar wewnętrznej pamięci RAM mikrokontrolera (128

lub 256 bajtów),• XDATA – zewnętrzna pamięć danych, adres dostępu 16 bitowy (64kB),• PDATA – tak samo, jak XDATA z tym, że adres dostępu do pamięci zewnętrznej jest 8

bitowy,• BDATA – obszar pamięci RAM, w którym możliwe jest adresowanie pojedynczych bitów

rejestrów specjalnych SFR, na przykład sbit OV = PSW^2,• CODE – pamięć programu; może być albo wewnętrzny, albo zewnętrzny ROM

mikrokontrolera,• SFR – obszar rejestrów specjalnych położony w pamięci RAM,• SBIT – obszar pojedynczego bitu położony w obszarze bitowym wewnętrznej pamięci

RAM.Wyżej wymienione słowa kluczowe języka C noszą nazwę kwalifikatorów obszaru

pamięci.

Page 58: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

57

Rys. 8.6. Schemat szyny systemowej DSM-51

System DSM-51 ze względu na swoja złożoność wyposażony jest w szynę systemową. Narys. 8.6 pokazano schemat blokowy urządzenia DSM-51 wraz z jego urządzeniamiperyferyjnymi podłączonymi do szyny systemowej. Na szynę systemową składa się 16 bitowa

szyna adresowa, 8 bitowa szyna danych oraz szyna sterująca złożona z sygnałów RD ,

WR oraz sygnału wyboru układu.• Szyna adresowa – 16 linii oznaczonych jako A0 do A15. Na tę szynę podawany jest adres.

Pod każdym adresem może znajdować się komórka pamięci lub jeden 8 bitowy portwe/wy. Ustawienie adresu polega na ustawieniu 0 lub 1 na poszczególnej linii adresowej.Maksymalnie można w ten sposób zaadresować 65 536 komórek.(64kB)

• Szyna danych – 8 linii oznaczonych jako D0 do D7. Po szynie danych przesyłana jestzawartość komórki pamięci lub portu. Szyna danych jest dwukierunkowa i umożliwiaprzesyłanie danych z i do mikrokontrolera. Przesyłanie danych to ustawianieposzczególnych linii danych w stan 0 lub 1, przez urządzenie zewnętrzne (odczyt) lubprzez mikrokontroler (zapis).

• Szyna sterująca składa się z trzech linii sterujących przesyłaniem danych (wmikrokontrolerze 8051) oraz sygnału wyboru układu.Są to linie:• PSEN- odczyt pamięci programu,• RD- odczyt pamięci danych,• WR- zapis pamięci danych,• Sygnały wyboru układu pokazano w tabl. 8.2.

Porty we/wy podłączone do szyny systemowej umieszczone są w przestrzeni adresowejpamięci danych. Przez to możliwy jest zarówno ich zapis (sygnał WR) jak i odczyt (sygnałRD). W kompilatorze zewnętrzny obszar pamięci danych określony jest jako XDATA.

Poniżej w tabl. 8.2 pokazano elementy zewnętrzne podłączone do szyny systemowej, orazwymieniono ich nazwy symboliczne i adresy w urządzeniu DSM-51.

Page 59: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

58

Tablica 8.2. Urządzenia we/wy DSM-51 oraz ich adresy w pamięci

Adres Adres hex Symbol Urządzenie0000 0XXX B FF00 H CSIC Sterownik przerwań0000 1XXX B FF08 H CSDA Przetwornik C/A0001 0XXX B FF10 H CSAD Przetwornik A/C0001 1XXX B FF18 H CSMX Multiplekser analogowy0010 0X01 B FF21 H CSKB0 Klawiatura matrycowa: klawisze od 0 do 70010 0X10 B FF22 H CSKB1 Klawiatura matrycowa: klawisze od 8 do ...0010 1X00 B FF28 H CS55A Układ 8255 – rejestr portu A0010 1X01 B FF29 H CS55B Układ 8255 – rejestr portu B0010 1X10 B FF2A H CS55C Układ 8255 – rejestr portu C0010 1X11 B FF2B H CS55D Układ 8255 – rejestr sterujący0011 0XXX B FF30 H CSDS Bufor wyboru wskaźnika 7-segmentowego0011 1XXX B FF38 H CSDB Bufor danych wskaźnika 7-segmentowego01XX XXX B FF40 H CSMOD Tryb dekodera adresów10XX XX00 B FF80 H LCDWC HD44780 – wpis rozkazów10XX XX01 B FF81 H LCDWD HD44780 – wpis danych10XX XX10 B FF82 H LCDRC HD44780 – odczyt stanu10XX XX11 B FF83 H LCDRD HD44780 – odczyt danych11XX XXXXB FFC0 H CSX Zewnętrzna magistrala systemowa

W poniższej lekcji użyta zostanie linijka diod LED, których schemat połączenia wsystemie DSM-51 pokazano na rys. 8.7. znajdująca się w zewnętrznej przestrzeni pamięcidanych XDATA. Do sterowania tych diod wykorzystuje się dwa bufory:• CSDA - bufor wyboru wskaźnika• CSDB - bufor danych wskaźnika

Bufory te zostaną omówione przy okazji wykorzystania wyświetlacza 7-segmentowegoLED w lekcji 5. Do linii 6 rejestru sterowanego sygnałem CSDS podłączono 6 diod LEDktórymi można sterować wpisując odpowiednie dane do rejestru sterowanego sygnałemCSDB. Do sterowania diodami wykorzystywane są dwa rejestry oznaczone na rys.8.7 jakoU22 i U23 oraz linia P1.6 mikrokontrolera 8051. Rejestr U23 jest sterowany sygnałem CSDSpochodzącym z dekodera adresów, wysyłanym w przypadku wystawienia adresu 0xFF30.Pozwala on na włączenia zasilania +8V na anody diod LED w przypadku ustawienia stanu 0na linii 6 portu P1 mikrokontrolera oraz wpisania do rejestru danej o wartości zawierającej 0na 6 bicie. Rejestr U22 jest sterowany sygnałem CSDB pochodzącym z dekodera adresów,wysyłanym w przypadku wystawienia adresu 0xFF38. Pozwala on na indywidualnewłączenie każdej z diod poprzez wystawienie sygnału na bazy tranzystorów które zamykają(podają 0) ich obwody zasilające.

Page 60: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

59

Rys. 8.7. Schemat podłączenia zewnętrznych diod led do szyny systemowej

Przykład 1W poniższym przykładzie sterowane będą diody LED podłączone do szyny systemowej.

Sterowanie będzie realizowane przez wysyłanie do rejestru U22 bajtu danych włączającegoodpowiednio tranzystory zamykające obwody katod wybranych diod. Efektem działaniaprogramu będzie świecenie diod oznaczonych w systemie DSM-51 jako F1, F2, F3, F4, OK. iER.

Na początku programu załączono plik z definicjami rejestrów specjalnych i zdefiniowano2 wskaźniki do pamięci XDATA wskazujące na bufory w pamięci zewnętrznej o nazwach:

• CSDS – bufor wyboru diod.• CSDB – bufor za pomocą którego wybierane są diody podlegające włączeniu.Wewnątrz funkcji main zdefiniowano dwie zmienne pomocnicze typu char, przy pomocy

których będą przekazywane wartości do buforów. Do zmiennej leds wpisywana jest wartośćodpowiadającą wyborowi diod LED jako urządzeń wyjściowych, a do zmiennej num wartośćumożliwiającą włączenie wybranych diod. Do rejestru CSDS wysyłana jest wartość zmiennejleds a do rejestru CSDB wartość zmiennej num. W odróżnieniu od portów bezpośredniopodłączonych do mikrokontrolera sterowanie urządzeniami zewnętrznymi przy pomocy szynyadresowej odbywa się ustawiając odpowiedni bit w stan wysoki. Ustawiając na linii P1_6 stanniski zostaje załączone zasilanie linijki diod LED. Poniżej pokazano program realizującypowyższe czynności. Został on zapisany w pliku o nazwie p1.c, umieszczonym w katalogu onazwie L3.

Page 61: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

60

/**************************************************************************Lekcja 3 - PamięćPrzykład 1 - Porty w pamięci Xdata**************************************************************************/#include <reg51.h> /* zbiór nagłówkowy adresów rejestrów i bitów *//************************Adresy buforów wyświetlacza LED ******************/xdata CSDS _at_ 0x0ff30;xdata CSDB _at_ 0x0ff38;/************************ program główny **********************************/void main(void) {char leds, num; //definicja zmiennych pomocniczychleds = 0x40; //ustawienie bitu 6 na 1num = 0x3f; //ustawienie bitów 0,1,2,3,4,5 na 1CSDS = leds; //włączenie obwodu diodCSDB = num; //włączenie konkretnych diodP1_6 = 0; //załączenie zasilania +8V na katody diodP1_7=0; //port w pamięci – dla porównaniawhile(1) {} //pętla nieskończona}

Przykład 2Kwalifikatory pamięci zadeklarowane w poprzednim przykładzie mają zasięg globalny, ale

w języku C można posłużyć się inna metoda deklaracji wskaźników. W tym przykładzie będąone posiadały zasięg lokalny ograniczony do funkcji main.

Na początku programu załączono plik nagłówkowy oraz zdefiniowano funkcje main.Wewnątrz tej funkcji zadeklarowano dwa wskaźniki *CSDS i *CSDB oraz dwie zmienne typuchar. Aby określić adresy w obszarze pamięci zewnętrznej, do których odnosić będą sięwskaźniki należy przypisać im wartości adresów np.: CSDS=0x02ff30, gdzie:.• 0x02 - oznacza obszar pamięci zewnętrznej XDATA,• ff30 - oznacza adres bufora w pamięci XDATA.

Do adresu pamięci wskazywanego przez wskaźnik CSDS przesyła się wartościodpowiadające za wybór włączenia zasilania diod LED, a do adresu wskazywanego przezCSDB wartości odpowiadające wybranym do załączenia diodom. Dla porównania użytorównież diody podłączonej bezpośrednio do portu mikrokontrolera. Główne włączeniezasilania diod LED odbywa się przy pomocy portu P1_6. Po wykonaniu powyższychinstrukcji mikrokontroler zostaje zatrzymany w nieskończonej pętli while(1).

Poniżej pokazano program realizujący powyższe czynności. Został on zapisany w pliku onazwie p2.c, umieszczonym w katalogu o nazwie L3.

/***************************************************************************Lekcja 3 - PamięćPrzykład 2 - Porty w pamięci - wskaźniki***************************************************************************/#include <reg51.h> //zbiór nagłówkowy adresów rejestrów i bitów/************************ program główny **********************************/void main(void) {char *CSDS,*CSDB,leds,num;CSDS=0x02ff30; //przypisanie wskaźnikom adresówCSDB=0x02ff38; //przypisanie wskaźnikom adresów/*0x02 –pamięć XDATA, ff30- adres w pamięci XDATA*/leds = 0x40; //0x4 diody F1,F2,F3,F4,OK.,ERnum = 0x3f; //0x3f wszystkie diody 0011 1111*CSDS = leds; //przepisanie wartości zmiennej do rejestru*CSDB = num; //przepisanie wartości zmiennej do rejestruP1_6=0; //załączenie zasilania układu diodP1_7=0; //port w pamięci- dla porównaniawhile(1) {} //pętla nieskończona}

Page 62: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

61

Ćwiczenia:

1. Zmienić program 1 w taki sposób by wyświetlana była tylko dioda oznaczona w systemieDSM-51 jako OK.2. Zmienić program 2 w taki sposób by diody LED podłączone do szyny systemowej migały.3. Zmienić program 2 w taki sposób by diody LED podłączone do szyny systemowejutworzyły migający wąż.

Page 63: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

62

Ćwiczenie M24. Operacje arytmetyczneBardzo mocna stroną języka C jest prostota wykonywania operacji arytmetycznych.

Wszystkie operacje wykonywane są przy wykorzystaniu klasycznego zapisu z użyciemoperatorów arytmetycznych.

Do wizualizacji wykonywanych operacji użyta zostanie funkcja printf, której działanieoparte jest na funkcji putchar. Budowa i wykorzystanie funkcji putchar zostało opisane wlekcji 7 dotyczącej wyświetlacza LCD. Drugim elementem wykorzystanym w programachprzykładowych jest funkcja getkey, której budowa i działanie zostały opisane w lekcji 6dotyczącej klawiatury matrycowej.

Funkcja printf umożliwia formatowane wyprowadzanie danych. Analizuje ona najpierwprzekazany jako pierwszy argument tekst, a następnie na podstawie informacji zawartych wtym tekście, wypisuje kolejne wartości. W szczególnym przypadku do funkcji printf możezostać przekazany tylko format. Tekst przekazywany jako format, składa się z tekstu, któryzostanie wypisany tak jak został przekazany oraz informacji o koniecznych konwersjach.Informacja o konwersji rozpoczyna się znakiem '%'. Każda taka informacja odpowiada jednejwartości przekazanej jako kolejny argument. W wypisywanym tekście, kolejne wartościpojawiają się w miejscu odpowiednich konwersji '%'. Same znaki '%' nie są wypisywane. Wprzypadku, gdy chcemy wypisać na ekranie znak '%' w podanym tekście należy wpisać"%%". W tabl. 8.3 pokazano wszystkie specyfikatory funkcji printf().

Tablica 8.3 Specyfikatory funkcji printf.

Opis Typ operandu Typ%d,i Dziesiętna notacja int%ld długa liczba całkowita dziesiętna int%o ósemkowa bez znaku int%x,X szesnastkowa bez znaku int%u dziesiętna bez znaku unsigned int%c Znak int lub char%s Ciąg char[] char *%f Dziesiętna notacja double lub float%e,E Notacja naukowa double lub float%g,G Krótkie %e lub %f double lub float%p Wskaźnik void *%% Znak % n/a

Poniżej przedstawiono przykłady użycia funkcji printf():

printf("Dzisiaj jest wtorek!\n"); wynik: Dzisiaj jest wtorekprintf("120 %% 10 = 0\n"); wynik: 120 % 10 = 0

Przykłady specyfikatorów użycia funkcji printf():

%3d wyświetli 3 cyfry wyrównane do prawej%3.0f nie wyświetli przecinka i liczby po nim%3.1f wyświetli jedną cyfrę po przecinku

Przykład 1W przykładzie zaprezentowane zostanie użycie podstawowych operatorów

arytmetycznych dodawania (+), odejmowania (-), mnożenia(*), dzielenia (/) dzielenia modulo(%), odejmowania z wynikiem ujemnym i dzielenia z resztą. Jako dane do działań będąwykorzystywane 2 bajtowe liczby całkowite ze znakiem (typ int). Warto pamiętać, żeoperacje arytmetyczne wykonywane na liczbach całkowitych dają w wyniku również liczbycałkowite, dlatego niektóre z otrzymanych wyników mogą znacząco odbiegać odspodziewanych. Wyniki działań prezentowanych w przykładzie zostaną wyświetlone nawyświetlaczu LCD. Ze względu na ograniczona pojemność wyświetlacza (2 linie)

Page 64: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

63

jednorazowo zostaną wyświetlone tylko 2 operacje arytmetyczne. W celu wyświetleniakolejnych dwu operacji należy nacisnąć dowolny klawisz z klawiatury matrycowej.

Na początku programu załączone zostają pliki nagłówkowe z definicjami rejestrów SFR,

plik ze standardowymi procedurami języka C pozwalającymi na wyświetlenie danych zestandardowego strumienia wejścia wyjścia stdio.h oraz pliki z programami obsługiwyświetlacza LCD (lcd.c) oraz klawiatury matrycowej (key.c). Pogramy z plików lcd.c i key.czostaną opisane w późniejszych lekcjach. W programie głównym zdefiniowano zmiennepomocnicze typu int oraz przypisano im wartości wyjściowe. Przed użyciem wyświetlaczaLCD wywoływana jest funkcja z pliku lcd.c o nazwie lcd_init() odpowiadająca zainicjalizacje wyświetlacza. Pierwsze operacje jakie zostają wykonane to operacje dodawania iodejmowania. Wyniki tych operacji są wyświetlone na wyświetlaczu LCD. Następniewykonane są operacje mnożenia i dzielenia oraz dzielenia modulo i odejmowania z ujemnymwynikiem, na końcu powtórnie zostaje wykonana operacja dzielenia. W efekcie wykonaniaoperacji otrzymywane są kolejne wyniki:1+2 =3, 2-1 =1, 2*6 =12, 6/2 =3, 8%6 =22-6 =-4, 8/6 =1

Każdorazowo po wyświetleniu dwu operacji system czeka na zezwolenie wykonaniakolejnych dwu operacji i wyświetlenie ich wyników na wyświetlaczu LCD.

Poniżej pokazano program realizujący powyższe czynności. Został on zapisany w pliku onazwie p1.c, umieszczonym w katalogu o nazwie L4.

/***************************************************************************Lekcja 4 - Działania arytmetycznePrzykład 1 - dodawanie odejmowanie mnożenie dzielenie reszta z dzielenia***************************************************************************/#include <reg51.h> //zbiór nagłówkowy adresów rejestrów i bitów#include <stdio.H> //zbiór nagłówkowy z programami obsługistrumienia

//wejścia/wyjścia#include "lcd.c" //zbiór nagłówkowy z programami obsługi LCD#include "key.c" //zbiór nagłówkowy z programami obsługi klawiatury/************************ program główny **********************************/void main (void){int a,b,c,d,e; //deklaracja zmiennychlcd_init(); //inicjalizacja wyświetlaczaa=1;b=2;c=6;d=8; //przypisanie wartości wyjściowyche=a+b; //operacja dodawaniaprintf("%i+%i=%i\n",a,b,e); //wyświetl a jako int,b jako int,e jako int,e=b-a; //operacja odejmowaniaprintf("%i-%i=%i\n",b,a,e); //wyświetl b jako int,b jako int,e jako int,getkey(); //oczekiwanie na klawisze=b*c; //operacja mnożeniaprintf("%i*%i=%i\n",b,c,e); //wyświetl a jako int,b jako int,b jako int,e=c/b; // i zacznij od nowej liniiprintf("%i/%i=%i\n",c,b,e); //wyświetl c jako int,b jako int,e jako int,getkey(); //oczekiwanie na klawisze=d%c; //reszta z dzieleniaprintf("%i%%%i= %i\n",d,c,e); //wyświetl d jako int,c jako int,e jako int,c=b-c; //liczb ujemneprintf("%i-%i= %i\n",b,c,e); //wyświetl b jako int,c jako int,e jako int,getkey(); //oczekiwanie na klawisze=d/c; //dzielnieprintf("%i%%%i= %i\n",d,c,e); //wyświetl d jako int,c jako int,e jako int,while (1);}

Page 65: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

64

Przykład 2W poniższym przykładzie wykorzystano zaprezentowane już operacje arytmetyczne do

wykonania prostego kalkulatora mogącego realizować podstawowe operacje arytmetyczne nawartościach wprowadzonych z klawiatury. Wartości te są jednocyfrowe i całkowite. Dowyświetlania danych wykorzystano wyświetlacz LCD. W celu wpisania operacji jaka mazostać wykonana należy wpisać pierwszą liczbę następnie typ operacji i zakończyć wpisaniemdrugiej liczby.

Na początku programu załączane są pliki nagłówkowe, następnie wewnątrz funkcji main

zadeklarowane są zmienne pomocnicze niezbędne do wykonywania działań. Przed użyciemwyświetlacza LCD jest wywoływana funkcja z pliku lcd.c o nazwie lcd_init() odpowiadającąza inicjalizacje wyświetlacza. Dane na wyświetlacz LCD wyprowadzane są przy pomocyfunkcji printf(). Dane z klawiatury są pobierane przy wykorzystaniu funkcji getnum().

Wartości pobrane z klawiatury zapisywane są kolejno pod zmienne pomocnicze. W celuustalenia rodzaju żądanej operacji, użyto instrukcji wyboru if. Jeśli wartość zapisana podzmienną b jest równa wartości ‘znak’ (wartości kodu ASCII danego znaku) wtedywykonywana jest operacja zapisana po warunku. Ponieważ kalkulator może wykonać czteryoperacje, użyto czterech instrukcji wyboru if, z których wykonywana jest ta, która zostaławybrana. Wynik operacji wraz z wartościami wejściowymi zostaje wyświetlony nawyświetlaczu LCD. Program wykonuje się jednoprzebiegowo w celu powtórzenia operacjikonieczne jest jego ponowne uruchomienie.

Poniżej pokazano program realizujący powyższe czynności. Został on zapisany w pliku onazwie p2.c, umieszczonym w katalogu o nazwie L4.

/***************************************************************************Lekcja 4 - Działania arytmetycznePrzykład 2 - Prosty kalkulator****************************************************************************/#include <reg51.h>#include <stdio.h>#include "delay.c"#include "lcd.c" //procedura obsługi wyświetlacza LCD#include "key.c" //procedura obsługi klawiatury/********************** program główny *************************************/void main(void) {int a,c,d; //deklaracje zmiennych char b;lcd_init(); //inicjalizacja wyświetlaczaprintf("kalkulator\n"); //wyświetl napis" " i przejdź do następnej liniia=getnum(); //pobierz wartośćdelay(100); //funkcja opóźnieniab=getkey(); //pobierz znak klawisza w ASCIdelay(100); //funkcja opóźnieniac=getnum(); //pobierz wartośćif (b=='+')d=a+c; //jeśli wprowadzono znak + wykonaj d=a+cif (b=='*')d=a*c; //jeśli wprowadzono znak * wykonaj d=a*cif (b=='-')d=a-c; //jeśli wprowadzono znak - wykonaj d=a-cif (b=='/')d=a/c; //jeśli wprowadzono znak / wykonaj d=a/cprintf("%d%c%d=%d",a,b,c,d); //wyświetl a dziesiętnie, b znakowo,while(1); //c dziesiętnie, d dziesiętnie,}

Przykład 3W ostatnim dzieleniu przykładu 1 celowo została wykonana operacja, której wynik jest

inny niż oczekiwany. Powodem występowania błędu było użycie typu zmiennychcałkowitych, które nie są w stanie przedstawić liczb rzeczywistych. Mikroprocesor 8051operuje co prawda na liczbach całkowitych ale wykorzystując język C można łatwo

Page 66: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

65

rozwiązać ten problem wykorzystując zmienne typu float (zmiennoprzecinkowe). Wponiższym przykładzie wykonana zostanie tylko jedna operacja dzielenia. Do przedstawieniawyniku działania wykorzystana zostanie funkcja printf() oraz wyświetlacz LCD. Operacjadzielenia w przykładzie jest taka sama jak w programie z przykładu 1 jednak ze względu nawykorzystanie zmiennych rzeczywistych oraz arytmetyki liczb rzeczywistych wynik jestpoprawny.

Na początku programu załączone zostają pliki nagłówkowe. Wewnątrz funkcji main

definiowane są zmienne pomocnicze typu int oraz float. Pod zmienne pomocnicze zostająprzypisane wartości początkowe. Wywołując funkcję lcd_init inicjalizowane jest działaniewyświetlacza LCD. Wykonywane są dwie operacje dzielenia:• Pierwsza, w której zmienne odpowiadające za dzielną i dzielnik są typu całkowitego a

zmienna wynik jest typu rzeczywistego.• Druga, w której wszystkie użyte zmienne są typu float (zmiennoprzecinkowe).

Wyświetlenie wyników zrealizowane jest przy wykorzystaniu funkcji printf.Poniżej pokazano program realizujący powyższe czynności. Został on zapisany w pliku o

nazwie p3.c, umieszczonym w katalogu o nazwie L4.

/***************************************************************************Lekcja 4 - Działania arytmetycznePrzykład 3 - działania arytmetyczne z użyciem zmiennych typu float***************************************************************************/#include <reg51.h>#include <stdio.h>#include "lcd.c"/********************* program glowing *************************************/int main(void){int a,b; //deklaracja zmiennychfloat c,d,e; //deklaracja zmiennycha=36; //przypisanie wartości do zmiennychb=5;lcd_init(); //inicjalizacja wyświetlacza LCDc=a/b; //dzielenie liczb integer wynik float//printf("%i/%i=%f\n",a,b,c); //wyświetlanie a,b jako int, c jako floatd=a;e=b;c=d/e; //dzielenieprintf("%f/%f=%f",d,e,c); //wyświetlanie c d e jako wartości floatwhile (1); //pętla nieskończona}

Chcąc otrzymać wynik w formacie liczby zmiennoprzecinkowej również użyte zmiennepomocnicze muszą być w tym formacie, w przeciwnym wypadku wynik może być odmiennyod oczekiwanego. W celu umożliwienia pokazania efektu wywołanego przez niewłaściwąinterpretację zmiennych można w programie uruchomić linię oznaczoną jako komentarz.

Poniżej pokazano fragment kodu w asemblerze z listingu programu z przykładu 3odpowiadający za wykonywanie dzielenia na liczbach rzeczywistych (c=d/e;).

Page 67: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

66

; SOURCE LINE # 19004A AB00 R MOV R3,e+03H004C AA00 R MOV R2,e+02H004E A900 R MOV R1,e+01H0050 A800 R MOV R0,e0052 AF00 R MOV R7,d+03H0054 AE00 R MOV R6,d+02H0056 AD00 R MOV R5,d+01H0058 AC00 R MOV R4,d005A 120000 E LCALL ?C?FPDIV005D 8F00 R MOV c+03H,R7005F 8E00 R MOV c+02H,R60061 8D00 R MOV c+01H,R50063 8C00 R MOV c,R4

Przykład 4W języku C istnieje niezwykle użyteczna biblioteka o nazwie math.h, która zawiera

definicje funkcji matematycznych takich jak : sin, cos, tan, potęga, pierwiastek itd. Wponiższym przykładzie zaprezentowane zostanie wykorzystanie dwu funkcji sinus i cosinus zwspomnianej biblioteki. Funkcje tej biblioteki operują wyłącznie na zmiennych typu float.Poniższy program oblicza wartość sin () i cos() dla podanych wartości kata. Wartość kataprzekazywana do funkcji musi być podana w radianach. Przeliczenie stopni na radianyzostanie wykonane według poniższego wzoru:

radian=stopnie*(3,14159/180) (8.1)

Na początku programu załączane są niezbędne pliki nagłówkowe, w tym bibliotekamath.h, następnie wewnątrz funkcji głównej deklarowane są zmienne pomocnicze typu float.Do zmiennej o nazwie kat przypisana zostaje wartość kąta w stopniach. Następnie wartośćkąta zostaje przeliczona na radiany i przypisana do zmiennej kat_rad. Wywołania funkcjitrygonometrycznych zostały umieszczone w wywołaniach funkcji printf, która odpowiada zawyświetlanie działania oraz wyników na wyświetlaczu LCD. Najpierw pobiera ona dane dowyświetlenia, a potem wysyła już kompletny format do wyświetlacza LCD.

Poniżej pokazano program realizujący powyższe czynności. Został on zapisany w pliku onazwie p4.c, umieszczonym w katalogu o nazwie L4.

/**************************************************************************Lekcja 4 - Działania arytmetycznePrzykład 4 - funkcje sin i cos - biblioteka math.h***************************************************************************/#include <reg51.h>#include <math.h> //biblioteka z funkcjami matematycznymi#include <stdio.h>#include "lcd.c" //obsługa wyświetlacza LCD/************************ program główny **********************************/int main(void){float kat_rad; //deklaracja zmiennychint kat;kat=45; //wartość katalcd_init();kat_rad=kat*3.141593/180.0; //przeliczenie stopni na radiany

printf("sin%d=%f \n",kat,sin(kat_rad));//wywołanie funkcji trygonometrycznejprintf("cos%d=%f \n",kat,cos(kat_rad));//i wyświetlenie wyników na LCDwhile (1); //pętla nieskończona

}

Ćwiczenia:

1. Zmienić program 2 w taki sposób by operacje arytmetyczne były wykonywane na liczbachrzeczywistych.

Page 68: LABORATORIUM PODSTAW TECHNIKI MIKROPROCESOROWEJ · • zapis znak-moduł - w tym zapisie najstarszy bit (zapisywany po lewej stronie) decyduje o znaku liczby (0 - dodatnia, 1 - ujemna),

67

2. Używając funkcji z biblioteki math.h zmienić program 4 w taki sposób by wyliczonezostały odwrotności sinusa i cosinusa, a wynik wyświetlony w stopniach.

Literatura

[1] P.Gałka, P.Gałka : „Podstawy programowania mikrokontrolera 8051”, MIKOM, Warszawa 2000.[2] J.Majewski, K.Kardach: „Programowanie mikrokontrolerów z serii 8x51 w języku C”, OficynaWydawnicza Politechniki Wrocławskiej, Wrocław 2002.[3] J.Doliński: „Mikrokomputer jednoukładowy Intel 8051”, PLJ, Warszawa 1993.[4] P.Printz, Ukrich_Prinz: C leksykon kieszonkowy.[5] T.Zhang: „Poznaj C w 24 godziny”, Intersoftland, Warszawa 1998.[6] B.W. Kernigham, D.M.Ritchie: „Język Ansi C”, WNT, Warszawa 2003.[7] Keil Software 8051 Demo Kit – User’s Guide.[8] Keil Software Getting Started with µVision2 – User’s Guide.[9] Keil Software Cx51 Compiler – User’s Guide.

Strony internetowe:

1. www.keil.com2. www.intel.com3. www.republika.pl/zaklad_techniki/index.php4. www.ampr.intertele.pl5. www.republika.pl/mikrokontrolery6. www.easy-soft.tdnet.pl/akademia/c/jc.html7. www.kmeif2.kmeif.pwr.wroc.pl/elektron/mikropro/ppt_proc/index.htm