wykład

Transkrypt

wykład
Podstawy techniki
mikroprocesorowej dla
elektroenergetyków
Multipleksacja
Zwielokrotnienie
czasowe
Demultipleksacja
Dane kanału 1
0
0
1
1
0
1
0
0
Dane kanałów
szczelina szczelina szczelina
czasowa czasowa czasowa
1
2
3
Dane kanału 2
1
1
0
1
1
0
0
0
001101001101100010010010
1
1
0
1
1
0
0
0
Dane kanału 2
Dane kanału 3
1
0
0
1
0
0
1
0
kierunek transmisji
1
0
0
1
0
0
1
0
Dane kanału 3
0
0
1
1
0
1
0
0
Dane kanału 1
U10
U11
U2
U1
RD
5
WR 36
A0
9
A1
8
RESET 35
CS 8255 6
D0
D1
D2
D3
D4
D5
D6
D7
PA0
PA1
PA2
PA3
PA4
PA5
PA6
PA7
RD
WR
A0
A1
RESET
CS
PB0
PB1
PB2
PB3
PB4
PB5
PB6
PB7
PC0
PC1
PC2
PC3
PC4
PC5
PC6
PC7
8255
R.Kowalik
4
3
2
1
40
39
38
37
1
2
3
4
5
6
7
8
1K
16
15
14
13
12
11
10
9
18
19
20
21
22
23
24
25
14
15
16
17
13
12
11
10
U12
U13
U14
S1
S2
S3
S4
S5
S6
S7
S8
16
15
14
13
12
11
10
9
34
33
32
31
30
29
28
27
U15
U16
U17
VCC
LED
LED
LED
LED
LED
LED
LED
VCC
U2
10K
1
2
3
4
5
6
7
8
D0
D1
D2
D3
D4
D5
D6
D7
LED
Informacje
Wykładowca: dr inż. Ryszard Kowalik
Tel. wew. PW: 5608
Email: [email protected]
Konsultacje: GM-213
Literatura:
1. TIETZE U., SCHENK CH.: Układy półprzewodnikowe,
Warszawa, WNT, 1996
2. Pełka R.: Mikrokontrolery architektura, programowanie, zastosowania,
Warszawa, WKŁ, 1999
3. Daca W.: Mikrokontrolery od układów 8 do 32-bitowych, ZNI MIKOM. Warszawa 2000
4. GAŁKA P., GAŁKA P.: Podstawy programowania mikrokontrolerów 8051,
Warszawa, ZNI “MIKOM”, 1995
5. Z.Czaja: Materiały do wykładu Mikrokontrolery i mikrosystemy 2003,
Politechnika Gdańska, 2003
www.pg.gda.pl/~zbczaja/mk.html
2
Spis tematów
INFORMACJE ................................................................................................................................................................. 2
SPIS TEMATÓW ............................................................................................................................................................. 3
WSTĘP .............................................................................................................................................................................. 6
1. ALGEBRA BOOLE'A ................................................................................................................................................. 8
1.1. PODSTAWOWE FUNKCJE LOGICZNE ........................................................................................................................ 9
1.2. INNE FUNKCJE LOGICZNE ..................................................................................................................................... 10
2. OPIS FUNKCJI LOGICZNYCH – UKŁADY KOMBINACYJNE....................................................................... 11
3. REALIZACJA UKŁADOWA FUNKCJI LOGICZNYCH .................................................................................... 13
3.1. REALIZACJA UKŁADOWA FUNKCJI LOGICZNYCH - PRZEGLĄD WŁAŚCIWOŚCI ........................................................ 17
4. UKŁADY LOGICZNE WYKORZYSTYWANE W TECHNICE MIKROPROCESOROWEJ ........................ 20
4.1. BRAMKI O WYJŚCIACH Z OTWARTYM KOLEKTOREM ............................................................................................ 20
4.2. BRAMKI O WYJŚCIACH TRÓJSTANOWYCH ............................................................................................................ 20
4.3. PROSTE UKŁADY KOMBINACYJNE ........................................................................................................................ 21
4.3.1. Proste układy kombinacyjne – dekoder 1 z n ........................................................................................... 22
4.3.2. Proste układy kombinacyjne – demultiplekser ......................................................................................... 22
4.3.3. Proste układy kombinacyjne – multiplekser ............................................................................................. 23
4.3.4. Proste układy kombinacyjne – dekoder priorytetowy............................................................................... 24
4.4. PROSTE UKŁADY SEKWENCYJNE.......................................................................................................................... 25
4.4.1. Przerzutniki FLIP-FLOP.......................................................................................................................... 25
4.4.1. Proste układy sekwencyjne – przerzutnik FLIP-FLOP............................................................................. 25
4.4.2. Proste układy sekwencyjne – przerzutnik RS-kluczowany........................................................................ 26
4.4.3. Proste układy sekwencyjne – przerzutnik D-kluczowany ......................................................................... 26
4.4.4. Proste układy sekwencyjne – przerzutnik wyzwalany impulsem............................................................... 27
4.4.5. Przerzutniki wyzwalane zboczem (single-edge-triggered flip flops)......................................................... 28
4.4.6. Liczniki dwójkowe .................................................................................................................................... 30
4.4.7. Asynchroniczne Liczniki dwójkowe .......................................................................................................... 31
4.4.8. Synchroniczne Liczniki dwójkowe ............................................................................................................ 32
4.4.9. Rejestry przesuwające .............................................................................................................................. 34
4.4.10. Rejestr przesuwający z wpisem równoległym......................................................................................... 35
4.5. PAMIĘCI............................................................................................................................................................... 36
4.5.1. Pamięci statyczne RAM ............................................................................................................................ 37
4.5.1. Pamięci statyczne RAM – parametry dynamiczne.................................................................................... 39
4.5.2. Pamięci dynamiczne RAM........................................................................................................................ 41
4.5.3. Pamięci dynamiczne RAM – układ sterowania (kontroler) ...................................................................... 43
4.5.4. Pamięci dwubramowe RAM ..................................................................................................................... 44
4.5.5. Pamięci RAM jako rejestr przesuwający.................................................................................................. 46
4.5.6. Pamięci FIFO........................................................................................................................................... 47
4.5.7. Pamięci stałe (ROM) ................................................................................................................................ 49
4.5.8. Pamięci ROM programowane maską....................................................................................................... 49
4.5.9. Pamięci programowane w sposób trwały (PROM) .................................................................................. 49
4.5.9. Pamięci stałe - PROM.............................................................................................................................. 50
4.5.10. Pamięci stałe kasowane promieniami UV - EPROM ............................................................................. 51
4.5.11. Pamięci stałe kasowane elektrycznie - EEPROM .................................................................................. 54
4.5.12. Pamięć błyskowa - FLASH..................................................................................................................... 55
4.5.13. Układy logiki programowalnej – PLD ................................................................................................... 61
4.6. UKŁADY WSPÓŁPRACY Z WEJŚCIAMI ORAZ WYJŚCIAMI BINARNYMI ..................................................................... 71
4.7. UKŁAD WSPÓŁPRACY Z WYŚWIETLACZEM 7 SEGMENTOWYM LED ..................................................................... 76
4.8. UKŁAD WSPÓŁPRACY Z KLAWIATURĄ.................................................................................................................. 79
4.9. UKŁAD WSPÓŁPRACY Z WYŚWIETLACZEM LCD .................................................................................................. 81
4.10. PRZETWORNIKI ANALOGOWO-CYFROWE ............................................................................................................ 86
4.10.1. Konwersja analogowo-cyfrowa – przetwornik SAR ............................................................................... 88
4.10.2. Konwersja analogowo-cyfrowa – przetwornik SS.................................................................................. 89
3
4.10.3. Konwersja analogowo-cyfrowa – przetwornik SigmaDelta (Σ∆)........................................................... 90
4.10.4. Błędy konwersji w przetwornikach A/C.................................................................................................. 94
4.11. UKŁADY PRÓBKUJĄCO-PAMIĘTAJĄCE (S/H) ...................................................................................................... 96
4.12. UKŁADY KLUCZY I MULTIPLEKSERÓW ANALOGOWYCH ..................................................................................... 99
4.13. UKŁADY PRZETWORNIKÓW C/A ...................................................................................................................... 104
5. BUDOWA I ZASADA DZIAŁANIA MIKROKONTROLERÓW O ARCH. STANDARDOWEJ .................. 107
5.1. STANDARDOWA ARCHITEKTURA MIKROKONTROLERA ....................................................................................... 109
5.2. UKŁAD WYKONAWCZY ...................................................................................................................................... 111
5.2.1. Jednostka ALU ....................................................................................................................................... 111
5.2.2. Rejestry................................................................................................................................................... 113
5.3. Tryby adresowania argumentów ............................................................................................................... 115
5.3.1. Formaty instrukcji .................................................................................................................................. 116
5.3.2. Podstawowe tryby adresowania ............................................................................................................. 118
5.3.3. Przykładowa lista instrukcji - mikrokontroler 80C51 ............................................................................ 124
5.4. UKŁAD STEROWANIA ......................................................................................................................................... 125
5.4.1. Układ oscylatora .................................................................................................................................... 125
5.4.2. Układ resetu ........................................................................................................................................... 129
5.4.3. Cykl wykonania rozkazu ......................................................................................................................... 131
5.4.4. Przerwania i sytuacje wyjątkowe ........................................................................................................... 135
5.4.5. Tryby redukcji mocy mikrokontrolera .................................................................................................... 140
5.5. ARCHITEKTURA SYSTEMU PAMIĘCI MIKROPROCESORA...................................................................................... 141
5.5.2. Segmentacja pamięci.............................................................................................................................. 146
5.5.3. Stos ......................................................................................................................................................... 147
6. DODATKOWE BLOKI FUNKCJONALNE MIKROKONTROLERÓW......................................................... 149
6.1. PORTY WEJŚCIA WYJŚCIA................................................................................................................................... 149
6.2. UKŁADY LICZNIKOWE/CZASOWE ....................................................................................................................... 153
6.2. UKŁADY LICZNIKOWE/CZASOWE – CD. (80C51) ................................................................................................ 159
6.3. UKŁADY NADZORUJĄCE – UKŁAD WATCHDOG .................................................................................................. 159
6.4. SPECJALIZOWANE UKŁADY KOMUNIKACJI SZEREGOWEJ .................................................................................... 161
6.4.1. Interfejs UART........................................................................................................................................ 162
6.4.2. Interfejs SPI............................................................................................................................................ 172
6.4.3. Interfejs I2C............................................................................................................................................ 177
6.4.4. Interfejs CAN.......................................................................................................................................... 180
6.4.5. Interfejs USB .......................................................................................................................................... 180
7. WSPÓŁPRACA Z UKŁADAMI ZEWNĘTRZNYMI .......................................................................................... 182
7.1. STEROWANIE SZYNAMI ...................................................................................................................................... 184
7.2. WSTRZYMANIE DOSTĘPU DO SZYNY .................................................................................................................. 186
7.3. PRZYŁĄCZENIE ZEWNĘTRZNYCH PAMIĘCI RAM/ROM/EPROM....................................................................... 188
7.4. WSPÓŁPRACA Z PAMIĘCIAMI EEPROM I BŁYSKOWYMI .................................................................................... 192
7.5. PRZYŁĄCZANIE PAMIĘCI EEPROM Z DOSTĘPEM SZEREGOWYM ....................................................................... 193
7.6. WSPÓŁPRACA Z PAMIĘCIAMI BŁYSKOWYMI ....................................................................................................... 196
7.7. BEZPOŚREDNI DOSTĘP DO PAMIĘCI .................................................................................................................... 202
8. MIKROKONTROLERY DSP................................................................................................................................. 203
8.1. STAŁOPRZECINKOWE DSP NA PRZYKŁADZIE ADSP 2181................................................................................. 203
8.2. ZMIENNOPRZECINKOWE DSP NA PRZYKŁADZIE ADSP-21061 SHARC ............................................................ 209
9. PROGRAMOWANIE MIKROKONTROLERÓW .............................................................................................. 212
9.1. PROGRAMOWANIE W JĘZYKU ASEMBLERA......................................................................................................... 212
9.1.1. Asemblery i makroasemblery ................................................................................................................. 214
9.1.2. Przykłady Makroasemblerów ................................................................................................................. 218
9.1.3. Przykłady programów asemblera........................................................................................................... 220
9.2. PROGRAMOWANIE W JĘZYKU C ......................................................................................................................... 223
9.2.1. Kompilatory języka C ............................................................................................................................. 223
9.2.2. Przykłady programów w języku C – przykład 1...................................................................................... 224
9.2.3. Przykłady programów w języku C – przykład 2...................................................................................... 225
9.2.4. Przykłady programów w języku C – przykład 3...................................................................................... 227
4
9.2.5. Przykłady programów w języku C – przykład 4...................................................................................... 229
9.3. NARZĘDZIA WSPOMAGAJĄCE URUCHAMIANIE SYSTEMÓW MIKROPROCE-SOROWYCH ........................................ 231
9.3.1. Monitory i programy śledzące................................................................................................................ 231
9.3.2. Symulatory.............................................................................................................................................. 233
9.3.3. Zintegrowane programy wspomagające uruchamianie ......................................................................... 236
10. LITERATURA........................................................................................................................................................ 238
11. DOKUMENTACJA STEROWNIKA DSM-51 WYK. W LABORATORIUM ................................................ 239
5
Wstęp
Poniżej przedstawiono schemat blokowy oraz ideowy układu mikroprocesorowego, który
będzie przez Państwa wykorzystywany w zajęciach laboratoryjnych w semestrze letnim.
6
Jak widać, aby przeanalizować działanie tego układu nie wystarczy poznanie jedynie zasady
działania mikroprocesora, trzeba także znać działanie innych układów, które z nim współpracują. Z
tego względu, naukę techniki mikroprocesorowej należy rozpocząć od przypomnienia
podstawowych wiadomości z zakresu algebry, elektroniki i techniki cyfrowej. Te dziedziny wiedzy
legły u postaw działania układów mikroprocesorowych.
1.
1.1.
1.2.
2.
3.
4.
ALGEBRA BOOLE’A
Podstawowe funkcje logiczne
Inne funkcje logiczne
OPIS FUNKCJI LOGICZNYCH – UKŁADY KOMBINACYJNE
REALIZACJA UKŁADOWA FUNKCJI LOGICZNYCH
UKŁADY LOGICZNE WYKORZYSTYWANE W TECHNICE
MIKROPROCESOROWEJ
7
1. Algebra BOOLE'A
Budowa układów cyfrowych opiera się na idei wielokrotnego stosowania niewielkiej liczby
podstawowych rodzajów układów logicznych. Sposób połączenia tych układów można uzyskać za
pomocą algebry Boole’a zwanej też algebrą łączeń.
W przeciwieństwie do zmiennej w zwykłej algebrze zmienna logiczna może przyjmować dwie
wartości dyskretne:
- zero logiczne
- jedynkę logiczną
Rozróżniamy trzy podstawowe działania na zmiennych logicznych:
- iloczyn (koniunkcja)
y = x1 ∩ x2 = x1 ∗ x2 = x1 x2
- suma (dysjunkcja)
y = x1 ∪ x2 = x1 + x2
- negacja
y=x
Dla tych działań obowiązuje szereg praw:
- prawo przemienności:
y = x1 ∗ x2 = x2 ∗ x1
y = x1 + x2 = x2 + x1
- prawo łączności:
y = x1 ∗ ( x2 ∗ x3 ) = ( x1 ∗ x2 ) ∗ x3
y = x1 + ( x2 + x3 ) = ( x1 + x2 ) + x3
- prawo rozdzielczości:
y = x1 ∗ ( x2 + x3 ) = x1 ∗ x2 + x1 ∗ x3
y = x1 + x2 ∗ x3 = ( x1 + x2 ) ∗ ( x1 + x3 )
- prawo pochłaniania:
y = x1 ∗ ( x1 + x2 ) = x1
y = x1 + x1 ∗ x2 = x1
- prawo tautologii:
y = x∗ x = x
y = x+x= x
- własności negacji:
y = x∗ x = 0
y = x + x =1
-
()
podwojona negacja:
y= x =x
-
prawo De’Morgana:
y = x1 ∗ x2 = x1 + x2
y = x1 + x2 = x1 ∗ x2
-
szereg praw dla działań z 0 i 1:
y = x ∗1 = x
y = x+0= x
y = x∗0 = 0
y = x +1 = 1
8
y = 0 =1
y =1= 0
Zauważmy, że w przedstawionych prawdach obowiązuje zasada dualności, mówiąca o tym, że
jeżeli w którejś z tożsamości zamienimy znaki “ ∗ ” na ”+” a “0” na “1”, to również
otrzymamy tożsamość.
1.1. Podstawowe funkcje logiczne
Bardzo często przy opisywaniu funkcji logicznych będziemy korzystać z tzw. “tablicy prawdy”.
Tablica 1.1 Tablica prawdy funkcji AND
X1
0
0
1
1
y = 1 wtedy i tylko wtedy, gdy x1 = 1 i x2 = 1
X2
0
1
0
1
Y
0
0
0
1
X2
0
1
0
1
Y
1
1
1
0
Tablica 1.2 Tablica prawdy funkcji OR
X1
0
0
1
1
y = 1 wtedy, gdy x1 = 1 lub x2 = 1
Przejdźmy do prezentacji fizycznej wspomnianych funkcji. Ze względu na to, że zmienne logiczne
przyjmują jedynie dwa stany pracy pod uwagę można brać tylko urządzenia o podobnych
właściwościach. Urządzeniami takimi są np. zestyki. W tej reprezentacji funkcji logicznej OR
odpowiada obwód przedstawiony na rysunku 1.1 (równoległe połączenie zestyków), natomiast
funkcji AND połączenie szeregowe zestyków (rysunek 1.2).
x1
x2
Rysunek 1.1. Realizacja funkcji OR na zestykach
x1
x2
Rysunek 1.2. Realizacja funkcji AND na zestykach
Prawo tautologii przybierze w tej reprezentacji następującą postać:
x1
x2
x
Rysunek 1.3. Przedstawienie prawa tautologii
Innym sposobem reprezentacji zmiennych logicznych mogą być poziomy napięć elektrycznych.
Jeżeli wyróżnimy dwa poziomy:
9
- H – wysoki, L – niski i przypiszemy im stany logiczne w następujący sposób H=1 i L=0, to
otrzymamy logikę dodatnią.
Przy przyporządkowaniu odwrotnym tzn.:
- H – wysoki, L – niski, ale wartość stanów H=0 i L=1, otrzymamy logikę ujemną.
Przy takiej reprezentacji podstawowe funkcje logiczne można realizować za pomocą odpowiednich
układów elektronicznych posiadających jedno lub wiele wejść oraz jedno wyjście (rysunek 1.4).
x1
x2
y
F(x)
xn
Rysunek 1.4. Układ elektryczny realizujący funkcję logiczną
Ponieważ istnieje wiele rozwiązań układowych wspomnianego układu, dla uproszczenia
wprowadzono symbole oznaczające funkcję logiczną realizowana przez układ, a nie mówiące nic o
jego budowie wewnętrznej.
x1
x2
x1
&
y=x1+x2
x2
y=x1+x2
x2
x1
x1
x1
>1
y=x1+x2
x2
y=x1+x2
x2
y=x1+x2
x2
x1
x2
x1
1
x1
y=x
y=x
x2
y=x1+x2
x1
y=x
x2
Rysunek 1.5. Symbole podstawowych funkcji logicznych
Zauważmy, że pomimo pewnej realizacji układowej opis wejść i wyjść układu pozostał zgodny z
opisem logicznym i nie odzwierciedla poziomów napięć występujących w układach.
1.2. Inne funkcje logiczne
Poprzednio pokazano, że dowolną funkcję logiczna można przedstawić za pomocą
odpowiedniej kombinacji funkcji OR, AND i NOT. Istnieją jednak funkcje złożone, które w
technice występują na tyle często, że nadano im własne nazwy. Funkcjami tymi są:
- funkcja równoważności, przyjmuje wartość y = 1 wówczas, gdy obie zmienne wejściowe są
sobie równe:
y = EQUIV ( x1 , x2 ) = x1 x2 + x1 x2
- funkcja nierównoważności, jest negacją równoważności; y = 1 gdy zmienne wejściowe są
różne.
y = ANTIV ( x1 , x2 ) = x1 x2 + x1 x2
Z tablicy prawdy wynika jeszcze inna interpretacja funkcji nierównoważności; funkcja ta jest
zgodna z funkcja OR dla wszystkich wartości z wyjątkiem przypadku, gdy wszystkie zmienne
wejściowe są równe jeden. Dlatego nosi ona nazwę EXCLUSIVE OR (EXOR) lub sumy modulo 2
(MOD 2)
y = EXOR( x1 , x2 ) = x1 x2 + x1 x2
Zgodnie z tym funkcję równoważności można nazwać funkcją EXCLUSIVE NOR (EXNOR)
y = EXNOR ( x1 , x2 ) = x1 x2 + x1 x2
10
2. Opis funkcji logicznych – układy kombinacyjne
Zwykle opis funkcji logicznej podany jest w postaci wspomnianej tablicy prawdy. W celu
znalezienia funkcji logicznej spełniającej daną tablicę prawdy należy:
- w tablicy prawdy wyszukać wiersze, których wartość zmiennej wyjściowej wynosi “1”
- dla każdego z wierszy utworzyć iloczyn tworzących go zmiennych wejściowych w ten sposób,
-
że jeżeli wartość danej zmiennej wynosi “1”, to piszemy “ xi ”, jeżeli “0” piszemy xi .
poszukiwaną funkcję otrzymujemy tworząc sumę wszystkich znalezionych iloczynów.
Przykład:
Tablica 2.1. Przykład tablicy prawdy
Wiersz
x1
x2
x3
y
1
0
0
0
0
2
0
0
1
0
3
0
1
0
1
4
0
1
1
0
5
1
0
0
1
6
1
0
1
0
7
1
1
0
1
8
1
1
1
0
W wierszach 3,5,7 jest y = 1 . Najpierw musimy więc utworzyć iloczyn dla tych wierszy:
-
wiersz 3
I 3 = x1 x2 x3
-
wiersz 5
I 5 = x1 x2 x3
- wiersz 7
I 7 = x1 x2 x3
poszukiwana funkcja jest sumą iloczynów:
y = I3 + I5 + I7
y = x1 x 2 x3 + x1 x 2 x3 + x1 x 2 x3
Po znalezieniu funkcji przystępujemy do jej uproszczenia stosując podane wcześniej prawa algebry
Boole’a.
y = x1 x 2 x3 + x1 x 2 x3 + x1 x 2 x3 = x1 x 2 + x1 ( x 2 + x 2 ) x3 = ( x1 x 2 + x1 ) x3 = ( x1 + x 2 )( x1 + x1 ) x3
[
]
y = ( x1 + x 2 ) x3
Jeżeli w tablicy prawdy zmienna wyjściowa częściej przybiera wartość “1” wygodniej jest wstępnie
zanegować tablicę, a następnie po znalezieniu funkcji opisującej poddać ją negacji. Innym
sposobem znalezienia funkcji opisującej jest zastosowanie tzw. tablicy Karnaugha. Tworzy się ją
następująco:
- wartości zmiennych wejściowych wpisuje się na brzegach tablicy w taki sposób, aby przy
przejściu do kolejnej kratki wartość zmieniała się co najwyżej na jednej pozycji
- w kratki wpisuje się wartość zmiennej wyjściowej dla wartości zmiennych wejściowych
znajdujących się na brzegach
- dla każdej kratki zawierającej wartość “1” tworzymy iloczyn zmiennych wejściowych wg
przykładu
- sumujemy otrzymane iloczyny otrzymując szukaną funkcję
(Jeżeli w kwadracie lub prostokącie o parzystej liczbie kratek są same jedynki, iloczyn całej grupy
można otrzymać bezpośrednio, uwzględniając tylko zmienne wejściowe, dla wszystkich kratek
grupy mają stałą wartość.)
Przykład:
11
Tablica
tablicy Karnaugha
Karnaugha
Tablica 2.2.
1.4. Przykład
Przykład tablicy
x1 x2
0 0
0 1
1 1
1 0
x3
0
1
0
1
1
1
0
0
0
0
Szukana funkcja to:
x1 x3 + x2 x3 = ( x1 + x 2 ) x3
12
3. Realizacja układowa funkcji logicznych
W dotychczasowych rozwiązaniach zajmowaliśmy się elementami logicznymi nie troszcząc się o
ich budowę wewnętrzną. Ma to swoje uzasadnienie w technice, bowiem współczesne układy
scalone mają zaznaczone jedynie zaciski zasilania oraz wejść i wyjść.
Do realizacji poszczególnych podstawowych funkcji logicznych istnieje wiele technik układowych,
które różnią się między sobą:
- poborem mocy - ∆P
- poziomami “L” i “H”
- czasem propagacji - t
- obciążalnością wyjścia (Termin obciążalność wyjścia bramki określa, ile wejść bramek tej
samej rodziny można dołączyć do jednego wyjścia bez zmniejszania jej odporności na
zakłócenia.)
W ciągu kilkudziesięciu lat historii układów logicznych mieliśmy do czynienia z wieloma
technikami układowymi, z których duża część nie jest już stosowana. Do technologii, które odeszły
w zapomnienie możemy zaliczyć:
- układy RTL – (resistor transistor logic) - ∆P = 5mW t = 25ns
- układy DTL – (diode transistor logic) - ∆P = 180mW t = 175ns
- układy TTL – (transistor transistor logic) - ∆P = 10mW t = 10ns
- układy ECL – (emitter coupled logic) - ∆P = 25mW t = 2ns
Obecnie używane technologie to:
- TTL-LS – (coraz mniej) - ∆P = 2mW t = 10ns
- HC, HCT, ACT – (high speed cmos) - ∆P = 0,3µW / kHz t = 10ns
Wyjaśnijmy zasadę działania przykładowych bramek z obu grup, zaczynając od TTL i TTL LS.
+5V
+5V
R1
4k
+5V
R2
1,6k
R4
130
T4
T1
D
T2
U1
T3
U2
Uwy
R3
1k
Rysunek 3.1. Standardowa bramka NAND TTL
W standardowej bramce TTL przedstawionej na rysunku 3.1, jeżeli wszystkie wejścia są w stanie
”H”, prąd płynie przez rezystancję R1 i złącze baza-kolektor tranzystora wejściowego
spolaryzowane jest w kierunku przewodzenia do bazy tranzystora T2, powodując jego
przewodzenie. Jeżeli na jedno z wejść doprowadzimy niskie napięcie, odpowiednie złącze bazaemiter zaczyna przewodzić i przejmuje prąd bazy T2. powoduje to zatkanie tranzystora T2 i
przejście wyjścia do stanu “H”. Wzmacniacz w układzie TTL składa się z tranzystora sterującego
T2 i przeciwsobnego wzmacniacza wyjściowego. Gdy tranzystor T2 przewodzi, przewodzi również
T3, a T4 jest zatkany. Na wyjściu jest poziom “L”, a tranzystor T3 może przyjmować duże prądy,
pochodzące np. z dołączonych wejść bramek (w stanie “L” prąd wypływa z wejść). Gdy tranzystor
13
T2 jest zatkany , zatkany jest również T3. W tym przypadku T4 przewodzi i daje poziom “H” na
wyjściu. Tranzystor T4 pracujący jako wtórnik emiterowy może teraz dostarczać dużego prądu
wyjściowego i dzięki temu szybko ładować pojemności obciążenia. Standardowe układy TTL tego
rodzaju , jak pokazane na rysunku 3.1, są obecnie spotykane rzadko z powodu dużego czasu
propagacji wywołanego nasyceniem tranzystorów. Nasyceniu można zapobiec przez dołączenie
diody Schottky’ego równolegle do złącza kolektor-baza (rysunek 3.2). dzięki napięciowemu
sprzężeniu zwrotnemu przy przewodzeniu tranzystora uniemożliwia ona spadek napięcia kolektoremiter poniżej wartości ok. 0,3V.
C
C
B
B
E
E
Rysunek 3.2.Tranzystor z diodą Schottky’ego przeciwdziałającą nasyceniu i jego symbol graficzny
Bramka TTL zbudowana z takich “tranzystorów Schottky'ego" (bramka TTL-S) jest przedstawiona
na rys. 3.3. Jest to uproszczony schemat bramki TTL-S małej mocy, tzw. bramki TTL-LS (Iow
power Schottky). Z porównania ze standardową bramką TTL z rys. 3.1 widać, że ma ona
rezystancje kolektorowe pięć razy większe, dzięki czemu pobór mocy jest pięć razy mniejszy i
wynosi tylko 2 mW. Mimo to czas propagacji bramki nie jest większy i wynosi 10 ns. Wejściowy
zespół diod jest zbudowany tak, jak w układzie DTL, z oddzielnych diod. Dioda D (rys. 3.1) w
stopniu wyjściowym, służąca do przesunięcia potencjału, została tu zastąpiona układem Darlingtona
T3.
+ 5V
20kΩ
+ 5V
8kΩ
+ 5V
Pstr = 2mW
120Ω
t p = 10ns
T3
D1
T1
U1
U2
D2
3kΩ
T2
U wy
Rysunek 3.3. Bramka NAND TTL LS (74LS00)
Charakterystykę przejściową inwertera TTL-S małej mocy przedstawiono na rys. 3.4. Nietrudno
zauważyć, że poziom przełączania wynosi ok. 1,1 V. Charakterystyczne dla układów TTL
tolerancje są tu zachowane z dużym zapasem. Przy najwyższym dopuszczalnym poziomie L na
wejściu, równym 0,8 V, na wyjściu musi być poziom H wynoszący co najmniej 2,4 V. Przy
najniższym poziomie H na wejściu, równym 2,0 V, poziom L na wyjściu może wynosić najwyżej
0,4 V.
14
4,8
U wy
[V ]
3,2
2,4
1,6
0,8
0
0,4
0,8
1,2
2,0
1,6
U we [V ]
2,8
Rysunek 3.4. Charakterystyka przejściowa bramki TTL LS (Zakreskowane granice tolerancji)
Bramki CMOS są rodziną układów logicznych odznaczającą się szczególnie niskim poborem mocy.
Układ inwertera pokazany jest na rysunku 3.5.
USS
G
D
T2
typu P
Uwe
S
S
G
typu N
T1
D
Uwy
Rysunek 3.5. Inwerter CMOS
Zwraca uwagę fakt, że układ ten składa się wyłącznie z tranzystorów polowych MOS z kanałem
wzbogaconym. Źródło tranzystora z kanałem typu n jest połączone z masą, a tranzystora typu p – z
napięciem zasilania USS. Oba tranzystory pracują więc w układzie ze wspólnym źródłem i
wzmacniają napięcie wejściowe, odwracając jego fazę. Każdy z tranzystorów stanowi równocześnie
rezystancję obciążenia drugiego tranzystora. Napięcie progowe obu tranzystorów wynosi około
1,5V. Dlatego też przy napięciu zasilania równym 5V przynajmniej jeden z tranzystorów
przewodzi. Jeżeli przyjmiemy UWE = 0, przewodzi tranzystor T2 z kanałem typu p, a tranzystor T1
z kanałem typu n jest zatkany. Napięcie wyjściowe jest równe USS. Dla UWE = USS tranzystor T2
jest zatkany, a T1 przewodzi. Napięcie wyjściowe jest równe zeru. Nietrudno zauważyć, że w stanie
ustalonym przez układ nie płynie żaden prąd. Niewielki prąd płynie tylko podczas przełączania.
Poziomy logiczne zależą od wybranego napięcia zasilania. Dopuszczalny zakres napięcia zasilania
układów CMOS jest bardzo duży. Dla układów z bramką krzemową wynosi od 3 do 6V, a dla
układów z bramką metalową od 3 nawet do 15V jak pokazano na rysunku 3.6.
15
5
Uss
Uwy [V ]
4
3
2
I ss
1
0
1
2
4 Uwe [V ] 5
3
Rysunek 3.6. Charakterystyki przejściowe bramki CMOS przy napięciu 5V
Tablica 3.1.
USS = 5V
Układ standardowy
Układ szybki
Typ
74C04
74HC04
Moc strat
0,3µW/kHz
0,5µW/kHz
Czas propagacji
90ns
10ns
Prąd pobierany przez bramkę CMOS ma trzy składowe:
1. Gdy napięcie wejściowe jest stałe i równe zeru lub Uss, płynie bardzo mały prąd upływu
bramek rzędu kilku mikroamperów.
2. Gdy sygnał wejściowy zmienia stan, przez oba tranzystory przepływa prąd przewodzenia.
3. Największy wpływ ma jednak przeładowywanie pojemności tranzystora CT.
Przy ładowaniu jest magazynowana energia — CTUgS; równocześnie taka sama energia jest
przekształcana w tranzystorze na ciepło. Przy rozładowaniu energia zmagazynowana w kondensatorze
jest również przetwarzana, na ciepło. W cyklu L-H-L przetworzona zostaje energia W=- CTC/js.
Wynika stąd moc strat Pdiss = W/ 1 = W-f= CTUlsf. Ze względu na fakt, że straty wywołane przez
prąd przewodzenia są również proporcjonalne do częstotliwości, można je uwzględnić, definiując
pojemność mocy strat. Jest ona nieco większa od pojemności CT samego tranzystora. Potencjał
rozwartego wejścia układu CMOS jest nieokreślony. Dlatego też wejścia układów CMOS muszą
być połączone z masą lub napięciem Uss. Jest to zalecane także w przypadku nieużywanych bramek,
gdyż w przeciwnym razie na ich wejściach może ustalić się taki potencjał wejściowy, przy którym
przez oba tranzystory popłynie prąd przewodzenia, co pociągnie za sobą wzrost strat. Elektrody
bramek tranzystorów polowych z izolowaną bramką są bardzo wrażliwe na ładunki statyczne. W celu
uniknięcia uszkodzeń wejścia układów scalonych MOS są zabezpieczone diodami w sposób
pokazany na rys. 3.7. Mimo to należy zachować ostrożność. Diody zabezpieczające powodują również
dalsze ograniczenie, które należy uwzględnić przy stosowaniu bramek CMOS.
U SS
U SS
D4
R1
D2
D1
D3
U SS
T2
T1
U wy
Rysunek 3.7. Zabezpieczenie bramek CMOS od wpływu ładunków statycznych
16
Wskutek izolacji złączowej obu tranzystorów polowych T1 i T2, między zaciskami napięcia zasilania
powstaje pasożytniczy tyrystor, jak to pokazano na rys. 3.8.
Rysunek 3.8. Pasożytniczy tyrystor w bramce CMOS
W normalnych warunkach tyrystor ten nie wpływa na pracę układu, ponieważ tranzystory T3 i T4 są
zatkane, a ich prądy zerowe płyną przez rezystancję R2 lub R3. Jeżeli jednak jedna z działających
jako dodatkowe emitery diod zabezpieczających zostanie spolaryzowana w kierunku przewodzenia,
może to spowodować włączenie tyrystora T3, T4. Oba tranzystory przechodzą wtedy w stan
przewodzenia i powodują zwarcie napięcia zasilania. Występujące przy tym prądy o dużej wartości
powodują zniszczenie układu scalonego. Dla uniknięcia tego zjawiska, zwanego zatrzaskiwaniem,
napięcie wejściowe nie powinno być niższe od potencjału masy, ani wyższe od napięcia zasilania.
Jeżeli nie da się tego wykluczyć, należy przynajmniej ograniczyć prąd płynący przez diody
zabezpieczające do wartości wynoszącej w zależności od technologii od 1 do 100mA. Wystarcza do
tego najczęściej zwykła rezystancja szeregowa. Załączanie pasożytniczego tyrystora również
nastąpić po podaniu na wyjście napięcia przekraczającego zakres napięć zasilania.
3.1. Realizacja układowa funkcji logicznych - przegląd właściwości
W tablicy 3.2 przedstawiono przegląd najczęściej używanych rodzin układów cyfrowych. Podane
dane techniczne odnoszą się do pojedynczej bramki. Nietrudno zauważyć, że każda technika
realizacyjna istnieje w różnych wykonaniach, różniących się od siebie poborem mocy i czasem
propagacji bramek. Wskaźnikiem jakości rodziny układów logicznych jest iloczyn czasu propagacji i
strat mocy bramki (wskaźnik energetyczny). Mówi on, czy bramka oprócz małych strat mocy ma
również mały czas propagacji. Można więc zauważyć, że nowsze rodziny, jak 74AS, 74ALS, 74F,
10H100 i 100.100 mają bardzo mały wskaźnik energetyczny. Jest to spowodowane zastosowaniem
izolacji dielektrycznej i związaną z tym mniejszą wartością pojemności obciążających elementy przy
przełączaniu, niż ma to miejsce w przypadku starszych rodzin z izolacją złączową.. Dużym postępem
technologicznym są również układy CMOS z bramką krzemową. Przy takich samych właściwościach,
są one dziesięć razy szybsze od typów z bramką metalową. Większość rodzin układów cyfrowych
oferowanych przez różnych producentów jest oznaczana symbolami różniącymi się tylko częścią
literową umieszczoną na początku symbolu. Moc pobierana przez elementy z różnych rodzin
układów cyfrowych jest bardzo różna. Z wykresu na rys. 3.9 widać, że układy CMOS są bardzo
korzystne przy małych częstotliwościach. Powyżej l MHz różnice mocy strat między układami TTL-S
małej mocy i układami CMOS są niewielkie. Godnym podkreślenia jest fakt, że w tym zakresie
częstotliwości rośnie również pobór mocy przez układy TTL. Przyczyną tego jest prąd płynący przez
przeciwsobny stopień wyjściowy podczas każdego procesu przełączania, powodujący znaczne
zwiększenie poboru mocy przy większych częstotliwościach.
17
Tablica 3.2. Przegląd najbardziej rozpowszechnionych rodzin układów TTL, ECL i CMOS
Wady tej nie mają układy ECL. Dlatego też przy częstotliwościach powyżej 30 MHz układy ECL
odznaczają się samymi zaletami z wyjątkiem ich wysokiej ceny.
Rysunek 3.9. Zależność mocy strat od częstotliwości pracy układu
18
Warunkiem wstępnym prawidłowej pracy cyfrowych układów scalonych jest poprawne
doprowadzenie napięć zasilających. Wszystkie rodziny układów cyfrowych wytwarzają przy
przełączaniu impulsy prądowe w przewodach doprowadzających prąd zasilania. Ponieważ
wszystkie sygnały mają za punkt odniesienia potencjał masy, jest wymagane wykonywanie we
wszystkich układach scalonych połączeń masy o małej rezystancji i indukcyjności. Na płytce
drukowanej warunek ten można spełnić najlepiej przez wykonanie masy w postaci siatki. Przy
częstotliwościach powyżej 50 MHz należy raczej wykonać masę w postaci metalizacji całej jednej
strony płytki. Aby impulsy prądowe powstające przy przełączaniu nie zakłócały zasilania, musi być
ono doprowadzone do układów scalonych w sposób niskorezystancyjny i bezindukcyjny. Jeśli masa
jest dobra, zakłócenia impulsowe mogą być odfiltrowane kondensatorami blokującymi. Stosuje się
do tego kondensatory ceramiczne o pojemności 10... 100 nF. Nie nadają się do tego celu
kondensatory elektrolityczne, ze względu na złe właściwości przy wielkich częstotliwościach.
Przeciętnie jeden kondensator powinien przypadać na 2... 5 układów scalonych.
19
4. Układy logiczne wykorzystywane w technice mikroprocesorowej
4.1. Bramki o wyjściach z otwartym kolektorem
Niekiedy występuje problem logicznego połączenia wyjść dużej liczby bramek. Przy np.
dwudziestu wyjściach byłaby potrzebna do tego bramka o dwudziestu wejściach, do których
musiałoby prowadzić dwadzieścia oddzielnych przewodów. Kłopotu tego można uniknąć, stosując
bramkę z otwartym kolektorem. Jej stopień wyjściowy stanowi tranzystor npn którego emiter jest
połączony z masą. Takie wyjścia można w odróżnieniu od stosowanych zazwyczaj przeciwsobnych
stopni wyjściowych – bez obaw łączyć równolegle i zaopatrzyć we wspólny rezystor kolektorowy
(rysunek 4.1).Potencjał wyjścia przyjmuje stan „H” tylko wówczas, gdy wszystkie wyjścia są w
stanie „H”. W logice dodatniej otrzymamy więc funkcję AND. Jednakże wiadomo, że wyjście
przechodzi w stan „L” wówczas, gdy jedno lub więcej wyjść ma stan „L”. W logice ujemnej
otrzymamy więc funkcję OR. Ponieważ funkcja logiczna została zrealizowana przez zewnętrzne
połączenia galwaniczne, mówimy wówczas o iloczynie galwanicznym lub sumie galwanicznej.
Ponieważ wyjścia bramek mają małą rezystancję tylko w stanie „L”, można je nazwać również
wyjściami z aktywnym stanem niskim. Symbol bramki z otwartym kolektorem przedstawia rysunek
4.2. za pomocą wyjść z otwartym kolektorem możemy też zrealizować funkcję OR, stosując iloczyn
galwaniczny dla zmiennych zanegowanych. Zgodnie z prawem de Morgana mamy:
y1 + y2 + ... + yn = y1 * y2 * ... * yn
+
Rc
B1
B2
Bn
Uwy
Rysunek 4.1. Łączenie wyjść bramek z otwartym kolektorem
x1
y
x2
Rysunek 4.2. Symbol bramki z otwartym kolektorem
Wadą układów z otwartym kolektorem jest wolniejsze narastanie napięcia wyjściowego niż w
przypadku elementów z wyjściem przeciwsobnym, ponieważ przełączane pojemności mogą się
naładować tylko przez rezystancję Rc.
4.2. Bramki o wyjściach trójstanowych
Istnieje jeszcze jeden ważny przykład zastosowania, w którym równoległe połączenie wyjść
bramek prowadzi do uproszczenia układu: jest to przypadek, gdy jedna z wielu bramek ma
decydować o stanie linii sygnałowej w tzw. Magistrali. Zadanie to można rozwiązać przy użyciu
bramek z otwartym kolektorem ustawiając w wysoko-impedancyjny stan „H” wszystkie wyjścia z
wyjątkiem jednego. Zasadniczej wady tego rozwiązania, małej szybkości narastania napięcia
20
wyjściowego, można w tym specyficznym zastosowaniu uniknąć, stosując zamiast bramek z
otwartym kolektorem tzw. bramki z wyjściem trójstanowym. Jest to typowe wyjście przeciwsobne z
tym, że za pomocą dodatkowego sygnału sterującego można je przełączyć w stan tzw. wysokiej
impedancji. Stan ten nosi również nazwę stanu Z. Zasadę realizacji takiego układu przedstawiono
na rysunku 4.3, na rysunku widać też jego symbol graficzny.
+ 5V
EN
&
T2
y
&
X
EN
X
EN 1
T1
y
Rysunek 4.3. Inwerter z wyjściem trójstanowym i jego symbol graficzny
Jeśli sygnał zezwolenia EN=1, układ działa jak zwykły inwerter: dla x=1 mamy z1=0 i z2=1,
tzn. T1 jest zatkany, a T2przewodzi. Jeżeli jednak zmienna sterująca EN=0, to z1=z2=0 i oba
tranzystory wyjściowe są zatkane. Jest to stan wysokiej impedancji Z.
4.3. Proste układy kombinacyjne
Przez pojęcie układu kombinacyjnego rozumie się układ cyfrowy nie zawierający pamięci.
Zmienne wyjściowe są określone jednoznacznie przez zmienne wejściowe. Stanowi to kryterium
odróżniające układy kombinacyjne od układów sekwencyjnych, w których zmienne wyjściowe
zależą dodatkowo od stanu układu, czyli od jego przeszłości. W układach kombinacyjnych zmienne
wyjściowe można przyporządkować zmiennym wejściowym za pomocą tabel prawdy lub funkcji
logicznych. Do realizacji technicznej układów kombinacyjnych można stosować pamięci stałe
ROM (read only memory), w których zapisuje się tabele prawdy. Zmienne wejściowe są wówczas
adresami. Druga możliwość polega na użyciu bramek lub ukladów logiki programowalnej PLD
(programmable logic devices), za pomocą których realizuje się funkcje logiczne. W dalszym ciągu
zajmiemy się kilkoma prostymi układami. Układy kombinacyjne są często stosowane do przeliczeń
i przekodowywania liczb. Aby te liczby móc przedstawić za pomocą zmiennych logicznych, należy
je przekształcić w ciąg informacji dwuwartościowych (binarnych). Jedna taka pozycja binarna nosi
nazwę bitu. Specjalnym przypadkiem binarnego przedstawienia liczb jest kod dwójkowy, w którym
poszczególne pozycje są uszeregowane według rosnących potęg liczby 2. Cyfra 1 jest wtedy
identyfikowana z logiczną jedynką, a cyfra 0 - z zerem logicznym. Zmienną logiczną przypisaną
poszczególnym pozycjom będziemy oznaczać małymi literami, a całą liczbę - wielką literą. Npozycyjna liczba ma więc w kodzie dwójkowym postać
XN = xN-12N-1 + xN-2 2N-2 + ... + x121 + x020
Należy oczywiście zawsze rozróżniać, czy chcemy przeprowadzić działanie arytmetyczne na
cyfrach, czy też zrealizować funkcję zmiennych logicznych. Różnicę tę wyjaśnimy jeszcze raz na
przykładzie. Załóżmy, że chcemy dokonać obliczeń odpowiadających wyrażeniu 1 + 1. Jeżeli znak
„+" potraktujemy jako rozkaz dodawania w systemie dziesiętnym, otrzymamy zależność: 1+1=2
21
Natomiast dodawanie w systemie dwójkowym daje:
1 + 1 = 10B (czytaj: jeden zero).
Jeżeli znak „+" potraktujemy jako sumę zmiennych logicznych, otrzymamy:
1+1=1
4.3.1. Proste układy kombinacyjne – dekoder 1 z n
Dekoder 1 z n jest układem o n wyjściach i log2 n wejściach. Wyjścia y1 są ponumerowane od 0 do
(n - 1). Wyjście jest w stanie jeden wtedy, kiedy wprowadzona liczba dwójkowa A jest równa
numerowi tego wyjścia. W poniższej tablicy przedstawiono tablicę prawdy dekodera 1 z 4. Zmienne
a0 i a1 przedstawiają liczbę A w kodzie dwójkowym. Można z niej bezpośrednio odczytać postać
normalną sumy dla funkcji konwersji kodu. Odpowiednią realizację przedstawiono na rysunku 4.4.
1
a0
a1
A
0
1
2
3
a1
0
0
1
1
1
a0
0
1
0
1
y3
0
0
0
1
&
y0
&
y1
&
y2
&
y3
y2
0
0
1
0
y1
0
1
0
0
y0
1
0
0
0
Rysunek 4.4. Realizacja funkcji dekodera
Przy realizacji scalonej w postaci układu monolitycznego, zamiast bramki AND używa się często
bramki NAND. Zmienne wyjściowe są więc najczęściej zanegowane.
Tablica 4.1. Najczęściej używane typy dekoderów 1 z n
Typy układów scalonych:
dziesięciowyjściowe
TTL
74LS42
CMOS
4028
4.3.2. Proste układy kombinacyjne – demultiplekser
Za pomocą demultipleksera można doprowadzać informację wejściową do różnych wyjść. Stanowi
on rozszerzenie dekodera 1 z n. Zaadresowane wyjście nie przechodzi do stanu jeden, lecz
przyjmuje wartość zmiennej wejściowej d. Na rysunku 4.5 pokazano zasadę jego pracy, posługując
się bramkami logicznymi. Jeżeli x = const. = 1, demultiplekser pracuje jako dekoder 1 z n.
Najczęściej używane typy demultiplekserów zebrano w tablicy poniżej.
22
a0
a1
1
1
d
A
0
1
2
3
a1
0
0
1
1
a0
0
1
0
1
y3
0
0
0
d
&
y0
&
y1
&
y2
&
y3
y2
0
0
d
0
y1
0
d
0
0
y0
1
0
0
0
Rysunek 4.5. Realizacja funkcji demultipleksera
Tablica 4.2. Najczęściej używane typy demultiplekserów
Typy układów scalonych:
16 wyjściowe
8 wyjściowe
TTL
74LS154
74LS138
CMOS
5414
74HC138
4.3.3. Proste układy kombinacyjne – multiplekser
Układ działający odwrotnie do demultipleksera nazywa się multiplekserem. Wykorzystując schemat
ideowy z rys. 4.5 można go zrealizować przez zamianę wyjścia z wejściem. Powstaje wówczas
układ przedstawiony na rys. 4.6. Na tej podstawie można w bardzo prosty sposób wytłumaczyć jego
działanie: dekoder 1 z n wybiera to z n wejść, którego numer jest zgodny z wprowadzoną liczbą, i
łączy je z wyjściem. Na rysunku 4.6. przedstawiono także odpowiednią realizację multipleksera za
pomocą bramek logicznych.
Rysunek 4.6. Zasada działania multipleksera i jego układ logiczny
W technice CMOS multiplekser można zrealizować zarówno za pomocą bramek, jak i kluczy
analogowych (bramek transmisyjnych – transmission gates). Jak widać z porównania rys. 4.5 i 4.6,
23
multiplekser zbudowany przy zastosowaniu kluczy analogowych staje się identyczny z
demultiplekserem. W tym przypadku układ nosi nazwę analogowego multipleksera /
demultipleksera.
Rysunek 4.7. Multiplekser z
bramkami z otwartym kolektorem
Rysunek 4.8. Multiplekser z bramkami
trójstanowymi
Potrzebną w multiplekserach funkcję OR można zrealizować w postaci sumy galwanicznej, np.
wykorzystując bramki z otwartym kolektorem (rys. 4.7). Ponieważ w logice dodatniej otrzymuje się
w tym przypadku funkcję AND, należy - tak jak na rys. 4.1 - przejść na sygnały zanegowane. Jeżeli
chcemy uniknąć wady związanej z otwartym kolektorem, tzn. wzrostu czasu propagacji tpLH,
możemy połączyć równolegle wyjścia bramek trójstanowych, z których zawsze tylko jedna jest
włączona. To rozwiązanie przedstawiono na rys. 4.8. Możliwości realizacji funkcji OR
przedstawione na rys. 4.7 i 4.8 nie są stosowane w scalonych rnultiplekserach. Mają one jednak
znaczenie wówczas, gdy źródła sygnałów wejściowych multipleksera są rozmieszczone w różnych
miejscach.
Najczęściej używane typy multiplekserów zestawiono w tabl. 4.3.
Tablica 4.3. Scalone multipleksery. CMOS analogowy oznacza multiplekser/demultiplekser z bramkami
transmisyjnymi
4.3.4. Proste układy kombinacyjne – dekoder priorytetowy
Do zamiany kodu 1 z n na kod dwójkowy można zastosować dekoder priorytetowy. Na jego
wyjściach pojawia się liczba dwójkowa odpowiadająca najwyższemu numerowi wejścia, na którym
jest jedynka. Wartość zmiennych wejściowych o niższych numerach nie jest istotna. Nazwa dekoder
priorytetowy wzięła się stąd, że za pomocą tego układu można zdekodować nie tylko kod 1 z n, lecz
także kod, w którym jedynki występują we wszystkich pozycjach położonych niżej. Tablica prawdy
kodera priorytetowego jest przedstawiona tablicy 4.4.
24
Tablica 4.4. Tablica prawdy kodera priorytetowego
J
0
!
7
3
4
5
6
7
8
9
x9
0
0
0
0
0
0
0
0
0
1
X8
0
0
0
0
0
0
0
D
1
x
X6
0
0
0
0
0
0
0
1
x
x
X6
0
0
0
0
0
0
1
x
x
x
X5
0
0
0
0
0
1
x
x
x
x
X4
0
0
0
0
1
x
x
x
x
x
X3
0
0
0
1
x
x
x
x
x
x
X2
0
0
1
x
x
x
x
x
x
x
X1
0
1
x
x
x
x
x
x
x
x
y1
0
0
0
0
0
0
0
0
1
1
y1
0
0
0
0
1
1
1
1
0
0
y1
0
0
1
1
0
0
1
1
0
0
yo
0
1
0
1
0
1
0
1
0
1
Tablica 4.5. Najczęściej używane dekodery priorytetowe
Typy układów scalonych:
Kod 1 z 10
Kod 1 z 8 z możliwością rozszerzenia
TTL
SN 74147
SN74148
CMOS
5414
MC 14532
4.4. Proste układy sekwencyjne
Przez pojęcie układu .sekwencyjnego rozumie się taki układ elementów cyfrowych służący
do realizacji zależności logicznych, który może zapamiętywać poszczególne stany zmiennych.
W odróżnieniu od układów kombinacyjnych zmienne wyjściowe y zależą więc nie tylko od
zmiennych wejściowych x, lecz dodatkowo od przeszłości, która jest reprezentowana przez stan
przerzutników (wewnętrzny stan układu).
4.4.1. Przerzutniki FLIP-FLOP
Jeżeli dwie bramki NOR połączymy w sposób pokazany na rys. 4.9, to otrzymamy przerzutnik
(FLIP-FLOP). Ma on dwa dopełniające się wyjścia Q i Q oraz dwa wejścia S (set) i R (reset). Jeżeli
na wejścia podamy S = 1 i R = 0, otrzymamy:
Q = S + Q =1+ Q = 0 , Q = R + Q = 0 + 0 = 1
Oba wyjścia przyjmują więc rzeczywiście stany dopełniające się.
Rysunek 4.9. Przerzutnik RS zbudowany z bramek NOR i jego tablica praejść
4.4.1. Proste układy sekwencyjne – przerzutnik FLIP-FLOP
W analogiczny sposób dla R = 1 i S = 0 otrzymamy odwrotny stan wyjść. Jeżeli R = S = 0, zostaje
zachowany poprzedni stan wyjść. Na tym właśnie polega zastosowanie przerzutnika RS jako
elementu pamięci. Dla R = S = 1 oba wyjścia są równocześnie równe zeru, jeżeli jednak w
następnej chwili R i S staną się równocześnie równe zeru, stan wyjść jest nieokreślony. Dlatego stan
wejść R = S = 1 jest w zasadzie niedozwolony. Zestawienie stanów przerzutnika zamieszczono w
tablicy przejść na rys. 4.9.
25
Rysunek 4.10. Przerzutnik RS zbudowany z bramek NAND i jego tablica przejść
Równanie logiczne nie ulega zmianie, jeżeli zanegujemy wszystkie zmienne i zamienimy między
sobą operacje (+) i (*). Jeżeli zasadę tę zastosujemy w tym przypadku, otrzymamy przerzutnik RS
zbudowany z bramek NAND (rys. 4.10) o takiej samej tablicy przejść, jak podana na rys. 4.9.
Należy jednak pamiętać, że teraz mamy do czynienia ze zmiennymi wejściowymi S i R . Jego
tablicę przejść dla zmiennych wejściowych R i S przedstawia rys. 4.10.
4.4.2. Proste układy sekwencyjne – przerzutnik RS-kluczowany
Często jest potrzebny przerzutnik RS, który reaguje na stan wejść tylko w określonym czasie.
Czas ten ma określać dodatkowa zmienna taktująca C. Na rysunku 4.11 przedstawiono taki
kluczowany przerzutnik RS (clocked RS flip flop). Dla C = 0 mamy R = S = 1. W tym przypadku
przerzutnik pamięta poprzedni stan. Dla C = 1 mamy R=R' i S=S', czyli przerzutnik zachowuje się
jak normalny przerzutnik RS.
Rysunek 4.11. Przerzutnik RS kluczowany
4.4.3. Proste układy sekwencyjne – przerzutnik D-kluczowany
W dalszej kolejności zbadamy, jak w przerzutniku z rys. 4.11 można zapamiętać wartość zmiennej
logicznej D. Stwierdziliśmy, że Q = S, jeśli na wejścia podamy dopełniające się stany i jeśli C = 1.
Aby zapamiętać wartość zmiennej D, należy tylko spełnić warunek S = D i R = D. Do tego służy
inwertor B5 na rys. 4.12. W powstałej w ten sposób komórce pamięci mamy Q = D tak długo, jak
długo sygnał zegarowy C = 1. Wynika to również z tablicy przejść pokazanej na rys. 4.12. Ze
względu na tę właściwość taka kluczowana komórka pamięci nosi nazwę przerzutnika D typu
„zatrzask" (data latch).
Rysunek 4.12. Przerzutnik D typu „zatrzask” i jego tablica przejść
26
Jeżeli C = 0, aktualny w danej chwili stan wyjść zostaje zapamiętany. Nietrudno zauważyć, że
bramka NAND B4 na rys. 4.12 dla C = 1 jest inwertorem zmiennej D. Umożliwia to zaoszczędzenie
inwertora B5 i prowadzi do praktycznej realizacji przerzutnika D przedstawionej na rys. 4.13. Na
tym rysunku przedstawiono także jego symbol graficzny.
Rysunek 4.13. Realizacja praktyczna przerzutnika D typu „zatrzask” i jego symbol graficzny
Tablica 4.6. Najczęściej używane przerzutniki D typu „zatrzask”
Typy układów scalonych:
Zatrzask
TTL
74L575
CMOS
4042
4.4.4. Proste układy sekwencyjne – przerzutnik wyzwalany impulsem
Do wielu zastosowań, jak np. liczniki i rejestry przesuwające, przerzutniki proste nie nadają się. W
tych zastosowaniach są potrzebne przerzutniki zapamiętujące stany wejściowe i przekazujące je na
wyjścia dopiero po ponownym zablokowaniu wejść. Składają się one z dwu przerzutników
prostych: przerzutnika głównego (master) na wejściu i przerzutnika pomocniczego (slave) na
wyjściu. Na rysunku 4.14 pokazano przerzutnik wyzwalany impulsem (two-edge triggered flip-flop)
typu master-slave zbudowany z dwu kluczowanych przerzutników RS z rys. 10.5. Oba przerzutniki
są blokowane na przemian sygnałem zegarowym C. Do inwersji sygnału zegarowego służy bramka
B15. Gdy sygnał zegara C = 1, informacja wejściowa jest wczytywana do przerzutnika głównego.
Stan wyjść nie ulega zmianie, gdyż przerzutnik pomocniczy jest zablokowany.
Rysunek 4.14. Przerzutnik RS master-slave
27
Rysunek 4.14. Przerzutnik RS master-slave
Gdy impuls zegara zmieni swój stan na C = 0, przerzutnik główny zostaje zablokowany i w
ten sposób zostaje „zamrożona" informacja, która była na wejściu bezpośrednio przed ujemnym
zboczem impulsu zegara. Równocześnie zostaje odblokowany przerzutnik pomocniczy i tym
samym stan przerzutnika głównego zostaje przekazany na wyjście. Przesyłanie danych następuje
więc przy ujemnym zboczu sygnału zegara, nie ma jednak takiego stanu zegara, przy którym dane
wejściowe oddziaływałyby bezpośrednio na wyjście, jak to ma miejsce w przerzutnikach prostych
(transparent flip flnps). Kombinacja zmiennych wyjściowych R=S=1 prowadzi do nieokreślonego
zachowania się przerzutnika, ponieważ wejścia S 1 i R 1 w części głównej równocześnie zmieniają
się z 00 na 11 przy przejściu zegara do stanu C = 0.
4.4.5. Przerzutniki wyzwalane zboczem (single-edge-triggered flip flops)
Przerzutniki złożone można realizować również łącząc szeregowo dwa przerzutniki D typu
„zatrzask" (rys. 10.8) i sterując je dopełniającymi się sygnałami zegarowymi. Otrzymuje się wtedy
układ przedstawiony na rys. 10.16. Jeżeli zegar jest w stanie C = 0, przerzutnik główny śledzi
sygnał wejściowy i Q1 = D. W tym czasie przerzutnik pomocniczy pamięta poprzedni stan. Gdy
zegar zmienia swój stan na 1, istniejąca w tym momencie informacja D zostaje zamrożona w
przerzutniku głównym i przeniesiona do przerzutnika pomocniczego, a tym samym na wyjście Q.
Informacja istniejąca na wejściu D w chwili pojawienia się dodatniego zbocza impulsu zegarowego
zostaje więc natychmiast przeniesiona na wyjście Q. W pozostałym czasie stan wejścia D nie
odgrywa roli, co widać również na rys. 4.16. W przerzutniku z rys. 4.15wartość wczytana pojawia
się na wyjściu natychmiast, a nie dopiero przy ujemnym zboczu impulsu zegarowego.
Rysunek 4.15. Przerzutnik D wyzwalany zboczem
Stanowi to zaletę, ponieważ dla utworzenia nowych sygnałów D mamy do dyspozycji cały
czas trwania okresu zegara.
28
Rysunek 4.16. Przebiegi czasowe sygnałów
wejściowych i wyjściowych w przerzutniku D
wyzwalanym zboczem
Rysunek 4.17. Symbol graficzny
przerzutnika D wyzwalanego zboczem
Symbol graficzny przerzutnika D wyzwalanego zboczem przedstawiono na rys. 4.17.
Tablica 4.7. Najczęściej używane przerzutniki D wyzwalane zboczem
Typy układów scalonych:
TTL
CMOS
Przerzutnik wyzwalany
74L74
4013
zboczem
Przerzutniki D wyzwalane zboczem mogą pracować również jako przerzutniki T (toggle). Należy w
tym celu zrealizować zależność D = Q , jak to pokazano na rys. 4.18. W chwili wystąpienia
dodatniego zbocza impulsu zegarowego stan wyjścia zmienia się na przeciwny. Przedstawiono to na
rys. 4.19. W przypadku zastosowania przerzutników D typu „zatrzask", zamiast dzielenia
częstotliwości w czasie, gdy C = 1, otrzymalibyśmy generację drgań, ponieważ ze względu na nie
zablokowane przejście sygnału, po upływie czasu opóźnienia następowałoby odwrócenie jego fazy.
Rysunek 4.18. Przerzutnik D wyzwalany
zboczem jako dzielnik częstotliwości
Rysunek 4.19. Przebiegi czasowe w dzielniku
częstotliwości
Odwracanie fazy można uzależnić również od zmiennej sterującej, łącząc zgodnie z wyborem
wyjście Q lub Q z wejściem D przez multiplekser. Multiplekser jest sterowany z wejścia T, jak
pokazano na rys. 4.20.
Rysunek 4.20. Budowa przerzutnika T i jego symbol graficzny
Jeszcze bardziej uniwersalne przerzutniki można otrzymać przez stworzenie dodatkowej
możliwości synchronicznego wprowadzania danych. W tym celu należy wykorzystać multiplekser o
dodatkowym - poza wejściem D - wejściu, które jest wybierane za pomocą wejścia wpisującego L
(load) w sposób przedstawiony na rys. 4.21. Dla L = 1 mamy y = D, a w następnym takcie Q = D.
Dla L = 0 układ pracuje dokładnie tak, jak układ na rys. 4.20. Symbol oraz tablicę przejść tego
przerzutnika przedstawiono na rys. 4.22.
29
Rysunek 4.21. Przerzutniki wielofunkcyjne
Rysunek 4.22. Symbol graficzny i tablica przejść przerzutnika wielofunkcyjnego
4.4.6. Liczniki dwójkowe
Ważną grupę układów sekwencyjnych stanowią liczniki. Licznikiem może być każdy układ, w
którym w pewnym zakresie istnieje jednoznaczne przyporządkowanie liczbie wprowadzonych
impulsów stanu zmiennych wyjściowych. Ponieważ każda zmienna wyjściowa może przyjmować
tylko dwie wartości, w przypadku n wyjść istnieje 2n możliwych kombinacji (często wykorzystuje
się jednak tylko część możliwych kombinacji). Wybór kombinacji, która ma odpowiadać danej
liczbie, jest w zasadzie obojętny. Celowe jest jednak dobranie takiego sposobu przedstawienia liczb,
który umożliwia łatwe ich dekodowanie. Najprostsze układy otrzymuje się w przypadku
naturalnego kodu dwójkowego. Na rysunku 4.23 przedstawiono odpowiednie przyporządkowanie
liczbie impulsów wejściowych Z wartości zmiennych wyjściowych zi dla 4-bitowego licznika
dwójkowego. Jeżeli czytamy tę tablicę od góry do dołu, możemy zauważyć dwie prawidłowości:
- zmienna wyjściowa zi zmienia swoją wartość wtedy, kiedy najbliższa zmienna zi-1
przechodzi z 1 na 0;
- zmienna wyjściowa zi zmienia zawsze swoją wartość wtedy, kiedy wszystkie niższe zmienne zi-1
... z0 mają wartość 1 i pojawi się nowy impuls zliczany. Prawidłowości te można odczytać
również z wykresu czasowego przedstawionego na rys. 4.24. Pierwsza prawidłowość prowadzi
do realizacji licznika asynchronicznego, a druga - licznika synchronicznego.
30
Rysunek 4.23. Tablica stanów licznika dwójkowego
Rysunek 4.24. Przebiegi czasowe na wyjściach licznika dwójkowego liczącego w przód
Niekiedy są potrzebne liczniki, których stan po każdym impulsie zliczanym zmniejsza się o
jeden. Prawidłowości charakteryzujące taki licznik liczący w tył (odejmujący - down counter) można
również dostrzec w tablicy na rys. 4.23, czytając ją od dołu do góry:
- w liczniku odejmującym zmienna wyjściowa zi zmienia swą wartość zawsze wtedy, kiedy
najbliższa niższa zmienna zi-1 przechodzi z 0 na 1;
- w liczniku odejmującym zmienna wyjściowa zi zmienia swą wartość zawsze wtedy, kiedy
wszystkie niższe zmienne zi-1 ... z0 mają wartość 0 i pojawi się nowy impuls zliczany.
4.4.7. Asynchroniczne Liczniki dwójkowe
Asynchroniczny licznik dwójkowy można zrealizować, tworząc łańcuch przerzutników i łącząc
wejście zegarowe C każdego przerzutnika z wyjściem Q poprzedniego, jak to pokazano na rys.
4.25. Można np. zastosować przerzutniki wyzwalane dodatnim zboczem impulsu zegarowego,
czyli np. przerzutniki D wyzwalane zboczem. Jeżeli połączymy je tak, jak na rys. 4.25, otrzymamy
licznik odejmujący. Aby zrealizować zliczanie w przód, należy dokonać inwersji sygnału
31
zegarowego. W tym celu wejście zegarowe łączymy po prostu z wyjściem Q poprzedniego
przerzutnika.
Z0
CLK
C1
Q
Q
Z1
C1
Q
Q
Z2
C1
Q
Z3
C1
Q
Q
Q
Rysunek 4.25. Asynchroniczny licznik dwójkowy
Każdy licznik jest równocześnie dzielnikiem częstotliwości. Częstotliwość na wyjściu
przerzutnika Po jest równa połowie częstotliwości impulsów zliczanych. Na wyjściu P1 występuje
jedna czwarta częstotliwości wejściowej, na wyjściu P2 jedna ósma, itd. Ta właściwość dzielenia
częstotliwości jest dobrze widoczna na rys. 4.25. Typy scalonych asynchronicznych liczników
dwójkowych przedstawiono w tabl. 10.2.
Tablica 4.8. Najczęściej używane asynchroniczne liczniki dwójkowe
TTL
74L93
74LS93
Typy układów scalonych:
Licznik 4 bitowy
Licznik 8 bitowy
Licznik 24 bitowy
CMOS
4521
4.4.8. Synchroniczne Liczniki dwójkowe
Cechą liczników asynchronicznych jest to, że zliczane impulsy są podawane tylko na wejście
zegarowe pierwszego przerzutnika, podczas gdy pozostałe przerzutniki są sterowane w sposób
pośredni. W następstwie tego sygnał wejściowy dociera do ostatniego przerzutnika dopiero
wówczas, gdy przerzucą wszystkie poprzednie przerzutniki. Stany kolejnych wyjść z0 do zn
zmieniają się z opóźnieniem równym czasowi przerzutu. W przypadku długiego łańcucha
przerzutników i dużej częstotliwości liczenia może się zdarzyć, że zn zmienia się dopiero po
pojawieniu się następnego impulsu zliczanego. Dlatego po ostatnim impulsie należy odczekać czas
opóźnienia całego łańcucha przerzutników, a dopiero potem odczytywać stan licznika. Jeżeli jest
potrzebny odczyt stanu licznika w trakcie liczenia, to okres impulsów zliczanych nie może być
krótszy od czasu opóźnienia łańcucha przerzutników tworzących licznik. Wad tych nie mają liczniki
synchroniczne.
Rysunek 4.26. Synchroniczny licznik dwójkowy
Charakteryzują się one tym, że zliczane impulsy są podawane równocześnie na wszystkie wejścia
zegarowe C. Aby każdy impuls zegarowy nie przerzucał wszystkich przerzutników, stosuje się
sterowane przerzutniki T (rys. 4.20), które zmieniają stan tylko wówczas, gdy zmienna sterująca T=
1. Zgodnie z tabl. z rys. 4.23 warunek przerzutu brzmi: przerzutnik wchodzący w skład licznika
dwójkowego może zmienić stan tylko wtedy, kiedy wszystkie przerzutniki poprzednie są w stanie
32
jeden. Aby to zrealizować, należy zapewnić warunki T0 = 1, Tl = z0, T2 = z0zl i T3 = z0zlz2. Na
rysunku 4.26 można zauważyć służące do tego celu bramki AND. Scalone liczniki synchroniczne
mają jeszcze kilka innych wejść i wyjść, których działanie i zastosowanie wyjaśnimy dokładniej na
podstawie rys. 4.27.
Rysunek 4.27. Praktyczna realizacja scalonego licznika synchronicznego
Wejście zerujące CLR umożliwia wyzerowanie całego licznika. (Z = 0). Wejście wpisujące
LOAD umożliwia wpisanie do licznika dowolnej liczby Z = D. Wejścia C1 są asynchroniczne,
natomiast wejścia wpisujące mogą być zarówno synchroniczne, jak i asynchroniczne. Liczniki
wieloczłonowe można realizować przez kaskadowe połączenie większej liczby członów, np.
czteropozycyjnych. Człony łączy się ze sobą przez wyjścia przeniesienia szeregowego RCO (ripple
carry output) i wejścia zezwolenia T (enable T) ENT, za pomocą których można zablokować cały
człon licznika i wyjście przeniesienia. Na wyjściu przeniesienia sygnał 1 pojawi się wówczas, gdy
licznik osiągnie stan 1111, i wszystkie człony poprzedzające dadzą również przeniesienie 1. W tym
celu w każdym członie należy zrealizować funkcję: RCO = ENT z0zlz2z3. W celu kaskadowego
połączenia członów licznika należy tylko połączyć wejście ENT jednego członu z wyjściem RCO
najbliższego członu poprzedzającego. W celu kaskadowego połączenia członów licznika należy
tylko połączyć wejście ENT jednego członu z wyjściem RCO najbliższego członu poprzedzającego.
Rysunek 4.28. Kaskadowe łączenie członów licznika synchronicznego
33
Tablica 4.9. Wybrane scalone synchroniczne liczniki dwójkowe
Kaskadowa realizacja funkcji AND powoduje jednak sumowanie się czasów propagacji. W
licznikach wieloczłonowych powoduje to zmniejszenie maksymalnej osiągalnej częstotliwości
liczenia. W tym przypadku jest bardziej korzystne tworzenie wymaganej funkcji AND równolegle
w każdym członie licznika. W tym celu opuszcza się najniższy człon licznika przy szeregowym
łączeniu RCO-ENT i steruje blokadę wyższych członów równolegle, przez wejście zezwolenia P
(enable P) ENP. W ten sposób równoległą realizację funkcji AND można przeprowadzić bez
udziału zewnętrznych bramek, jak to pokazano na rys. 4.28.
4.4.9. Rejestry przesuwające
Rejestry przesuwające to łańcuchy zbudowane z przerzutników, które umożliwiają przesuwanie
informacji podanej na wejście o jeden przerzutnik w każdym takcie zegara. Po przejściu przez cały
łańcuch informacja jest dostępna na wyjściu z opóźnieniem, ale w niezmienionej postaci. Zasada
pracy rejestru przesuwającego jest przedstawiona na rys. 4.29. Pierwszy impuls zegarowy powoduje
wczytanie informacji D1 podanej na wejście do przerzutnika P1. Drugi impuls zegarowy powoduje
przekazanie jej do przerzutnika P2; równocześnie do przerzutnika P1 zostaje wczytana nowa
informacja. Tablica 4.10 ilustruje działanie takiego układu na przykładzie rejestru przesuwającego o
długości czterech bitów. Można zauważyć, że po czterech taktach rejestr przesuwający zostaje
wypełniony wprowadzanymi danymi. Są one do dyspozycji w postaci równoległej na wyjściach
czterech przerzutników Q1... Q4 lub można je otrzymać w następnych taktach w postaci szeregowej
na wyjściu Q4.
Rysunek 4.29. Najprostsza realizacja 4-bitowego rejestru przesuwającego
Rysunek 4.29. Najprostsza realizacja 4-bitowego rejestru przesuwającego
34
Tablica 4.10. Tablica stanów 4-bitowego rejestru przesuwającego
Jako przerzutniki nadają się do tego celu wszystkie typy przerzutników złożonych. Przerzutniki
proste nie nadają się, ponieważ w chwili pojawienia się jedynki na wejściu zegarowym informacja
podana na wejście przebiegłaby natychmiast aż do ostatniego przerzutnika.
4.4.10. Rejestr przesuwający z wpisem równoległym
Jeżeli do każdego wejścia D dołączymy multiplekser, jak to pokazano na rys. 4.30, to za pomocą
wejścia LOAD można przełączyć układ na wpisywanie równoległe. W następnym takcie dane d1 ...
d4 zostają wpisane równolegle i pojawiają się na wyjściach Q1... Q4. Umożliwia to nie tylko
przejście z postaci szeregowej na równoległą, lecz także z postaci równoległej na szeregową.
Rysunek 4.30. Rejestr przesuwający z równoległym wejściem wpisującym
Rejestr przesuwający z wejściami do wpisywania równoległego może pracować również jako rejestr
dwukierunkowy. W tym celu należy połączyć każde wejście do wpisywania równoległego z
sąsiednim wyjściem po prawej stronie. Wtedy dla LOAD = 1 otrzymuje się przesuwanie danych od
prawej strony do lewej. Przykłady scalonych rejestrów przesuwających przedstawiono w tabl. 4.11.
Tablica 4.11. Wybrane scalone rejestry przesuwające
35
4.5. Pamięci
Wśród pamięci półprzewodnikowych można wyróżnić dwie podstawowe grupy: pamięci typu
tablicowego oraz pamięci typu funkcyjnego . Na rysunku 4.31 przedstawiono klasyfikację
najczęściej używanych rodzajów pamięci.
Rysunek 4.31. Rodzaje pamięci półprzewodnikowych
W pamięciach typu tablicowego podaje się adres mieszczący się w zakresie
Długość słowa adresu wynosi, zależnie od rodzaju pamięci, N = 5 ...22. Pod każdym z 2N
adresów można zapamiętać dane. Długość słowa danych wynosi m=l...l6 bitów. Na rysunku 4.32
pokazano przykład pamięci o N = 3 bitach adresu i m = 2 bitach danych.
Rysunek 4.32. Układ tablicy
Pojemność pamięci P = m * n jest podawana w bitach, a przy długościach słowa danych 8 lub 16
bitów - również w bajtach, jako P/8. Użycie większej liczby elementów pamięci umożliwia
dowolne rozszerzenie tak przestrzeni adresowej, jak też długości słowa. W ten sposób można
zapamiętywać dowolne tablice, jak np. tablice prawdy, programy komputerowe lub ciągi danych
pomiarowych. W pamięciach typu funkcyjnego zapamiętuje się nie tablice, lecz funkcje logiczne.
Każdą zmienną tablicy prawdy można przedstawić w postaci funkcji logicznej. Funkcja logiczna
zmiennej d0 na rys. 4.32 ma następującą postać normalną sumy:
36
d 0 = a 2 a1 a 0 d 00 + a 2 a1 a0 d10 + ... + a 2 a1 a 0 d 70
Jeżeli d0 nie wykazuje żadnych prawidłowości, a więc zera i jedynki są rozłożone zgodnie z
zasadami statystyki, otrzymujemy n/2, a więc w tym przypadku 4 nie znikające iloczyny. Tego
rodzaju zależności występują np. przy zapamiętywaniu programów. W tym przypadku realizacja
funkcji logicznej jest bardziej pracochłonna niż zapamiętanie jej w tablicy.
Rysunek 4.32. Układ tablicy
Jeżeli jednak punktem wyjścia jest tablica prawdy, z powodu występujących często prawidłowości
istnieją daleko idące możliwości uproszczenia funkcji logicznej. Przypadek ten ma miejsce np.
wtedy, kiedy w tablicy występuje bardzo mało jedynek. Jeżeli np. funkcja d0 jest równa tylko d70 =
l, potrzebny jest tylko jeden iloczyn d0 = a2a1a0. Inny przypadek występuje wtedy, kiedy funkcja
logiczna daje się uprościć za pomocą twierdzeń algebry Boole'a. Jeżeli np. na rys. 4.32 d0=a1,
otrzymuje się bardzo prostą funkcję, chociaż zawiera ona 4 jedynki. W takich przypadkach
zastosowanie pamięci typu funkcyjnego prowadzi do bardziej korzystnych rozwiązań niż
zastosowanie pamięci typu tablicowego. Pamięci typu tablicowego można podzielić na pamięci
RAM i ROM.
RAM jest ogólnym oznaczeniem pamięci, w których przy normalnej pracy istnieje możliwość
zapisywania i odczytywania informacji. Skrót RAM oznacza dosłownie „Random Access
Memory", czyli „pamięć o swobodnym dostępie".
Oznacza to, że w każdej chwili istnieje dostęp do każdego słowa danych, w przeciwieństwie do
pamięci o dostępie szeregowym, w których wpisane słowo danych może zostać odczytane lub
zmienione tylko w ściśle określonej chwili. Pamięci o dostępie szeregowym nie mają obecnie
większego znaczenia. Dlatego też nazwa RAM stanowi ogólne określenie pamięci z zapisem i
odczytem. Jest ona o tyle myląca, że pamięci ROM również umożliwiają swobodny dostęp do
każdego słowa danych.
ROM jest skrótem angielskiej nazwy „Read-Only Memory", czyli „pamięć tylko odczytywana".
Nazwa ta obejmuje pamięci scalone zachowujące dane nawet wówczas, gdy pracują bez
żadnego napięcia zasilania, w tym również bez pomocniczych baterii.
Jak sama nazwa wskazuje przy normalnej pracy dane z tych pamięci mogą być tylko odczytywane.
Proces zapisu danych odbywa się na ogól w specjalnych urządzeniach i nosi nazwę
programowania.
Przedstawione na rys. 4.31 rodzaje pamięci ROM różnią się sposobem programowania; zostanie to
dokładniej opisane w następnych punktach.
4.5.1. Pamięci statyczne RAM
RAM jest pamięcią, w której można po podaniu adresu zapisać dane i pod tym adresem ponownie
je odczytać (tzw. dostęp swobodny). Ze względów technologicznych komórki pamięci nie są
ułożone liniowo, lecz stanowią kwadratową matrycę. W celu wybrania określonej komórki pamięci
adres A jest dekodowany przez dekoder kolumn i wierszy, jak to pokazano na rys. 4.33.
Oprócz wejść adresowych pamięć RAM ma jeszcze wejście danych DI (data input), wyjście
danych DO (data output), wejście sygnału zapis/odczyt R/ W (read/write) i wejście sygnału wyboru
37
(selekcji) układu CS (chip selecf) lub sygnału zezwolenia dla układu CE (chip enable). Wejścia CS i
CE umożliwiają pracę w systemie multipleksowym większej liczby pamięci połączonych ze
wspólną linią danych (praca z wykorzystaniem magistrali). Jeżeli CS = O, wyjście danych DO
znajduje się w stanie wysokiej impedancji i nie ma wpływu na linię danych. W celu umożliwienia
tego rodzaju przełączania wyjście danych jest zrealizowane przeważnie jako wyjście z otwartym
kolektorem lub wyjście trójstanowe. W czasie zapisu (R/W = 0) dodatkowa funkcja logiczna
powoduje ustawienie bramki wyjściowej również w stan wysokiej impedancji. Dzięki temu istnieje
możliwość połączenia DI z DO i prowadzenie w ten sposób transmisji danych w obu kierunkach za
pomocą tej samej linii (magistrala dwukierunkowa). Inna funkcja logiczna zapobiega przełączeniu
w stan zapisu (we = 1), gdy CS = 0. Dzięki temu unika się omyłkowego zapisu przed wybraniem
odpowiedniego układu pamięci.
Rysunek 4.33. Budowa wewnętrzna pamięci RAM. Przykład pamięci o pojemności 16 bitów
Rysunek 4.34. Logiczny schemat zastępczy komórki pamięci
Funkcje te są pokazane na rys. 4.33. Wewnątrz układu do każdej komórki pamięci są doprowadzone
linie di, do i we (write enable), jak to schematycznie przedstawiono na rys. 4.34. Dane mogą zostać
wpisane do komórki pamięci tylko wówczas, gdy jest spełniony warunek adresu xj = yj = l i oprócz
tego we = l. Tę funkcję realizuje bramka B1 Zawartość komórki pamięci może być podana na
wyjście również tylko wtedy, kiedy jest spełniony warunek adresu. Tę funkcję realizuje bramka B2.
Ma ona wyjście z otwartym kolektorem. Jeżeli komórka nie jest zaadresowana, tranzystor
wyjściowy jest zablokowany. Wyjścia wszystkich komórek pamięci są połączone wewnątrz układu,
38
tworząc iloczyn galwaniczny i za pomocą pokazanej na rys. 4.33 bramki trójstanowej są dołączone
do wyjścia pamięci DO. Jeśli nie zostanie odłączone napięcie zasilania, zawartość pamięci jest
zachowana tak długo, aż zostanie zmieniona nowym poleceniem zapisu. Takie pamięci noszą
nazwę pamięci statycznych, w odróżnieniu od pamięci dynamicznych, których zawartość musi być
stale odświeżana, aby nie uległa zatarciu. Symbol graficzny pamięci RAM przedstawia rys. 4.35. Na
symbolu widać N wejść adresowych, które są dekodowane przez dekoder adresu tak, by można było
wybrać dokładnie tę komórkę pamięci (z 2N komórek), która odpowiada podanemu adresowi.
Przełączanie z zapisu na odczyt R/IV jest aktywne tylko wtedy, kiedy sygnał zezwolenia dla układu
(chip enable) CE = l lub CE = 0. Wtedy przy RfW = l wyjście trójstanowe jest aktywne, a przy R/W
= O w stanie wysokiej impedancji. Dlatego też istnieje możliwość wewnętrznego połączenia
wejścia i wyjścia danych w elemencie pamięci. Powstaje wówczas dwukierunkowy port danych,
którego kierunek transmisji jest określany za pomocą sygnału R/W.
Rysunek 4.35. Symbol graficzny pamięci RAM
Często pod jednym adresem jest pamiętany nie pojedynczy bit, ale całe m-pozycyjne słowo.
Pamiętanie całych słów można przedstawić jako przestrzenne rozszerzenie schematu blokowego z
rys. 4.33. Dodatkowe bity leżą wówczas na następnych poziomach pamięci jeden nad drugim; ich
linie sterujące x, y, i we są połączone równolegle, a linie danych tworzą słowo wejściowe lub
wyjściowe.
4.5.1. Pamięci statyczne RAM – parametry dynamiczne
W celu zapewnienia niezawodnej pracy pamięci powinny być spełnione pewne warunki. Na
rysunku 4.36 przedstawiono wykresy czasowe sygnałów w trakcie zapisu. Dla uniknięcia wpisania
danych do niewłaściwej komórki, polecenie zapisu można podać dopiero pewien czas po adresie.
Czas ten nosi nazwę czasu ustalania na wejściu adresowym tAS (adress setup time). Czas trwania
sygnalu zapisu nie może spaść poniżej wartości twp (write pulse width).
39
Rysunek 4.36. Przebiegi czasowe cyklu zapisu
Dane zostają wpisane na końcu sygnału zapisu. Muszą one być aktualne, tj. stabilne dla
poprzedzającego określonego minimalnego odstępu czasu. Czas ten jest oznaczany symbolem tDW,
(data valid to end ofwrite). W wielu pamięciach dane lub adresy muszą zostać przetrzymane jeszcze przez
pewien czas tH po zakończeniu impulsu zapisu (hold time). Jak widać na rys. 4.36, zapisywanie wymaga
czasu:
Nosi on nazwę czasu cyklu zapisu (write cycle time).
Cykl odczytu jest przedstawiony na rys. 4.37. Po podaniu adresu należy odczekać czas tAA, aż dane
będą dostępne na wyjściu. Czas ten nosi nazwę czasu dostępu od wejścia adresowego (adress access time)
lub po prostu czasu dostępu.
Rysunek 4.37. Przebieg czasowy cyklu odczytu
W tablicy 4.12 podano zestawienie najczęściej używanych pamięci stat. RAM w tech. bipolarnej i MOS.
40
Tablica 4.12. Przykłady pamięci statycznych RAM
4.5.2. Pamięci dynamiczne RAM
Ponieważ w pamięci chcielibyśmy pomieścić możliwie dużo komórek, należy je realizować
możliwie w prosty sposób. Z reguły komórka pamięci składa się tylko z kilku tranzystorów; w
statycznych pamięciach RAM CMOS typowa komórka składa się z 6 tranzystorów. W najprostszym
przypadku rezygnuje się nawet z przerzutnika, zastępując go kondensatorem, który jest wybierany
za pomocą tranzystora MOS. W ten sposób można zbudować komórkę pamięci zawierającą tylko l
tranzystor. Informacja jest wówczas pamiętana w postaci ładunku, ale niestety pozostaje
zachowana tylko przez krótki czas. Dlatego też kondensator pamiętający wymaga regularnego
doładowywania (co ok. 2... 8 ms). Operację tę nazywamy odświeżaniem (refresh), a pamięć
nosi nazwę pamięci dynamicznej RAM. Mimo tej wady pamięci dynamiczne mają wiele zalet: na
tej samej powierzchni półprzewodnika, przy tym samym poborze prądu i tych samych kosztach
umożliwiają uzyskanie w przybliżeniu czterokrotnie większej pojemności pamięci. W celu
41
zmniejszenia liczby wyprowadzeń w pamięciach dynamicznych adres jest wprowadzany w dwu
krokach oraz zostaje przejściowo zapamiętany w układzie scalonym. Odpowiedni schemat blokowy
jest przedstawiony na rys. 4.38. W pierwszym kroku sygnał bramkowania adresu wiersza RAS (rów
adress strobe) powoduje wpisanie bitów adresu a0...a1 do rejestru adresu wiersza (rów adress
latch), a w drugim kroku sygnal bramkowania adresu kolumny CAS (column adress strobe) wpisanie bitów adresu a8...a15 do rejestru adresu kolumny (column adress latch).
Rysunek 4.38. Dekodowanie adresu w pamięci dynamicznej 1 Mbit
Umożliwia to umieszczenie pamięci 1-megabitowej w obudowie 18-wyprowadzeniowej. W tablicy
4.13 umieszczono zestawienie najczęściej używanych typów takich pamięci.
Tablica 4.13. Przykłady pamięci dynamicznych RAM
42
4.5.3. Pamięci dynamiczne RAM – układ sterowania (kontroler)
Pamięci dynamiczne RAM wymagają współpracy dodatkowych układów. Przy normalnym
dostępie do pamięci adres musi być wpisany do pamięci w dwu następujących po sobie krokach. W
celu uniknięcia utraty danych jest wymagane wywołanie wszystkich adresów wierszy co najmniej
raz w ciągu 8 ms. Jeżeli zawartość pamięci nie jest czytana cyklicznie, są konieczne dodatkowe
układy, które powodują adresowanie cykliczne między normalnymi cyklami dostępu do pamięci.
Układy te noszą nazwę kontrolerów pamięci dynamicznych RAM (dynamie RAM controller).
Schemat blokowy takiego układu, jest pokazany na rys. 4.39.
W normalnym cyklu dostępu do pamięci podany z zewnątrz adres zostaje zapamiętany w
rejestrze adresu wiersza i kolumny, jeśli sygnal bramkowania adresu AS (adress strobe) jest równy
l i wskazuje, że adres jest aktualny. Równocześnie układ sterowania przebiegu inicjuje cykl dostępu
do pamięci. Powoduje to najpierw podanie adresu wiersza a0...a9 do pamięci za pomocą
multipleksera. Następnie sygnał bramkowania adresu wiersza RAS przyjmuje wartość l i powoduje
przekazanie adresu do pamięci. Potem zostaje podany adres kolumny a10...a19 i za pomocą sygnału
bramkowania adresu kolumny CAS zostaje wczytany również do pamięci. Odpowiedni przebieg czasowy
pokazano na rys. 4.40.
Rysunek 4.39. Schemat blokowy kontrolera pamięci dynamicznej RAM 1Mbit
Po wprowadzeniu adresu sygnał bramkowania adresu musi pozostać tak długo w stanie l, aż
zakończy się przesyłanie danych. Następny cykl dostępu do pamięci nie może zacząć się natychmiast,
lecz dopiero po upływie czasu wstępnego ładowania (precharge time), który jest tego samego rzędu, co
czas dostępu. W czasie odświeżania należy co 8 ms wywołać 512 niższych adresów. Przy czasie cyklu
odświeżania (refresh cycle time) równym 300 ns potrzeba na to w sumie ok. 150 µs. Dyspozycyjność
pamięci zmniejsza się wskutek tego tylko o mniej niż 2%.
Rysunek 4.40. Przebieg czasowy wprowadzania adresu do pamięci dynamicznej RAM
43
Istnieją trzy różne metody podziału czasowego cyklu odświeżania:
- Odświeżanie z przerwaniem cyklu pracy (burst refresh). Przy tym rodzaju odświeżania po każdych
8 ms normalnej pracy następuje jej przerwanie i odświeżenie wszystkich komórek pamięci. W wielu
jednak przypadkach zablokowanie pamięci na 150 us może zakłócać jej prace;
- Odświeżanie z wykradaniem cykli (cycle stealing). Dla uniknięcia niekorzystnego blokowania
pamięci proces odświeżania można równomiernie rozłożyć na okres 8 ms: jeżeli stan licznika
odświeżania będziemy co 15 us zwiększać o l po 512x15us≈8 ms, nastąpi aktywizacja wszystkich
adresów wierszy, tak jak jest to wymagane. Przy tym rodzaju odświeżania procesor jest
zatrzymywany co 15 us na jeden cykl i jest wykonywany krok odświeżania. W czasie cyklu
odświeżania stan licznika odświeżania jest podawany przez multiplekser do pamięci, a sygnał RAS
przejściowo jest ustawiany w stan 1. Na zakończenie stan licznika zostaje zwiększony o jeden. W
czasie cyklu odświeżania użytkownik pamięci jest wstrzymywany sygnałem oczekiwania (wait).
Biegnący proces jest wskutek tego zatrzymywany co 15 us na 0,3 us, a więc przebiega o 2%
wolniej;
- Odświeżanie o minimalnych stratach czasu (transparent refresh lub hidden refresh). Metoda ta
polega również na realizacji cyklu odświeżania co 15 µs. Układ sterowania odświeżania (refresh
controller) jest jednak synchronizowany tak, że nie następuje wstrzymywanie dostępu do pamięci,
lecz odświeżanie odbywa się dokładnie wtedy, kiedy użytkownik i tak nie korzysta z pamięci. Nie
występuje wtedy strata czasu. Jeżeli nie można całkowicie wykluczyć nakładania się na siebie
dostępu do pamięci z zewnątrz i cyklu odświeżania, można zastosować dekoder priorytetowy
(arbiter). Żądanie dostępu z zewnątrz zostaje potwierdzone sygnałem oczekiwania trwającym do
zakończenia trwającego cyklu odświeżania, po czym następuje jego realizacja.
Tablica 4.14. Typy układów scalonych
pamięci DRAM 1M:
SN74ACT4503
DP8421A
74F1764
673104
DP8430
AM29C668
74F1762
DP8840
DP8441
pamięci DRAM 4M:
pamięci DRAM 16M:
pamięci DRAM64M:
CMOS
CMOS
TTL
TTL
CMOS
CMOS
TTL
CMOS
CMOS
Texas Instr.
National
Philips
AMD
National
AMD
Philips
National
National
4.5.4. Pamięci dwubramowe RAM
Pamięci dwubramowe (dudport RAM) to specjalne pamięci RAM, które umożliwiają dwu
niezależnym procesom dostęp do wspólnych danych. Umożliwia to wymianę danych między
obydwoma procesami. W tym celu pamięć dwubramowa musi mieć dwa oddzielne zestawy linii
adresowych, danych i sterujących, jak to pokazano na rys. 4.41. Zasady tej nie można zrealizować
bez ograniczeń, ponieważ nie jest możliwy równoczesny wpis z obu bram do tej samej komórki
pamięci.
A1
R/W1
D1
A2
Pamięć
dwubramowa
Brama 1
R/W2
D2
Brama 2
Rysunek 4.41. Wyprowadzenia zewnętrzne pamięci dwubramowej
44
WRITE1
A1 Dekoder
adresu1
WRITE2
Matryca
pamięci
D1
Dekoder A2
adresu2
D2
4.42. Budowa pamięci z możliwością odczytu podczas zapisu
W przypadku pamięci z możliwością odczytu w trakcie zapisu (read while write) problem ten
ominięto w ten sposób, że jedna brama służy tylko do zapisu, a druga - tylko do odczytu. Na
rysunku 4.42 widać, że pamięci te mają dwa oddzielne dekodery adresu, które umożliwiają
równoczesny zapis pod jednym adresem i odczyt spod drugiego. Jeżeli chcemy czytać i zapisywać
na obu bramach pamięci dwubramowej, konflikt dostępów można rozwiązać w ogólny sposób
tylko przez uniemożliwienie równoczesnego dostępu do pamięci. Można do tego zastosować
normalną pamięć RAM, jak to pokazano na rys. 4.43, której linie adresowe, danych i sterujące są
przyporządkowane wywołanej bramie za pomocą multipleksera.
Rysunek 4.43. Pamięć dwubramowa z wykorzystaniem standardowej pamięci RAM
W wielu przypadkach oba procesy można tak ze sobą zsynchronizować, że równoczesny dostęp do
pamięci zostaje wykluczony. Jeżeli nie jest to możliwe, można zastosować dekoder priorytetowy,
który w przypadku nakładania się dostępów do pamięci wstrzymuje przejściowo jeden z procesów
sygnałem oczekiwania. Wybrane typy scalonych pamięci dwubramowych podane są w tablicy 4.15.
Ich pojemność jest jednak ograniczona. Przy realizacji dużych pamięci dwubramowych celowe jest
zastosowanie normalnych pamięci RAM i kontrolera pamięci dwubramowej. W tym wypadku
szczególnie przydatny jest kontroler 74 LS 764 firmy Valvo, wspomagający pracę pamięci
dynamicznych RAM jako pamięci dwubramowych.
45
Tablica 4.15. Przykłady pamięci dwubramowych (CMOS)
4.5.5. Pamięci RAM jako rejestr przesuwający
Pamięci RAM mogą pracować jako rejestry przesuwające, jeśli adresy są przeliczane cyklicznie.
Służy do tego licznik na rys. 4.44. Pod każdym adresem najpierw są wyprowadzane zapamiętane
dane, a następnie wczytywane nowe dane. Przebiegi czasowe są przedstawione na rys. 4.45.
Rysunek 4.44. Praca pamięci RAM jako rejestru przesuwającego
Rysunek 4.45. Przebiegi czasowe w rejestrze przesuwającym z pamięcią RAM
Stan licznika zwiększa się przy dodatnim zboczu impulsu zegara. Ponieważ sygnał CLK jest
używany również jako sygnał R/W, zatem przy dodatnim zboczu impulsu zegarowego odbywa się
odczytywanie zawartości pamięci, a przy ujemnym – zapamiętanie jej w przerzutniku wyjściowym.
W czasie gdy sygnał zegarowy CLK = O do komórki pamięci, z której właśnie nastąpił odczyt,
wpisuje się nowe dane. Minimalny okres impulsów zegarowych jest tu krótszy od sumy czasów
cyklu odczytu i zapisu, ponieważ adres pozostaje stały. Okres ten jest równy czasowi
zmodyfikowanego cyklu odczytu-zapisu (read modify write cycle time). Różnica w stosunku do
normalnego rejestru przesuwającego polega na tym, że tu nie są przesuwane dane, ale tylko adresy,
które stanowią wskaźniki dla nieruchomych danych. Korzyściami wynikającymi z tej metody są:
możliwość stosowania normalnych pamięci RAM, które mają o wiele większe pojemności, niż
konwencjonalne rejestry przesuwające, a dla częstotliwości zegara większej niż 64 kHz, możliwość
stosowania pamięci dynamicznych RAM bez dodatkowych układów odświeżania.
46
4.5.6. Pamięci FIFO
Pamięć FIFO jest odmianą rejestru przesuwającego. Podobnie jak w rejestrze, w pamięci FIFO
dane ukazują się na wyjściu w tej samej kolejności, w jakiej zostały wprowadzone: słowo wpisane
jako pierwsze (flrst in) zostaje również jako pierwsze wyprowadzone (first out). W przypadku
pamięci FIFO proces ten - inaczej niż w rejestrze przesuwającym - może przebiegać w pełni asynchronicznie, to znaczy takt wyprowadzenia jest niezależny od taktu wprowadzenia. Dlatego też
pamięci FIFO są używane do sprzęgania systemów asynchronicznych. Zasada działania pamięci
FIFO jest podobna do tworzenia się kolejki: dane nie przesuwają się od wejścia do wyjścia w takt
kolejnych impulsów zegarowych, lecz czekają w pamięci tak długo, aż wszystkie wprowadzone
wcześniej dane zostaną wyprowadzone. Jest to schematycznie pokazane na rys. 4.46.
Rysunek 4.46. Poglądowe przedstawienie zasady działania pamięci FIFO
W pamięciach FIFO pierwszej generacji dane były rzeczywiście przesuwane przez łańcuch
rejestrów zgodnie ze schematem pokazanym na rys. 4.46. Wprowadzane dane przechodzą do
najniższego wolnego miejsca pamięci i stamtąd przesuwają się do wyjścia w takt impulsów
wyprowadzających. Wadą tej metody jest duży czas przelotu (fall-trough time). Uwidacznia się on
w szczególnie nieprzyjemny sposób w przypadku, gdy pamięć FIFO jest pusta, ponieważ wtedy
dane, zanim pojawią się na wyjściu, muszą przejść przez wszystkie rejestry. Dlatego nawet małe
pamięci FIFO mają czas przelotu rzędu wielu mikrosekund. Dalszymi wadami są rozbudowany
układ logiczny i duża liczba operacji przesuwania, pozostająca w sprzeczności z oszczędną pod
względem poboru prądu techniką CMOS.
Dlatego też w pamięciach FIFO drugiej generacji nie przesuwa się już danych, a tylko dwa
wskaźniki, podające adres wejścia lub wyjścia pamięci RAM. Widać to na rys. 4.47. Wskaźnik
wejścia wskazuje pierwszy wolny adres AI, a adres wyjścia ostatni zajęty adres AO.
Rysunek 4.47. Pamięć pierścieniowa FIFO
47
Rysunek 4.48. Realizacja pamięci FIFOz wykorzystaniem pamięci z odczytem podczas zapisu
Przy wprowadzaniu i wyprowadzaniu danych oba wskaźniki zmieniają położenie.
Odstęp obu wskaźników AI - AO podaje stan wypełnienia pamięci. Jeżeli mamy AI - AO = Amax,
pamięć FIFO jest pełna. Nie można wtedy niczego wpisywać, gdyż nastąpiłoby skasowanie danych,
które nie były jeszcze czytane. Jeżeli AI = AO pamięć FIFO jest pusta. Wtedy nie wolno czytać
żadnych danych, gdyż grozi to przeczytaniem starych danych po raz drugi. Przepełnienia lub
opróżnienia pamięci można uniknąć tylko wówczas, gdy średnie szybkości transmisji danych
przy odczycie i zapisie są równe. W tym celu należy nadzorować wypełnienie pamięci i próbować
tak wpływać na źródło i ujście danych, by pamięć była wypełniona w połowie. Pamięć FIFO może
wtedy przejmować krótkotrwałe zamiany szybkości, jeżeli tylko ma wystarczająco dużą pojemność.
Budowę pamięci FIFO przedstawia rys. 4.48. Jej struktura zbliżona jest do rejestru przes. wyk.
pamięć RAM. Na pamięci nadają się tu szczególnie dobrze pamięci z możliwością odczytu podczas
zapisu, ponieważ mają możliwość wpisywania i czytania asynchronicznego. Zgodnie z tą zasadą
pracują nowsze pamięci FIFO. Przy realizacji dużych pamięci FIFO jest celowe wykorzystanie
standardowych pamięci RAM, ponieważ osiąga się wtedy najwyższy stopień scalenia. W tym celu
pamięć z odczytem podczas zapisu z rys. 4.48 zastępuje się pamięcią dwubramową zrealizowaną z
wykorzystaniem standardowych pamięci RAM. Wynikający stąd układ jest przedstawiony na rys.
4.49.
Rysunek 4.49. Relizacja pamięci FIFO z wykorzystaniem standardowych pamięci RAM
Ponieważ w przypadku normalnej pamięci RAM nie można równocześnie prowadzić zapisu i
odczytu, operacje te należy wykonać kolejno. Koordynację przejmuje arbiter wchodzący w skład
układu sterowania. Jeżeli zapis ma być wykonany w czasie, gdy trwa jeszcze odczyt, najpierw
kończy się cykl odczytu, a zapis zostaje opóźniony.Wykonywany jest zawsze ten cykl, który został
wywołany wcześniej. Jeżeli takty zapisu i odczytu zbiegną się, arbiter podejmuje decyzję
przypadkową. Wskutek możliwego czasu oczekiwania, w niekorzystnym przypadku czas dostępu
może się podwoić. Układ sterujący potrzebny do pracy pamięci RAM jako FIFO jest dostępny w
postaci układu scalonego zwanego kontrolerem RAM-FIFO.
48
Tablica 4.16. Przykłady pamięci FIFO
4.5.7. Pamięci stałe (ROM)
Pamięci ROM to pamięci typu tablicowego, które normalnie są tylko odczytywane. Z tego też
względu nadają się do pamiętania tablic i programów. Ich zaletą jest, że zawartość pamięci zostaje
zachowana po odłączeniu napięcia zasilającego. Wadę pamięci ROM stanowi to, że wpisywanie
tablicy jest znacznie bardziej pracochłonne niż w przypadku pamięci RAM. Odmiany pamięci
ROM przedstawione na rys. 4.31 (MROM, PROM, EPROM, EEPROM) różnią się procedurą
zapisu.
4.5.8. Pamięci ROM programowane maską
W pamięciach ROM programowanych maską (MROM) zawartość pamięci zostaje określona
przez producenta w ostatnim etapie produkcji za pomocą specjalnie do tego celu przygotowanej
maski metalizacji. Metoda ta jest opłacalna jedynie przy długich seriach produkcyjnych (od ok. 10
000 sztuk), a wykonanie układu scalonego trwa przeważnie kilka miesięcy.
4.5.9. Pamięci programowane w sposób trwały (PROM)
Skrót PROM (programmable ROM) oznacza pamięć, której zawartość jest programowana
przez użytkownika. Elementami umożliwiającymi programowanie takich pamięci są bezpieczniki,
realizowane w układach scalonych w postaci bardzo cienkich, metalizowanych mostków. Oprócz
tego są stosowane również diody, które po przeciążeniu w kierunku zaporowym przechodzą w stan
zwarcia. Najnowszymi elementami umożliwiającymi programowanie pamięci PROM są specjalne
tranzystory MOS, mające dodatkową, izolowaną (tzw. swobodną) bramkę (floating gate). W
procesie programowania pojemność tej bramki zostaje naładowana, co powoduje przesunięcie
napięcia progowego tranzystora MOS. Ze względu na fakt, że swobodna bramka jest ze
wszystkich stron izolowana za pomocą warstwy SiO2, można zagwarantować 10-letni czas
zachowania ładunku.
49
4.5.9. Pamięci stałe - PROM
Budowę wewnętrzną pamięci PROM omówimy na przykładzie z rys. 4.50. Ze względów
technologicznych poszczególne komórki pamięci nie są ułożone liniowo, lecz stanowią kwadratową
matrycę. Adresowanie określonej komórki pamięci odbywa się przez podanie logicznej jedynki na
odpowiednią linię wiersza i kolumny.
Rysunek 4.50. Budowa wewnętrzna pamięci PROM. Przykład pamięci 16 bitów
W tym celu należy odpowiednio zdekodować wektor adresu A — (a0...an) podany z zewnątrz.
Do tego służą dekodery kolumn i wierszy. Pracują one jako dekodery l z n.Wybrana komórka
pamięci jest aktywowana przez bramkę AND w punkcie przecięcia wybranych linii kolumn i wierszy.
Sygnał wyjściowy D otrzymuje się jako sumę logiczną (OR) wyjść wszystkich komórek pamięci. Aby
uniknąć użycia bramki o 2n wejściach, stosuje się sumę galwaniczną (wired OR). W przypadku wyjść
z otwartym kolektorem można ją zrealizować poprzez iloczyn galwaniczny (wired AND)
zanegowanych sygnałów.
W stanie pierwotnym każda zaadresowana komórka pamięci daje sygnał wyjściowy D=1. W
celu zaprogramowania zera przepala się bezpiecznik na wyjściu żądanej komórki. W tym celu wybiera
się adres odpowiedniej komórki i tym samym powoduje przewodzenie tranzystora wyjściowego bramki
NAND. Następnie wymusza się w linii odczytu silny impuls prądowy, który jest tak duży, że
powoduje przepalenie bezpiecznika na wyjściu bramki NAND. Należy przy tym dokładnie
przestrzegać podanego przez producenta kształtu impulsu. Dlatego też do tego celu używa się
specjalnych programatorów, które można dopasować do różnych typów pamięci. W pamięci PROM
pod jednym adresem jest pamiętany z reguły nie jeden bit, ale całe słowo 4- lub 8-bitowe. Dlatego
pamięci te mają odpowiednią liczbę wyjść danych. Pojemność pamięci np. l k x 8 bitów oznacza, że
pamięć zawiera 1024 słowa 8-bitowe. Zawartość pamięci podaje się w postaci tablicy programu. Na
rysunku 4.51 podano przykładowo tablicę dla pamięci PROM 32 x 8 bitów. Symbol graficzny
pamięci PROM odpowiada symbolowi pamięci RAM z tą różnicą, że wejście przełączające z zapisu
na odczyt jest tu wejściem programującym. W tablicy 4.17 zebrano kilka najczęściej używanych
typów pamięci PROM wykonanych w różnych technologiach.
50
Wejścia
Wyjścia
A4 A3 A2 A1 A0 D7 D6 D5 D4 D3 D2 D1 D0
0
0
0
0
0
0
0
0
0
1
0
0
0
1
0
0
0
0
1
1
...
...
1
1
1
1
0
1
1
1
1
1
...
...
Rysunek 4.51. Przykład pamięci PROM o pojemności 32 słowa 8 bitowe
Tablica 4.17. Przykłady pamięci PROM
4.5.10. Pamięci stałe kasowane promieniami UV - EPROM
Nazwa EPROM (erasable PROM) oznacza pamięć stałą, którą użytkownik może nie tylko
zaprogramować, lecz także może skasować jej zawartość światłem ultrafioletowym. Elementami
pamiętającymi są wyłącznie tranzystory MOS z dodatkową izolowaną bramką (floating gate). Przy
programowaniu ładuje się bramkę (tak jak w przypadku niektórych pamięci PROM) i wskutek tego
przesuwa napięcie progowe tranzystora MOS. W przypadku pamięci EPROM istnieje dodatkowa
możliwość skasowania jej zawartości przez naświetlanie promieniowaniem ultrafioletowym w
ciągu ok. 20 min. Aby to umożliwić, w obudowie nad strukturą znajduje się okienko wykonane ze
szkła kwarcowego.
51
Ze względu na dość skomplikowaną konstrukcję obudowy, pamięci EPROM są droższe od
wykonanych tą samą technologią pamięci PROM bez okna. Z tego też względu przy projektowaniu
urządzeń stosowanie pamięci EPROM jest uzasadnione, ale przy produkcji seryjnej należy przejść
na elementy PROM. Pamięci EPROM programuje się słowami, więc przy typowej organizacji 8bitowej bajtami. W starszych typach pamięci (np. 2716, 2k x 8 bitów) programowanie było
stosunkowo proste. Należało tylko doprowadzić napięcie programujące UPP = 25 V, żądany adres i
wzór bitów, a potem podać polecenie programowania o czasie trwania 50 ms. Na tym
programowanie można było zakończyć, lub też powtórzyć operację pod innym adresem i z nowym
wzorem bitów. Programowanie całej pamięci EPROM o pojemności 2 kilobajtów trwało więc ok. 2
minut. Programowanie pamięci 128 kB musiałoby więc zająć prawie 2 godziny. Ponieważ tej
niedogodności nie można uniknąć, dla większych pamięci EPROM należało zmodyfikować
technologię produkcji i algorytmy programowania. U podstaw wszystkich szybkich algorytmów
programowania leży spostrzeżenie, że większość bajtów pamięci EPROM daje się zaprogramować
w czasie znacznie krótszym niż 50 ms. Ponieważ jednak istnieją także „wolne" bajty, czasu
programowania nie daje się generalnie skrócić. Stosuje się przy tym raczej zmienny czas trwania
impulsów programujących. Stosowany obecnie „szybki" lub „inteligentny" algorytm
programowania przedstawiono na rys. 4.52. Najpierw podaje się napięcie programujące Upp = 12,5
V i podwyższa napięcia zasilania do Ucc = 6 V. Wyższe napięcie zasilania z jednej strony
przyśpiesza proces programowania, bo tranzystory mają wówczas mniejszą rezystancję, a z drugiej
strony stwarza możliwość weryfikacji układu w warunkach „najgorszego przypadku" (worst case).
Potem podaje się adres A = O i odpowiednie dane. Teraz następuje procedura programowania danego
bajtu. W tym celu zeruje się pomocniczy licznik (n = 0) i podaje polecenie programowania o czasie
trwania l ms. Po zwiększeniu stanu licznika odczytuje się zawartość pamięci, aby sprawdzić czy
programowanie zakończyło się sukcesem. Jeżeli nie, podaje się następne rozkazy programowania, aż do
24. Jeżeli nawet wtedy dany bajt nie zostanie zaprogramowany, program uznaje, że element pamięci
jest uszkodzony. Normalnie potrzeba tylko kilka impulsów programujących. Nie jest wtedy jednak pewne,
czy do izolowanej bramki został wprowadzony wystarczająco duży ładunek, który utrzyma się przez
następne 10 lat. Aby to zapewnić, operację ładowania wykonuje się jeszcze trzykrotnie. Do tego celu
służy operacja „doprogramowywania" o czasie trwania 3n * lms. W ten sposób został zaprogramowany
pierwszy bajt i procedurę można powtórzyć pod następnym adresem, z nowymi danymi. Na końcu
programowania następuje przełączenie do trybu czytania i jeszcze jedna weryfikacja całej zawartości
pamięci. Dzięki zastosowaniu szybkiego algorytmu programowania czas programowania pamięci
EPROM o pojemności l Mb skraca się z ok. 2 godzin do poniżej 10 minut. Przez zmniejszenie czasu
trwania impulsu programującego do 100 us można w przypadku niektórych pamięci EPROM osiągnąć
nawet czasy poniżej l minuty.
52
Rysunek 4.52. Szybki algorytm programowania pamięci EPROM
W tablicy 4.18 podano zestawienie częściej używanych typów pamięci EPROM.
Tablica 4.18. Przykłady pamięci EPROM
53
4.5.11. Pamięci stałe kasowane elektrycznie - EEPROM
Nazwa EEPROM (electrically erasable PROM) oznacza pamięć PROM, której zawartość -w
przeciwieństwie do pamięci EPROM -można kasować elektrycnie. W nowszych typach takich
pamięci w strukturze układu scalona jest także przetwornica (konwerter) wytwarzająca napięcie
programujące i układ czasowy (timer) do ustalania długości impulsu programującego. W celu
zaprogramowania bajtu wystarczy tylko podać adres i dane. Jeżeli podamy potem polecenie zapisu i
zainicjujemy operację programowania, EEPROM zapamiętuje wewnętrznie adres i dane, po czym
natychmiast zwalnia linie adresowe i linie danych. Dalszy ciąg operacji programowania przebiega
autonomicznie w strukturze układu scalonego. Najpierw jest kasowany stary bajt, a następnie
programowany nowy. Operacja ta jest wewnętrznie nadzorowana w celu zapewnienia, że
zaprogramowany ładunek jest wystarczająco duży. Czas trwania programowania wynosi l... 10
ms, a więc jest tego samego rzędu, jak w pamięciach EPROM. W niektórych pamięciach
EEPROM w jednej operacji programowania można zapisać nie tylko pojedynczy bajt, lecz całą
„stronę" mieszczącą 16... 64 bajty. W tym celu należy wpisać programowaną stronę do
wewnętrznej pamięci RAM i podać polecenie programowania. W ten sposób osiąga się efektywny
czas programowania jednego bajtu równy 30 us. Ta prostota operacji wpisywania i kasowania nie
daje jednak możliwości wykorzystywania pamięci EEPROM jako pamięci RAM, ponieważ liczba
cykli zapisu jest ograniczona. Jednego bajtu nie wolno zapisać więcej niż l04... 106 razy (w
zależności od typu układu scalonego).
Przy czasie programowania równym l ms już po 10 s można osiągnąć granicę trwałości
bajtu lub strony, jeżeli programowanie odbywałoby się w sposób ciągły. Z tego powodu w
niektórych typach układów łączy się pamięci EEPROM i RAM. Zawartość pamięci przenosi się do
pamięci EEPROM tylko w przypadku zaniku napięcia zasilania. Dzięki temu przy normalnej pracy
osiąga się krótki cykl zapisu, nie związany ze zjawiskami zużywania się pamięci.
Rozwiązanie pośrednie między pamięciami EPROM a EEPROM stanowią pamięci EEPROM
kasowane równolegle (Flash).
Można je kasować elektrycznie tak, jak pamięci EEPROM, ale nie bajt po bajcie, lecz całą pamięć
za jednym razem. Stąd też wzięła się nazwa tych układów: EEPROM typu „flash". Ich kasowanie
jest o wiele prostsze niż pamięci EPROM; wymaga podania tylko jednego impulsu kasującego
trwającego kilka sekund. Nie ma więc potrzeby wyjmowania elementu z układu i wkładania go na
ok. 20 minut do kasownika. Technologia produkcji tych elementów nie jest wcale bardziej złożona
od technologii elementów EPROM i umożliwia uzyskanie odpowiednio dużych gęstości
upakowania, a także niskiej ceny. Aby niepotrzebnie nie podrażać produkcji, w pamięciach
EEPROM typu „flash" z rodziny 28 rezygnuje się z przetwornicy (konwertera) napięcia
programującego i układu czasowego (timera) do ustalania długości impulsu programującego,
występujących w typowych pamięciach EEPROM. Dlatego też programuje si je tak samo, jak
pamięci EPROM.
Porównanie różnych odmian pamięci ROM z pamięciami RAM pod kątem możliwości zapisu i odczytu
jest przedstawione w tablicy 4.19.
Tablica 4.19. Porównanie pamięci RAM i ROM pod względem możliwości zapisu i odczytu
54
Widoczna jest wyższość pamięci RAM pod względem szybkości zapisu i odczytu, przy czym operacje
zapisu i odczytu mogą być powtarzane dowolnie często. W przypadku wszystkich odmian pamięci
ROM istnieje mniej lub więcej ograniczeń związanych z zapisem. Za to wszystkie pamięci ROM
zachowują swoją zawartość bez konieczności zasilania. W przypadku pamięci RAM własność tę można
uzyskać dołączając do układu baterię podtrzymującą. Pobór prądu wielu pamięci RAM CMOS - jak
to widać w tablicy 4.12 – jest mniejszy niż samowyładowanie baterii. Dlatego też i tutaj w
przypadku zastosowania odpowiednich baterii można zagwarantować 10-letni okres zachowania
danych.
Tablica 4.20. Przykłady pamięci EEPROM
4.5.12. Pamięć błyskowa - FLASH
Pamięć błyskowa (FLASH) jest również pamięcią programowaną i kasowaną elektrycznie. Koszt jej
produkcji jest niższy niż układu EEPROM. W porównaniu z pamięcią EEPROM cechuje się ona
szybszymi czasami programowania i kasowania. Najczęściej pamięć ta składa się z sektorów, na
których mogą być wykonywane odpowiednie operacje, posiada własną listę komend
automatyzujących programowanie i kasowanie pamięci.
Szczególną zaletą pamięci błyskowych (FLASH) w stosunku do pamięci EEPROM jest krótki czas
kasowania i zapisu. Do programowania i kasowania pamięci błyskowych potrzebne jest
podwyższone napięcie 11,5 - 13,5V, które w zależności od typu układu może być podawane z
zewnątrz lub wytwarzane przez wbudowaną przetwornicę. Pamięci FLASH przyjmują oprócz
danych polecenia, które umożliwiają realizację różnych rodzajów operacji. Ten typ pamięci zostanie
przedstawiony na przykładzie popularnej pamięci typu 29F010 firmy AMD (Advanced Micro
55
Devices) o organizacji 128k x 8 bitów. Na rys. 4.53 pokazano symbol logiczny pamięci wraz z
opisem linii.
Rysunek 4.53. Symbol logiczny pamięci Am29F010
Pamięć Am29F010 jest 1Mbit, 5V pamięcią FLASH zorganizowaną jako 131072 bajtów.
Produkowana jest w 32-pinowych obudowach typu PLCC ,TSOP i PDIP. Zaprojektowano ją z
możliwością programowania w systemie ze standardowym 5V zasilaniem. Ponadto może być
programowana za pomocą standardowego programatora do pamięci EPROM.
Pamięć ta posiada następujące właściwości:
− pojedyncze zasilanie, 5V +-10% dla czytania, zapisu i operacji kasowania programu,
− maksymalny czas dostępu 45ns,
− niskie zużycie energii, maksymalnie 30mA na odczyt i 50mA na programowanie oraz
czyszczenie, mniej niż 25µA podczas trybu standby,
− elastyczna architektura oparta na sektorach, 8 zunifikowanych sektorów, wszystkie kombinacje
sektorów mogą być czyszczone,
− możliwość wymazania całego chipu,
− ochrona sektorów przed zapisem,
− wsparcie sprzętowe dla zablokowania i odblokowania programowania i czyszczenia dla
wszystkich kombinacji sektorów,
− wbudowany algorytm czyszczenia automatycznie przeprogramuje i czyści chip lub wszystkie
kombinacje wybranych sektorów,
− wbudowany algorytm programowania automatycznie programujący i sprawdzający dane z
zadanego adresu,
− minimum 100000 gwarantowanych cykli programowania i czyszczenia,
− programowe metody detekcji końca cyklu programowania i czyszczenia.
Pamięć posiada wbudowany algorytm programowania (wewnętrzny algorytm, który automatycznie
weryfikuje szerokość i czas trwania impulsów programowania). Zawiera ona także wbudowany
algorytm czyszczenia. Podczas czyszczenia urządzenie automatycznie kontroluje czas i szerokość
sygnałów oraz weryfikuje właściwe komórki docelowe. System nadrzędny może wykrywać
zakończenia operacji czyszczenia/programowania poprzez czytanie bitów statusu: DQ7
(DATA#Polling) i DQ6 (toggle). Po zakończeniu cyklu programowania/czyszczenia pamięć jest
gotowa do czytania z niej danych lub oczekuje na następną komendę. Sektorowa architektura
pamięci pozwala na czyszczenie, czy ponowne programowanie wybranych sektorów pamięci bez
wpływu na pozostałe sektory. Sprzętowa ochrona danych wykrywa niski poziom napięcia zasilania i
wstrzymuje proces zapisywania podczas zmiany napięcia. Pamięć można przełączyć w tryb standby,
w celu znacznej redukcji pobieranej mocy.
Na rys. 4.54 przedstawiono schemat blokowy pamięci Am29F010.
56
Rysunek 4.54. Schemat blokowy pamięci Am29F010
Jak widać, składa się ona z wielu bloków, z których część służy do obsługi procesu zapisu do
pamięci (blok Cell Matrix), są nimi generatory napięć PGM Voltage Generator i Erase Voltage
Generator. Pracą całego układu zarządza blok State Control / Command Register. Komórki pamięci
są wybierane za pomocą układu dekodera adresu. Sterowanie przepływem danych odbywa się za
pośrednictwem dwukierunkowego bufora i rejestru zatrzaskującego oraz bloku Chip Enable /
Output Enable Logic. Rejestr komend (Command Register) składa się z zatrzasków, które
przechowują komendy z adresami i danymi potrzebnymi do wykonania komendy. Zawartość
rejestru służy jako wejścia dla „wewnętrznej maszyny stanu”. Wyjścia maszyny stanu dyktują
funkcje urządzenia. Funkcje te (operacje na szynie danych) wykonywane przez układ sterownia
pamięci Flash przedstawiono w tablicy 4.21.
Tablica 4.21. Operacje na szynie danych pamięci Am29F010
Aby odczytać dane z pamięci system musi zapewnić niski stan linii CE# i OE#. Linia CE#
kontroluje odczyt. Linia OE# steruje buforem wyjściowym. Sygnał na linii WE# powinien być na
poziomie VIH. Żadna komenda nie jest wymagana w tym trybie. Jest on trybem domyślnym po
włączeniu napięcia zasilania. Zatem mk może podawać na linie adresowe A0 – A16 adresy danych,
które chce otrzymać na liniach danych DQ0 – DQ7. Urządzenie pozostaje dostępne do odczytu
dopóki nie zmieni się zawartość rejestru komend. Aby zapisać komendę lub sekwencję komend
(które zawierają dane programujące czy czyszczące wybrane sektory pamięci), system musi
zapewnić następujące stany: na liniach WE# i CE# stan niski VIL oraz na linii OE# stan wysoki
VIH. Operacja czyszczenia może skasować jeden sektor, wiele sektorów lub całe urządzenie.
57
Tablica adresów sektorów wskazuje na adres w przestrzeni jaką każdy sektor zajmuje. „Adres
sektora” to bity adresu potrzebne aby jednoznacznie zidentyfikować sektor (patrz tablica 4.22).
Tablica 4.22. Tablica adresów sektorów pamięci Am29F010
Podczas operacji czyszczenia lub programowania system może sprawdzić status operacji przez
czytanie bitów statusu DQ7-DQ0. Pamięć posiada tryb autoselect, który umożliwia identyfikację
urządzenia oraz producenta, a także weryfikację chronionych sektorów przez kody identyfikacyjne
podane na DQ7-DQ0. Ten tryb jest niezbędny dla urządzeń programujących, aby mogły
wykorzystać odpowiedni algorytm programujący. Ten tryb może być także wykorzystany w
systemie przez rejestr komend. Pamięć można wprowadzić w tryb autoselect wydając odpowiednią
komendę (tablica 4.23).
Zapis adresu i danej rozkazu lub całej sekwencji rozkazowej do rejestru rozkazów inicjuje
wykonanie operacji. Poprawne sekwencje rozkazowe przedstawia tabela rozkazów (tablica 4.23).
Tablica 4.23. Formaty poleceń sterowania pamięcią Am29F010
Zapis niepoprawnych wartości adresu i danych lub zapis sekwencji w nieodpowiedniej kolejności
przestawia pamięć w tryb odczytu danych. Adres jest "zatrzaskiwany" w momencie pojawienia się
opadającego zbocza na linii WE# lub CE#, w zależności od tego, które z tych zdarzeń wystąpi jako
ostatnie.
58
Rozkaz AUTOSELECT umożliwia uzyskanie dostępu do kodów producenta i pamięci, a także
pozwala na ustalenie, czy dany sektor jest chroniony. Na sekwencję rozkazową składa się rozkaz
AUTOSELECT poprzedzony zapisem 2 cykli odblokowujących. Następnie pamięć wchodzi w tryb
autoselect i możliwy jest odczyt spod każdego adresu dowolną ilość razy bez inicjowania kolejnej
sekwencji rozkazowej. Cykl odczytu spod adresu XX00h zwraca kod producenta, a spod adresu
XX01h kod urządzenia. Cykl odczytu zawierający adres sektora (SA) i adres 02h zwraca 01h jeśli
ten sektor jest chroniony, a 00h w przeciwnym wypadku. W celu wyjścia z trybu autoselect do
pamięci trzeba przesłać rozkaz RESET.
Programowanie pamięci składa się z 4 cykli szyny (rozkaz PROGARM). Na sekwencję rozkazową
składa się rozkaz ustawiający tryb programowania poprzedzony zapisem 2 cykli odblokowujących.
Dane i adres są wysyłane w następnej kolejności. Operacja ta inicjuje wykonanie wbudowanego
algorytmu programowania. System programujący nie musi dostarczać dodatkowych sygnałów
sterujących czy t
aktujących. Urządzenie samo generuje wewnętrzne impulsy programujące i weryfikuje poprawność
zaprogramowania komórki. Kiedy wbudowany algorytm programowania zakończy działanie
urządzenie wraca do trybu odczytu danych i zwalniany jest przerzutnik "zatrzaskujący" adresy.
System nadrzędny może ustalić status operacji programowania na podstawie stanu linii DQ6 i DQ7.
Wszystkie rozkazy wysyłane do urządzenia podczas wykonywania wbudowanego algorytmu
programowania są ignorowane. Programowanie może odbywać się w dowolnej kolejności i może
przekraczać granice sektorów.
Sekwencja kasowania pamięci składa się 6 cykli szyny. W jej skład wchodzi rozkaz ustawienia
(set-up) poprzedzony zapisem 2 cykli odblokowujących. Po nich następują kolejne 2 cykle
odblokowujące zapis i rozkaz kasowania, który uruchamia wbudowany algorytm kasowania.
Wszystkie rozkazy wysyłane do urządzenia podczas wykonywania wbudowany algorytm kasowania
są ignorowane. Kiedy ten algorytm zakończy działanie urządzenie wraca do trybu odczytu danych i
zwalniany jest przerzutnik "zatrzaskujący" adresy.
Na rozkaz kasowanie sektora również składa się 6 cykli szyny. Pierwszym jest rozkaz ustawienia
(set-up) poprzedzony zapisem 2 cykli odblokowujących. W następnej kolejności wysyłane są 2
dodatkowe cykle odblokowujące. Potem zapisywane są: adres sektora do kasowania oraz rozkaz
kasowania. Po zapisie sekwencji rozkazowej rozpoczyna się 50µs przerwy. W trakcie tej przerwy
mogą zostać przesłane dodatkowe adresy i rozkazy kasowania sektorów. Załadowanie bufora
kasowania sektorów może się odbyć w dowolnej kolejności. Dowolna może być także liczba
sektorów przeznaczonych do skasowania. Odstęp czasu między tymi dodatkowymi cyklami, w
których przesyłane są informacje o dodatkowych sektorach do skasowania musi być mniejszy niż
50µs. Jakikolwiek rozkaz wysłany podczas 50µs przerwy przestawia urządzenie w tryb odczytu.
System musi ponownie wysłać sekwencje rozkazową oraz adresy dodatkowych sektorów i rozkazy.
System może nadzorować stan linii DQ3 w celu sprawdzenia, czy minął czas przerwy. Przerwa
zaczyna się od narastającego zbocza ostatniego impulsu w sekwencji rozkazowej na linii WE#.
Wszystkie rozkazy wysyłane do urządzenia podczas kasowania sektora są ignorowane. Kiedy
wbudowany algorytm kasowania zakończy działanie urządzenie wraca do trybu odczytu danych i
zwalniany jest przerzutnik "zatrzaskujący" adresy.
System nadrzędny może ustalić status operacji programowania przy wykorzystaniu linii DQ6 i
DQ7. Stan operacji zapisu można sprawdzić wykorzystując linie: DQ3, DQ5, DQ6 i DQ7. Za
pomocą pinów DQ7 i DQ6 można sprawdzić, czy operacja programowania lub kasowania została
zakończona (tablica 4.24).
59
Tablica 4.24. Status operacji zapisu
Na poniższym rysunku pokazano przebiegi czasowe operacji odczytu danej z pamięci.
Rysunek 4.55. Przebieg czasowy operacji odczytu z pamięci Am29F010
Na poniższym rysunku pokazano przebiegi czasowe operacji zapisu danej do pamięci.
Rysunek 4.56. Przebieg czasowy operacji programowania pamięci Am29F010
Na poniższym rysunku pokazano przebiegi czasowe operacji kasowania pamięci.
60
Rysunek 4.57. Przebieg czasowy operacji kasowania pamięci Am29F010
4.5.13. Układy logiki programowalnej – PLD
Układy logiki programowalnej (programmable logic demces, PLD) służą do pamiętania funkcji
logicznych. Znane są trzy rodzaje takich układów: PLA, PAL i LCA. Różnią się one możliwościami
programowania. Najprościej programuje się układy PAL (programmable array logie), dlatego cieszą
się one dużą popularnością i występują w wielu odmianach. Programowalne matryce logiczne PLA
(programmable logie array) są bardziej uniwersalne, ale ich programowanie jest bardziej
skomplikowane, dlatego nie odgrywają obecnie większej roli. Nowymi elementami są układy LCA (logie
celi array), które umożliwiają programowanie nie tylko funkcji logicznych, lecz także pól połączeń
między różnymi blokami logicznymi. Dzięki temu mogą one zastępować zwykłe matryce bramek i
można je nazwać matrycami logicznymi programowalnymi przez użytkownika.
a b c d
a
b
1
d
&
a*b*d
&
Vcc
a
b
0
d
>
1
a b c d
a*b*d
a b c d
a+b+d
&
a*b*d
a b c d
>
1
a+b+d
>
1
a+b+d
Rysunek 4.58. Uproszczony sposób przedstawiania funkcji AND i OR.
Jeśli przy realizacji funkcji logicznej skorzystamy z normalnej postaci sumy, musimy najpierw
utworzyć wymagane iloczyny logiczne zmiennych wejściowych, a potem sumy logiczne tych
iloczynów. Aby przedstawić układ w sposób przejrzysty, stosuje się skrócony zapis pokazany na rys.
4.58. (Krzyżyki wskazują, które z wyjść są dołączone. Wejście nie dołączone nie ma wpływu na stan
układu, gdyż w przypadku funkcji AND jest równoważne stanowi 1, a w przypadku funkcji OR stanowi
0.)
61
Zmienne wejściowe i ich negacje wraz z krzyżującymi się z nimi wejściami bramek AND tworzą
matrycę, w której można zaprogramować wszystkie potrzebne iloczyny. Aby otrzymać potrzebne
sumy logiczne, w odpowiedniej drugiej matrycy można zrealizować połączenia między wyjściami
bramek AND i bramkami OR. Na jedną zmienną wyjściową jest potrzebna przy tym tylko jedna
bramka OR.
W przypadku układów PLA (rys. 4.59 u góry) użytkownik ma możliwość programowania obu
matryc. W układzie PAL (rys. 4.59 u dołu) matryca OR jest narzucona przez producenta; tutaj
można programować tylko matrycę AND.
Rysunek 4.59. Układ PLD
Rysunek 4.60. Układ PLD
Za pamięć funkcyjną można również uważać pamięć PROM. Jeżeli dekoder adresu interpretuje się
jako matrycę iloczynów logicznych (AND), uzyskuje się wówczas układ pokazany na rys. 4.60. Dla
każdego adresu tylko jeden iloczyn logiczny ma wartość “jeden", i to właśnie ten, który odpowiada
podanemu adresowi. Mamy tu więc n = 2N iloczynów logicznych, podczas gdy układy PLA i PAL
mają ich znacznie mniej. To, czy przynależna wartość funkcji jest równa l czy 0, ustala się przez
62
zaprogramowanie matrycy OR. Pamięci PROM przewidziane do realizacji funkcji logicznych są
oznaczane skrótem PLE (programmable logie element). Różnice między tymi elementami
wyjaśnimy na przykładzie funkcji logicznych z rys. 4.61. W tym celu usuniemy wszystkie
połączenia, które dla rozważanych funkcji nie są potrzebne.
Rysunek 4.61. Przykład tablicy prawdy, jej funkcje i ich realizacja za pomocą układów PLA, PAL i
PROM
Nietrudno zauważyć, że zawartość pamięci PROM stanowi odwzorowanie tablicy prawdy, podczas
gdy układy PLA i PAL reprezentują funkcje logiczne. W pamięci PROM można zapamiętać
dowolną tablicę prawdy, podczas gdy w układzie PLA lub PAL dysponujemy tylko ograniczoną
ilością iloczynów i sum logicznych. Z tego też względu nie mamy tu możliwości realizacji
dowolnych tablic prawdy, lecz tylko te, które prowadzą do prostych funkcji logicznych. Aby
efektywnie wykorzystać układy PAL, musimy maksymalnie uprościć funkcje logiczne, korzystając z
algebry Boole'a, a w razie potrzeby za pomocą prawa de Morgana przekształcić iloczyny na sumy
logiczne. Dzisiaj nie robi się już tego ręcznie, lecz korzysta ze specjalnych programów wspomagających
projektowanie, pracujących na każdym komputerze osobistym.
Układy PAL
Układy PAL (programmable array logie) są najważniejszym przedstawicielem rodziny układów
logiki programowalnej (PLD). Dostępne są w wielu różnych odmianach, ale wszystkie oparte na
zasadzie pokazanej na rys. 4.58. Różnice polegają na odmiennych wykonaniach sum logicznych na
wyjściu. Najczęściej używane układy PAL są przedstawione na rys. 4.62. Typ H (z wyjściem
prostym - high, H) to typ podstawowy. Typ L ma wyjście zanegowane (Iow, L). Typ S (sharing) ma
strukturę zbliżoną do układu PLA. Ma możliwość częściowego programowania matrycy OR: dwie
sąsiadujące ze sobą sumy logiczne można w dowolny sposób łączyć z wyjściami współpracujących
iloczynów. Dzięki temu można tworzyć funkcje, dla których w innym przypadku zabrakło by sum
logicznych. W wielu układach PAL wyjście można wykorzystać również jako wejście lub też
zaprogramować końcówkę dwukierunkową (WE/WY).
63
Rysunek 4.62. Układy wyjściowe struktur PAL
Do tego celu służy bramka trójstanowa na wyjściu, której samo wejście zezwolenia (enable)
stanowi już funkcję logiczną. Ważną dziedziną zastosowań elementów PAL są układy
sekwencyjne. Aby nie były potrzebne żadne dodatkowe elementy, w strukturze PAL scala się
również rejestry (R). Rejestry te mają wspólne wyprowadzenie wejść zegarowych, umożliwiające
budowę synchronicznych układów sekwencyjnych. Sygnały wyjściowe są przeważnie podawane
wewnątrz układu z powrotem do matrycy AND, dzięki czemu zaoszczędza się na zewnętrznych
liniach sprzęgających i niepotrzebnie nie zajmuje wejść. Jeżeli do każdego zastosowania
chcielibyśmy użyć optymalnego układu PAL, potrzebowalibyśmy - jak widać na rys. 4.62wielu różnorodnych typów. Aby zredukować liczbę typów, na rynek wprowadza się coraz
więcej układów PAL z programowalną strukturą wyjść. Tego rodzaju makrokomórka V
(variable) jest przedstawiona na rys. 4.62. Jej jądrem jest multiplekser, umożliwiający wybór
jednego z czterech trybów pracy. Wyboru dokonuje się przez zaprogramowanie bitów
konfiguracyjnych f0 f1. W tablicy 4.25 zestawiono tryby pracy układu.
Tablica 4.25. Tryby pracy programowalnej makrokomórki
64
Bit f0 określa, czy wyjście ma być proste, czy zanegowane.
Bit f1 przełącza układ z pracy asynchronicznej na synchroniczną i odwrotnie.
Równocześnie drugi multiplekser przełącza sprzężenie z wyjścia na rejestr. Widać stąd, że za
pomocą tego jednego typu można zrealizować funkcje większości układów PAL.
Układy logiczne CPLD na przykładzie rodziny układów XC9500 firmy Xilinx
Układy logiczne CPLD zostaną przedstawione na przykładzie rodziny układów XC9500 firmy
Xilinx. Są one programowalne i testowalne w docelowym mse. Rodzina ta charakteryzuje się
następującymi właściwościami:
− duża szybkość działania (5ns opóźnienia pomiędzy pinami, fCNT do 125 MHz),
− duża gęstość upakowania (od 36 do 288 makrokomórek z 800 do 6,400 użytecznymi
bramkami),
− układy programowalne w systemie o napięciu zasilania 5V (możliwość wykonania 10000 cykli
programowania/kasowania),
− układy składają się z „elastycznych” bloków funkcyjnych (odpowiadających układom GAL typu
36V18), 90 linii product terms sterujących pojedynczymi lub wszystkimi 18 makrokomórkami
wewnątrz bloku funkcyjnego,
− posiadają interfejs standardu IEEE 1149.1 (JTAG),
− zapewniają programowalny tryb redukcji mocy dla każdej komórki,
− wyjścia układów przewodzą prąd do 24mA,
− piny wejściowo-wyjściowe mogą być ustawione na standard 3,3V lub 5V.
Tablica 4.26. Rodzina układów XC9500
Rysunek 4.63. Architektura układów rodziny XC9500
65
Na potrzeby programowania i testowania układów w systemie rozszerzono listę instrukcji
sterujących interfejsem JTAG. Zatem interfejs ten pozwala nie tylko na testowanie zgodnie ze
standardem IEEE 1149.1, ale również i programowanie układów zamontowanych już w systemie.
Możliwość przeprowadzania wielokrotnej liczby cykli programowania/kasowania zapewnia dużą
swobodę w zmienianiu wewnętrznej konfiguracji układów, czy uaktualnianiu zawartych w nich
projektów. Dodatkowo zapewniono kontrolę szybkości narastania napięć wyjściowych oraz
umożliwiono programowe uziemienie pinów w celu lepszej redukcji szumów. Urządzenia
wejścia/wyjścia mogą być konfigurowane dla napięć 3,3V oraz 5V. Wszystkie wyjścia przewodzą
prąd do 24mA.
Każdy układ XC9500 jest podsystemem zawierającym bloki funkcyjne (FB – Function Block) i
bloki wejścia/wyjścia (IOB – I/O Block), które są łączone między sobą za pomocą matrycy
przełączającej (FastCONNECT switch matrix) (rys. 4.63). Bloki IOB buforują sygnały wejściowe i
wyjściowe z układu oraz zapewniają odpowiednie parametry elektryczne zacisków. Każdy blok
funkcyjny FB daje możliwość zaprogramowania 36 wejść i 18 wyjść. Matryca przełączająca łączy
wszystkie wyjścia bloku FB z wejściami innego bloku FB. Dla każdego bloku FB wyjścia w liczbie
od 12 do 18 (w zależności od liczby wyprowadzeń obudowy) skojarzone z sygnałami output enable
sterują bezpośrednio blokami IOB. Każdy blok funkcyjny, jak przedstawiono na rys. 4.64, składa
się z 18 niezależnych makrokomórek, z których każda może realizować funkcję kombinacyjną bądź
rejestrową. Do bloku funkcyjnego doprowadzony jest sygnał zegara oraz sygnały set/reset. Blok
funkcyjny poprzez generację stanów na 18 wyjściach steruje matrycą przełączającą. Wyjścia te wraz
z sygnałami output enable sterują blokami IOB.
Rysunek 4.64. Blok funkcyjny (FB) układów rodziny XC9500
Do programowalnej matrycy iloczynów logicznych dochodzą 72 sygnały (36 normalnych sygnałów
i 36 ich negacji). Sygnały te są przez nią łączone do 90 linii product term dochodzących do 18
makrokomórek. Dla każdego bloku FB możliwe jest zrealizowanie połączeń (ścieżek) z wyjść
makrokomórek do matrycy iloczynów logicznych, bez potrzeby wyprowadzania ich poza dany blok
FB. Ścieżki te wykorzystywane są do tworzenia bardzo szybkich liczników oraz układów stanów,
gdzie wszystkie rejestry stanu są wewnątrz tego samego bloku FB. Każda makrokomórka w bloku
FB układu XC9500 może być indywidualnie skonfigurowana tak, aby realizować funkcje
kombinacyjne lub rejestrowe.
Rys. 4.65 przedstawia makrokomórkę i towarzysząca jej strukturę logiczną bloku FB. Pięciu linii
product terms bezpośrednio wyprowadzonych z matrycy iloczynów logicznych można użyć jako
podstawowych wejść danych (do bramek OR i XOR). Pozwalają one na implementację funkcji
kombinacyjnej lub mogą posłużyć jako wejścia sterujące włączając w to sygnały zegara, set/reset i
66
output enable. Blok PTA (Product Term Allocator), zawarty w każdej makrokomórce, służy do
wyboru sposobu użycia tych pięciu linii.
Rysunek 4.65. Makrokomórka bloku FB układów XC9500
Rejestr makrokomórki może być skonfigurowany jako przerzutnik D lub T, lub też może być
przeznaczony do operacji kombinacyjnych. Każdy rejestr wyposażony jest w dwie asynchroniczne
operacje ustawiania (set) i zerowania (reset). Podczas włączania zasilania wszystkie
wykorzystywane rejestry są inicjalizowane do stanu zdefiniowanego przez użytkownika (w
przypadku braku specyfikacji domyślnie ustawiane jest 0). Wszystkie globalne sygnały takie jak
sygnały zegara, set/reset oraz output enable są dostępne dla każdej makrokomórki. Sygnał zegarowy
dochodzący do rejestru makrokomórki może być jednym z trzech globalnych sygnałów zegara lub
sygnałem zegara pochodzącym z linii product term, co przedstawiono na rys. 4.66. Dodatkowo
istnieje możliwość wyboru aktywnego zbocza sygnału zegarowego. Poprzez wejście GSR możliwe
jest ustawienie rejestru użytkownika do zdefiniowanego przez niego stanu. Blok PTA
makrokomórki steruje wykorzystaniem pięciu bezpośrednich linii product terms dochodzących do
niej. Np. wszystkie pięć linii może być dołączonych do bramki OR, jak pokazano na rys. 4.67. Blok
PTA może dokonywać zmian wewnątrz FB i przydzielać makrokomórce dodatkowe linie, oprócz
pięciu podstawowych dochodzących już do niej.
67
Rysunek 4.66. Sposób wyboru sygnałów zegarowych set/reset w makrokomórce bloku FB układów
rodziny XC9500
Rysunek 4.67. Wykorzystanie bezpośrednich linii product terms w makrokomórce
Każda makrokomórka wymagająca dodatkowej linii product term może skorzystać z
niewykorzystanej linii innej makrokomórki wewnątrz bloku FB. Pojedyncza makrokomórka może
użyć 15 linii product terms, przy czym należy uwzględnić dodatkowe opóźnienia sygnałów na
dodanych liniach, wynikające z wydłużenia się ich drogi wewnątrz bloku FB (rys. 4.68).
Elastyczność ta wynika z budowy bloku PTA pokazanej na rys. 4.69.
Rysunek 4.68. Blok PTA z 15 liniami product terms
68
Rysunek 4.69. Schemat logiczny bloku PTA
Rysunek 4.70. Schemat logiczny matrycy przełączającej (Fast CONNECT Switch Matrix)
Matryca przełączająca dostarcza sygnały z bloków IOB i FB do wejść bloków FB (rys. 4.70).
Wszystkie wyjścia bloków FB i wejścia/wyjścia bloków IOB są podawane na tę matrycę. Za
pomocą matrycy użytkownik wybiera sygnały, które mają dochodzić do danego bloku FB.
Dodatkowo realizuje ona iloczyn logiczny na drucie co zwiększa funkcjonalność całego układu.
69
Rysunek 4.71. Schemat logiczny bloku IOB wraz z układami sterujacymi sygnałami ouput enable
Bloki wejścia/wyjścia IOB stanowią interfejs pomiędzy wewnętrzną logiką, a pinami
wejścia/wyjścia układu. Każdy blok zawiera bufor wejściowy, sterownik wyjściowy, multiplekser
wyboru output enable oraz programowalne uziemienie (rys. 4.71). Bufor wejściowy jest
kompatybilny ze standardami 5V CMOS, 5V TTL i poziomami sygnału 3,3V. Bufor wejściowy
używa wewnętrznego 5V źródła zasilania (VCCINT) w celu zapewnienia stałych progów wejścia i
eliminacji wahań napięcia VCCIO. Sygnał output enable może być generowany w następujący
sposób, jako: sygnał product term z makrokomórki, dowolny sygnał zegara globalnego, zawsze „1”
lub zawsze „0”. Rezystory są de aktywowane podczas normalnych operacji. Sterownik wyjściowy
jest zdolny do przewodzenia prądu 24mA. Wszystkie sterowniki wyjściowe w układzie mogą być
skonfigurowane dla poziomu 5V lub poziomu 3,3V przez połączenie wyjściowego pinu zasilania
(VCCIO) do 5V lub do źródła zasilania 3,3V.
Rys. 4.72 pokazuje jak układ XC9500 może być zasilany tylko napięciem 5V lub napięciem 5V i
3,3V.
Rysunek 4.72. Sposoby zasilania układu rodziny XC9500: a) jedno źródło zasilania 5V,
b) dwa źródła zasilania 5V i 3,3V
Programowanie i testowanie układów rodziny XC9500 jest realizowane za pomocą interfejsu
standardu IEEE 1149.1 (JTAG). Interfejs ten posiada następującą listę instrukcji: EXTES,
70
SAMPLE/PRELOAD, BYPASS, USER-CODE, INTEST, IDCODE, HIGHZ. Dodatkowo na
potrzeby programowania układów w systemie (ISP) dodano 5 instrukcji: ISPEN, FERASE, FPGM,
FVFY, ISPEX. Stanowią one rozszerzenie zestawu instrukcji 1149.1. Zgodnie ze specyfikacją
standardu IEEE 1149.1 piny TMS i TCK układu interfejsu JTAG są podwieszone poprzez rezystory
pull-up do zasilania. Układy XC9500 zawierają zaawansowane sposoby ochrony danych, które
całkowicie zabezpieczają program przed nieautoryzowanym czytaniem lub pomyłkowym
skasowaniem, czy przeprogramowaniem. Użytkownik może ustawić odpowiednie bity w celu
ochrony kodu programu zawartego w układzie przed jego przeczytaniem. Skasowanie w całości
programu jest jedynym sposobem na wyzerowanie bitów zabezpieczających, tym samym na
odblokowanie odczytu z układu. Wszystkie układy XC9500 oferują możliwość ustawienia trybu
niskiego poboru mocy dla każdej makrokomórki z osobna lub dla wszystkich jednocześnie.
Zatem ważne dla danej aplikacji części układu mogą pozostać w standardowym trybie poboru
mocy, podczas gdy pozostałe mogą zostać zaprogramowane na operacje przy niskim poborze mocy.
W czasie włączania zasilania (power-up time) układy XC9500 są w stanie uśpienia dopóki napięcie
zasilające VCCINT nie osiągnie bezpiecznego poziomu (około 3,8 V). Do tego czasu wszystkie
piny układu oraz interfejsu JTAG są wyłączone i podwieszone do zasilania za pomocą rezystorów
pull-up. Kiedy napięcie zasilania osiągnie bezpieczny poziom wszystkie rejestry użytkownika są
inicjalizowane (typowo w czasie 100µs dla 9536 - 95144, 200µs dla 95216, 300µs dla 95288) po
czym układ jest gotowy do pracy.
4.6. Układy współpracy z wejściami oraz wyjściami binarnymi
Układami bardzo często spotykanymi w urządzeniach mikroprocesorowych są układy wejść i wyjść
binarnych. Prosty układ wejścia binarnego ma formę ośmiobitowej bramy trójstanowej podłączanej do
systemu np. w sposób pokazany na rysunku 4.73.
U1
2
3
4
5
6
7
8
9
CS WE
19
1
A0
A1
A2
A3
A4
A5
A6
A7
E
DIR
B0
B1
B2
B3
B4
B5
B6
B7
18
17
16
15
14
13
12
11
S1
S2
S3
S4
S5
S6
S7
S8
VCC
16
15
14
13
12
11
10
9
D0
D1
D2
D3
D4
D5
D6
D7
U2
10K
1
2
3
4
5
6
7
8
74HC245
Rysunek 4.73. Schemat prostego układu 8 wejść binarnych
Wejścia trójstanowe są otwierane sygnałem CSWE (pochodzącym z procesora oraz dekodera adresów),
podłączonym do wejścia zanegowanego E. Kierunek przesyłania danych wyznacza wejście DIR, do
którego podłączono 0 logiczne, co powoduje, że dane są wysyłane z portu B do portu A. Osiem
71
rezystorów umieszczonych po stronie sygnałów obiektowych, wymusza stan 0 logicznego na każdym z
bitów portu. Stan ten w przypadku zamknięcia któregokolwiek z zestyków zmienia się na 1 logiczną.
Prosty układ wyjścia dwustanowego ma formę ośmiobitowego zatrzasku podłączanego do systemu np. w
sposób pokazany na rysunku 4.74.
U10
U11
U2
U1
D0
D1
D2
D3
D4
D5
D6
D7
9
8
7
6
5
4
3
2
CS WY 11
1
8D
7D
6D
5D
4D
3D
2D
1D
8Q
7Q
6Q
5Q
4Q
3Q
2Q
1Q
12
13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
16
15
14
13
12
11
10
9
1K
CLK
OC
74HC574
U12
U13
U14
U15
U16
U17
LED
LED
VCC
LED
LED
LED
LED
LED
LED
Rysunek 4.74. Schemat prostego układu 8 wyjść binarnych
Przerzutniki wyjściowe układu są zapisywane sygnałem CSWY (pochodzącym z procesora oraz
dekodera adresów), podłączonym do wejścia CLK dokonującego wpisu. Wyjścia Q0-Q7 są na stałe
otwarte przez połączenie wejścia sterującego OC z 0 logicznym (sygnał GND). Osiem rezystorów po
stronie wyjść ogranicza prąd płynący przez diody LED będące elementami sygnalizacyj-nymi
umieszczonymi po stronie sygnałów obiektowych. Ośmiobitowy rejestr zatrzaskujący 74HC/HCT574,
wykorzystany w przedstawionym na rysunku 4.74. układzie wyjść binarnych, ma następujące cechy:
- trójstanowe nieodwracające wyjścia, pozwalające na stosowanie układu w systemach
magistralowych,
- 8-bitowy rejestr składający się z przerzutników typu D wyzwalanych zboczem narastającym
sygnału CP,
- każdemu przerzutnikowi przyporządkowana jest linia wejściowa i wyjściowa,
- wszystkie przerzutniki mają wspólny sygnał zegara CP (clock) oraz sygnał sterowania
trójstanowymi buforami wyjściowymi OE.
Gdy na linii CP pojawi się zbocze narastające, to stan sygnałów na liniach wejściowych układu
(DO - D7) zostaje zapamiętany w rejestrze. Kiedy sygnał OE jest w stanie wysokim, wyjścia układu
(QO - Q7) są w stanie wysokiej irnpedancji. Stan niski na linii OE spowoduje wystawienie
zawartości rejestru na linie wyjściowe. Linia OE nie wpływa na zawartość rejestrów układu.
Na rys. 4.75 pokazano wyprowadzenia końcówek układu oraz jego schemat funkcjonalny.
72
Rysunek 4.75. Schemat wyprowadzeń oraz schemat funkcjonalny układu 74HC574
Rysunek 4.76. Schemat logiczny układu 74HC574
Bardziej skomplikowany układ programowanej bramy wejścia/wyjścia został pokazany na rysunku 4.77.
Wykorzystuje on popularny układ 8255A PIO (ang. programmable input-output) zawierający trzy
ośmiobitowe bramy o programowalnym kierunku przepływu danych.
Do portu A zaprogramowanego jako wyjścia binarne podłączono szeregowo osiem diod LED oraz
rezystorów ograniczających prąd wspomnianych diod.
Do portu B zaprogramowanego jako wejścia binarne podłączono osiem rezystorów, wymuszających stan
0 logicznego na każdym z bitów portu. Stan ten w przypadku zamknięcia któregokolwiek z zestyków S1S8 zmienia się na 1 logiczną.
Na rysunku 4.78 przedstawiono w uproszczeniu wewnętrzną strukturę tego układu 8255. Układ
steruje 24 liniami wejścia/wyjścia podzielonymi na dwie sekcje (grupy) A i B zawierające po 12
linii. Interfejs może sterować dowolnymi układami cyfrowymi TTL lub CMOS i bezpośrednio
współpracować z większością mikrokontrolerów.
73
U10
U11
U2
U1
5
RD
WR 36
9
A0
8
A1
RESET 35
CS 8255 6
D0
D1
D2
D3
D4
D5
D6
D7
PA0
PA1
PA2
PA3
PA4
PA5
PA6
PA7
RD
WR
A0
A1
RESET
CS
PB0
PB1
PB2
PB3
PB4
PB5
PB6
PB7
PC0
PC1
PC2
PC3
PC4
PC5
PC6
PC7
4
3
2
1
40
39
38
37
1
2
3
4
5
6
7
8
16
15
14
13
12
11
10
9
18
19
20
21
22
23
24
25
14
15
16
17
13
12
11
10
U12
U13
U14
S1
S2
S3
S4
S5
S6
S7
S8
16
15
14
13
12
11
10
9
34
33
32
31
30
29
28
27
U15
U16
U17
VCC
LED
LED
LED
LED
LED
LED
LED
VCC
U2
10K
1
2
3
4
5
6
7
8
D0
D1
D2
D3
D4
D5
D6
D7
1K
LED
8255
Rysunek 4.77. Schemat modułu wejść/wyjść binarnych wykorzystującego układ 8255
Rysunek 4.78. Schemat wewnętrzny układu 8255
Grupa linii A składa się z 8-bitowego portu A oraz czterech bardziej znaczących bitów portu C
(PC7-4), natomiast grupa B obejmuje 8-bitowy port B i cztery mniej znaczące bity portu C (PC3-0).
Układ jest wybierany sygnałem CS i zawiera cztery rejestry adresowane bitami Al i AO.
Przyporządkowanie adresów rejestrom wewnętrznym oraz funkcje rejestrów podano w tablicy 4.4.
74
Tablica 4.27. Wewnętrzne rejestry układu 8255A PIO
Adres
Al A0
0 0
0 1
l 0
1 1
Rejestr
Port A
Port B
Port C
Sterujący
Funkcja
Rejestr danych portu A
Rejestr danych portu B
Rejestr danych portu C
Rejestr konfiguracji portów A, B, C
Po sygnale RESET wszystkie linie interfejsu są zdefiniowane jako wejścia.
Rysunek 4.79. Funkcje bitów w rejestrze sterującym układu 8255
Użytkownik może zmienić kierunek przepływu danych w bramie, wpisując odpowiednie słowo
sterujące do jej rejestru sterującego.
Funkcje poszczególnych bitów w rejestrze sterującym przedstawiono na rysunku 4.79. Słowo
wpisywane pod adres AlA0 = 11 zostanie zinterpretowane jako słowo definicji kierunków
transmisji tylko wtedy, gdy najbardziej znaczący bit jest ustawiony (D7 = l). Jak wynika z rysunku
4.79, układ umożliwia niezależne definiowanie kierunków transmisji w porcie A i B oraz w każdej
z połówek portu C.
Ponadto dla każdego z portów definiuje się tryb pracy, określający sposób współpracy z
urządzeniem zewnętrznym sterowanym przez ten port. Port A może pracować w trybach 0, l i 2,
natomiast port B w trybach 0 i l. Poszczególne tryby różnią się sposobem wykorzystania linii portu
C do synchronizacji transmisji między interfejsem a urządzeniem zewnętrznym.
Jeśli słowo sterujące wpisywane pod adres A1A0 = 11 ma zero na pozycji najbardziej
znaczącego bitu (D7 = 0), wówczas jego znaczenie jest inne. Jest ono mianowicie używane do
ustawiania bądź zerowania poszczególnych bitów portu PC, zgodnie z opisem podanym na rysunku
4.80. Dla przykładu, wpis słowa 0xxx0010 spowoduje wyzerowanie bitu PCI, natomiast wpis słowa
0xxx1011 ustawi bit PC5. Możliwość manipulowania poszczególnymi bitami portu C rozszerza
zakres stosowania interfejsu 8255A, który, jak widać, nadaje się nie tylko do realizacji transmisji
równoległej, ale również do sterowania pojedynczymi liniami (diodami LED, przekaźnikami itp.).
Oczywiście, przyłączając do portu C urządzenia zewnętrzne należy zadbać, by nie przekroczyć
maksymalnych obciążalności wyjść w stanie niskim i wysokim.
75
Rysunek 4.80. Przykładowa konfiguracja portu A układu 8255 w trybach 1 i 2
4.7. Układ współpracy z wyświetlaczem 7 segmentowym LED
Układem spotykanym w starszych urządzeniach mikroprocesorowych jest zestaw wyświetlaczy
siedmiosegmentowych pozwalający użytkownikowi na wizualizację komunikatów pochodzących z
urządzenia.
Wyświetlacz 7-segmcntowy sterowany jest poprzez 2 bufory - porty wyjściowe podłączone do szyny.
Bufor wyboru wskaźnika (U23 – CSDS=FF30H) - dane wpisane do tego bufora określają, który
wskaźnik ma być w danym momencie aktywny. Stosowane są tzw. Kody l z 8, czyli każdy bit decyduje
indywidualnie o świeceniu konkretnego wskaźnika. Typowo wybrany będzie faktycznie tylko l z 7
wskaźników. Ustawienie l na poszczególnym bicie powoduje świecenie odpowiedniego wskaźnika. Bit 0
decyduje o świeceniu wskaźnika l, bit l decyduje o świeceniu wskaźnika 2 itd. Bit 6 decyduje o
świeceniu diod świecących, które zostały podłączone jako wskaźnik 7
Tablica 4.28. Bufor wskaźnika wyboru
76
Rysunek 4.81. Schemat przykładowego układu wyświetlacza siedmiosegmentowego
77
Bufor danych wskaźnika (U22 – CSDB=FF38H) – bajt umieszczony w tym buforze określa,
które segmenty wyświetlacza będą zapalone w wybranym wskaźniku. Jedynka umieszczona na
konkretnym bicie powoduje świecenie odpowiedniego segmentu lub diody świecącej, zgodnie z
opisem.
Rysunek 4.82. Bufor danych wskaźnika
Przykład przedstawia proste sterowanie wyświetlaczem 7-segmentowym.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
0096
FF30
FF38
0009
005B
0000: 02 01 00
0100:
0100:
0100: 90 FF 30
0103: 74 09
0105: F0
0106: 90 FF 38
0109: 74 5B
010B: F0
010C: C2 96
010E: 80 FE
SEG_ON EQU
P1.6
;bit. włączenia wyświetl. 7-segm.
;Pełne adresy urządzeń we/wy systemu DSM-51
F_CSDS EQU 0FF30H
;bufor wyboru wskaźnika
F_CSDB EQU 0FF38H
;bufor danych wskaźnika
;Stałe używane w programie
DISPLAY EQU 00001001B
;wybrane wskaźniki – 1 i 4
COD
EQU
01011011B
;wybrane segmenty
LJMP START
ORG 100H
;przesunięcie kodu instrukcji do adresu 100H
START:
MOV DPTR,#F_CSDS ;adres bufora wyboru wskaźnika
MOV A,#DISPLAY
MOVX @DPTR,A
;wpisz wybrane wskaźniki
MOV DPTR,#F_CSDB ;adres bufora danych wskaźnika
MOV A,#COD
MOVX @DPTR,A
;wpisz wybrane segmenty
CLR
SEG_ON
;włącz wyświetlacz 7-segmentowy
SJMP $
W przykładzie przedstawiony jest sposób zapisu danych do portów podłączonych do szyny
mikrokontrolera.
Zapis danych do tych portów polega na podaniu przez mikrokontroler odpowiedniego adresu na szynę
adresową i sygnału WR (porty wyjściowe umieszczone są w obszarze pamięci danych. Oznacza to, że do
zapisania potrzebny jest sygnał WR). Po podaniu odpowiedniego adresu do portu dotrze sygnał CS
wytworzony w dekoderze adresów. Sygnał ten, wraz z sygnałem WR, jest rozkazem dla portu
wyjściowego, aby wysterował zapisał do zatrzasku dane wystawione na szynę przez procesor. W ten
sposób po wystawieniu sygnału WR, mikrokontroler może zapisać dane do portu wyjściowego. Służy do
tego rozkaz MOVX. Literka X w nazwie rozkazu, dla odróżnienia od rozkazu MOV, oznacza, że chodzi
o zewnętrzną (eXternal) przestrzeń adresową danych. Rozkaz MOVX @DPTR,A zapisuje pod adres
zawarty w rejestrze DPTR bajt z akumulatora. Rejestr DPTR jest rejestrem 16-bitowym (jest to jedyny
rejestr 16-bitowy w mikrokontrolerze 8051 poza licznikiem rozkazów PC). W rzeczywistości są to dwa
rejestry 8-bitowe (DPL, DPH) umieszczone w obszarze rejestrów specjalnych SFR, które mikrokontroler
8051 potrafi użyć razem jako rejestr 16-bitowy. Przed rozkazem MOVX umieszczono w rejestrze DPTR
adres bufora, do którego należy przesłać dane. Dzięki temu rozkaz MOVX wystawia na szynę adresową
pełny adres potrzebnego bufora. Po uruchomieniu programu można zaobserwować, że świecą wskaźniki
wybrane stałą DISPLAY, natomiast segmenty wybrane stałą COD. Dokonując zmian w tych stałych
można decydować, które wskaźniki i które segmenty mają świecić.
78
W przykładzie w stałej DISPLAY umieszczono dwie jedynki, co powoduję że świecą dwa
wskaźniki - 1 i 4.
Po wpisaniu danych do buforów sterujących wyświetlaczem należy jeszcze wyzerować linię szóstą
w porcie Pl mikrokontrolera. Linia ta, ustawiona na l, blokuje tranzystor T18 i w rezultacie wyświetlanie
na całym wyświetlaczu 7-segmentowym. Jest ona doprowadzona do wyświetlacza po to, aby po
włączeniu zasilania nie była wyświetlana na wyświetlaczu przypadkowa zawartość buforów - port
mikrokontrolera jest automatycznie ustawiany na wartość l. Może ona też być wykorzystana przy
sekwencyjnej obsłudze wyświetlacza do jego wygaszania w czasie zmiany wyświetlanego wskaźnika.
4.8. Układ współpracy z klawiaturą
Ważnym elementem w systemie mikroprocesorowym jest zestaw klawiszy pozwalający użytkownikowi
na bezpośrednie wprowadzanie danych. Zwykle układ klawiszy ma formę klawiatury podłączanej do
systemu np. w sposób pokazany na poniższym rysunku. Obsługa klawiatury z rysunku 4.83 jest
wykonywana w sposób programowy, to znaczy sprawdzanie, czy został wciśnięty jakiś przycisk
oraz dekodowanie jego współrzędnych w matrycy (numeru wiersza i kolumny) odbywa się przy
użyciu algorytmu skanowania (przeglądania) klawiatury. W bardziej skomplikowanych zespołach
klawiatur alternatywnie stosuje się sygnalizację wciśnięcia przycisku przez linie przerwań oraz
sprzętowe dekodowanie wciśniętego przycisku.
SW9
SW1
R1
L0
SW2
SW10
SW3
SW11
R2
L1
R5
SW12
L3
SW5
R6
SW13
R7
L4
SW6
L0
L1
L2
L3
L4
L5
L6
L7
R4
L2
SW4
U9
R3
L5
8x10 k
SW7
SW15
+ 5V
SW16
D1
D2
D3
D4
D5
D6
D7
D8
Q1
Q2
Q3
Q4
Q5
Q6
Q7
Q8
18
17
16
15
14
13
12
11
D0
D1
D2
D3
D4
D5
D6
D7
D [0..7]
E1
E2
74541
RD
CSKB
L6
SW8
2
3
4
5
6
7
8
9
1
19
R8
SW14
L0
L1
L2
L3
L4
L5
L6
L7
3
4
1
L7
2
6
U8A
74125
5
U8B
74125
A1
A0
A [0..15]
Rysunek 4.83. Schemat układu klawiatury wyk. w urządzeniu dydaktycznym DSM-51
Odczytywanie danych z tych portów polega na podaniu przez mikrokontroler odpowiedniego adresu
na szynę adresową i sygnału RD (porty wejściowe umieszczone są w obszarze pamięci danych. Znaczy
to, że do odczytania potrzebny jest sygnał RD). Po podaniu odpowiedniego adresu do portu dotrze sygnał
CS wytworzony w dekoderze adresów. Sygnał ten, wraz z sygnałem RD, jest rozkazem dla portu
wejściowego, aby wysterował szynę danych zgodnie z danymi, które są na jego wejściu. W ten sposób po
wystawieniu sygnału RD, mikrokontroler może odczytać dane z portu wejściowego. Do
przeprowadzenia tej operacji służą, tak jak w przypadku portów wyjściowych, rozkazy MOVX. Można
oczywiście stosować zarówno adresowanie pełne, korzystając z rejestru DPTR, jak i adresowanie 8bitowe - rejestry R0 i Rl. W systemie DSM-51 najprostszym urządzeniem wejściowym jest klawiatura
matrycowa. Jest ona podłączona jako dwa porty wejściowe pod kolejnymi adresami: CSKBO i CSKB l.
Pod każdym z nich można odczytać stan ośmiu klawiszy. Wybór odczytywanego zestawu klawiszy
jest dokonywany liniami adresowymi A0 i A l (stan 0 na linii uaktywnia związany z nią zestaw kla-
79
wiszy). Jeśli port P2 zawiera starszą część adresu urządzeń wejść/wyjść, to do odczytania stanu
klawiatury można posłużyć się rozkazami podającymi na szynę tylko młodszą część adresu. Odczytanie
wartości spod adresu 21H (A l = O, AO = 1) daje stan pierwszego zestawu ośmiu klawiszy. Drugi zestaw
jest odczytywany spod adresu 22H (A l = l, AO = 0). Przyporządkowanie poszczególnych klawiszy
bitom danych odczytanych spod adresu 21H lub 22H jest przedstawione w tabeli.
Tablica 4.29. Porty wejściowe klawiatury matrycowej
Przykład przedstawia proste odwzorowanie stanu klawiszy [0],...[7] na wyświetlaczu 7-segmentowym.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
0096
0055
0021
0038
0000: 02 01 00
0100:
0100:
0100: 79 30
0102: 74 55
0104: F3
0105: 79 38
0107: 78 21
0109: C2 96
010B:
010B: E2
010C: F4
010D: F3
010E: 80 FB
SEG_ON EQU
P1.6
;włączenie wyświetlacza 7-segmentowego
;Stałe używane w programie
DISPLAY EQU 01010101B
;wskaźniki - 1,3,5,7
CSKB0 EQU 021H
;bufor wyboru wskaźnika
CSDB
EQU 038H
;bufor danych wskaźnika
LJMP START
ORG
100H
;przesunięcie kodu instrukcji do adresu 100H
START:
;pusta linia w programie źrdłowym
MOV R1,#CSDS
;adres wyboru wskaźnika
MOV A,#DISPLAY
MOVX @R1,A
;wpisz wybrane wskaźniki
MOV R1,#CSDB
;adres danych wskaźnika
MOV R0,#CSKB0
;adres klawiszy 0..7
CLR
SEG_ON
;włącz wyświetlacz 7-segm
LOOP:
;przepisuj stan klawiszy na wyświetlacz 7-segm.
MOVX A,@R0
;odczytanie klawiszy, bit = 0 – klawisz naciśnięty
CPL
A
;zmiana 0<->1
MOVX @R1,A
;włączenie segm. odpowiadających wciśniętym klawiszom
SJMP LOOP
Stan na wyświetlaczu jest wyświetlany statycznie, jednocześnie na kilku wskaźnikach. O tym, na
których, decyduje stała DISPLAY. W przykładzie można odczytać naraz stan ośmiu klawiszy.
Wybierając adres CSKBO wczytywany jest stan klawiszy
- klawiszowi [0] odpowiada bit 0 w odczytanym bajcie,
- klawiszowi [1] odpowiada bit l itd.
Jeżeli klawisz jest zwolniony, to odpowiada mu bit o wartości - l, jeśli jest naciśnięty, bit = 0. Negując
ten bajt i wysyłając go na wyświetlacz 7-segmentowy otrzymano zależność świecenia segmentu o
numerze odpowiadającym numerowi naciśniętego klawisza. Oznacza to, że:
- klawiszowi [0] odpowiada segment a,
- klawiszowi [1] odpowiada segment b itd.
80
Na rysunku poniżej pokazano inne rozwiązanie układu klawiatury matrycowej, wykorzystujące układ
8255.
Rysunek 4.84. Uproszczony schemat połączenia klawiatury matrycowej 7 x 4 z mikrokontrolerem x51
przez programowalny układ PIO
Przed rozpoczęciem skanowania klawiatury należy, odpowiednio skonfigurować układ 8255, to
znaczy zdefiniować odpowiednie kierunki transmisji w portach. Następnie dekodowanie stanu
klawiatury przebiega według następującego schematu:
- Mikrokontroler ustawia stan "0" na linii kolumny numer 0, sterowanej z wyjścia PBO
układu 8255.
- Program odczytuje port PCL i sprawdza, czy na jednym z wejść jest stan "0". Jeśli tak jest,
to wykryto wciśnięcie przycisku na skrzyżowaniu kolumny 0 i wiersza, na którym
odczytane zostało "0".
- Mikrokontroler generuje stan "0" na kolejnej linii kolumn i wykonuje sprawdzenie stanu
linii wierszy. Procedura powtarza się, aż sprawdzona zostanie cała klawiatura albo nastąpi
wykrycie stanu wciśnięcia jakiegokolwiek przycisku.
- Po zdekodowaniu klawiatury program przystępuje do obsługi przez wywołanie procedury
przypisanej do danego klawisza.
4.9. Układ współpracy z wyświetlaczem LCD
Ważnym elementem w systemie mikroprocesorowym jest wyświetlacz LCD pozwalający
użytkownikowi na wizualizację komunikatów pochodzących z urządzenia. W wyświetlaczach LCD tych
każdy znak zdefiniowany jest na polu 5x7 punktów, co pozwala na wyświetlanie dowolnych znaków
(cyfr, liter) w pełni zrozumiałych dla człowieka.
Ze względu na znacznie większą ilość danych niż w wyświetlaczu 7-segmentowym oraz na bardziej
złożone sterowanie, wyświetlacze LCD są standardowo wyposażone w specjalizowane procesory, które
zarządzają wyświetlaniem. Takie procesory nazywane są sterownikami wyświetlacza. Typowym ich
przedstawicielem jest układ firmy Hitachi HD 44780. Do takiego sterownika mikrokontroler wysyła
tylko dane (które mają być wyświetlane) i instrukcje (w jaki sposób mają być wyświetlane). Natomiast
sposób zamiany danych na punkty, które mają świecić, czy przebiegi sterujące wyświetlaniem, to już
zadanie sterownika.
81
+ 5V
D [0..7]
R1
10 k
+ 5V
R2
470
U10
2
3
1
KONTRAST
A0
A1
4
5
6
VCC
VO
GND
RS
R/W
E
D0
D1
D2
D3
D4
D5
D6
D7
17
16
15
10
11
12
13
14
D0
D1
D2
D3
D4
D5
D6
D7
LM16A21
A [0..15]
LCD
Rysunek 4.85. układ sterownika wyświetlacza LCD
Z tego względu wyświetlacz LCD (naprawdę układ interfejsu sterownika HD44780) zajmuje w
przestrzeni adresowej cztery kolejne komórki pamięci. W urządzeniu DSM-51 wykorzystywanym w
laboratorium, są to adresy począwszy od 80H (FF80H). Każdy z tych adresów pełni specyficzną rolę:
- 80H - zapis instrukcji,
- 81H - zapis danych,
- 82H - odczyt stanu,
- 83H - odczyt danych.
Po wysłaniu do sterownika wyświetlacza LCD kolejnej instrukcji bądź kolejnych danych, sterownik musi
wykonać otrzymane polecenie, tzn. wykonać instrukcję bądź umieścić dane pod odpowiednim adresem.
Na wykonanie tych operacji sterownik potrzebuje określonego czasu. W tym czasie sterownik jest zajęty
i nie przyjmuje kolejnych poleceń. Jedynym wyjątkiem jest możliwość odczytania stanu.
Przed wydaniem kolejnego polecenia należy sprawdzić, czy sterownik jest gotów do jego przyjęcia. Jest
to możliwe przez odczytanie stanu wyświetlacza, czyli odczyt spod adresu 82H. Siódmy bit stanu jest to
flaga Busy (flaga zajętości). Jeżeli flaga ta jest równa l, to sterownik jest zajęty i będzie głuchy na nasze
polecenia. Jeżeli flaga Busy równa się 0, to można wysłać do sterownika kolejne polecenie.
Sterownik wyświetlacza ma wyprowadzone następujące sygnały sterujące:
Tablica 4.30. Sygnały sterujące wyświetlacza LCD
W zależności od ich stanu można dokonywać wpisu lub odczytywania danych zgodnie z poniższą tabelą.
Tablica 4.31. Dozwolone stany sygnałów sterujących
82
Do sterownika można wysłać wiele różnych rozkazów pokazanych w poniższej tabeli wpisując je
pod adres rejestru sterującego.
Tablica 4.32. Rozkazy dla sterownika LCD
Pamięć sterownika składa się z dwu części pozwalających na:
- pamiętanie znaków pokazywanych na wyświetlaczu – obszar DD_RAM
Tablica 4.33.
Pozycja
Linia 1
Linia 2
-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
00 01 02 03 04 05 06 07 08 0A 0B 0C 0D 0E 0F 10
40 41 42 43 44 45 46 47 48 4A 4B 4C 4D 4E 4F 50
pamiętanie definicji kroju graficznego znaków wyświetlacza – obszar CG_RAM.
Na każdy znak przeznaczonych jest 8 bajtów w pamięci CG_RAM odpowiednio 0H...7H, 8H...0FH,
...38H...3FH. Przykładowo pamięć znaku M wygląda następująco:
83
Rysunek 4.86. Definicja kroju graficznego znaków wyświetlacza
Definicje znaków w obszarze pamięci CG_RAM sterownika przedstawiono poniżej w postaci
tabeli.
Tablica 4.34. Definicje znaków pamięci CG_RAM sterownika wyświetlacza LCD
84
Przykład l ilustruje sposób wprowadzania kolejnych danych na wyświetlacz.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0080
0081
0082
LCDWC EQU
LCDWDEQU
LCDRC EQU
0000: 02 01 00
0100:
0100:
0100: 79 82
0102: 78 80
0104: 74 01
0106: F2
0107:
0107: E3
0108: 20 E7 FC
80H
81H
82H
LJMP START
ORG 100H
;adres wpisywania rozkazów do wyświetlacza LCD
;adres wpisywania danych do wyświetlacza LCD
;adres odczytu stanu wyświetlacza LCD
;pusta linia w programie źrdłowym
;przesunięcie kodu instrukcji do adresu 100H
;pusta linia w programie źrdłowym
START:
MOV
MOV
MOV
MOVX
R1,#LCDRC
R0,#LCDWC
A,#1
@R0,A
;adres odczytu stanu wyświetlacza LCD
;adres wpisywania danych do wyświetlacza LCD
;rozkaz CLR dla wyświetlacza LCD
;wpis rozkazu CLR do wyświetlacza LCD
BUSY:
MOVX A,@R1
JB
ACC.7,BUSY
85
;odczyt stanu wyświetlacza
;oczekiwanie na bit BUSY=0
16
17
18
19
20
010B: 78 81
010D: 74 4B
010F: F2
0110: 80 FE
MOV
MOV
MOVX
SJMP
R0,#LCDWD
A,#4BH
@R0,A
$
;adres wpisywania danych do wyświetlacza LCD
;kod znaku “K”
;wpis kodu znaku do wyświetlacza LCD
Jako pierwszy do wyświetlacza (pod adres rejestru sterującego LCDWC=FF80H) zostaje wysłany
rozkaz CLR, który kasuje wszystkie znaki pokazywane na wyświetlaczu. Przed wysłaniem kolejnej danej
procesor sprawdza, czy sterownik wyświetlacza wykonał poprzednią instrukcję. Sprawdzenie jest
wykonywane w pętli BUSY. W pętli tej procesor czyta stan wyświetlacza (z adresu rejestru stanu
LCDRC=FF82H), aż do momentu, kiedy bit nr 7 w odczytywanej danej, czyli flaga zajętości (BUSY)
będzie równa 0. Wtedy wysyłany jest następny znak. Ale tym razem pod adres rejestru danych
LCDWD=FF80H. Po wprowadzeniu 16-tu znaków kursor znika z wyświetlacza i kolejne znaki pozornie
nie są wpisywane na wyświetlacz. Jednak gdy wprowadzonych zostanie ponad 40 znaków, kursor
ponownie pojawia się na wyświetlaczu - tym razem w dolnej linii. Takie zachowanie wynika z tego, że
wyświetlacz LCD wyposażony jest w uniwersalny sterownik LCD. Jego uniwersalność polega na tym, że
bez względu na to, jakim wyświetlaczem steruje (2 linie po 16 znaków, 2x20, 2x40, l x80), jest to
zawsze ten sam sterownik, który pamięta 80 znaków (l linia x 80 znaków bądź 2 linie x 40 znaków). Tak
więc wysłane na wyświetlacz znaki nie zginęły, a jedynie nie można było ich wszystkich naraz
wyświetlić.
4.10. Przetworniki analogowo-cyfrowe
Przetworniki analogowo-cyfrowe stosowane w układach mikroprocesorowych wykorzystują najczęściej
kilka spośród wielu znanych metod przetwarzania napięcia na odpowiadającą mu miarę liczbową:
- metodę sukcesywnej aproksymacji SAR (ang. successive approximation),
- metodę jednozboczowego ładowania pojemności SS (ang. single-slope A/D),
- metodę nadpróbkowania (ang. oversampling).
Częściej stosowana jest metoda SAR, która nie wymaga dołączania do mikrokontrolera zewnętrznych
elementów dyskretnych i jest łatwiejsza przy programowaniu obsługi przetwornika. Zaletą metody SAR
jest ponadto stosunkowo krótki czas konwersji, równy zwykle od 10 do 16 cykli zegara w przypadku
konwerterów 8-bitowych.
(Czas konwersji to czas upływający pomiędzy momentem podania na wejściu przetwornika
sygnału inicjującego konwersję a momentem ustalenia się na wyjściu przetwornika wyniku
liczbowego konwersji). Realizacja przetworników SAR o większej rozdzielczości napotyka jednak
trudności, dlatego (praktyce rozdzielczość przetworników SAR wbudowywanych do mikrokontrolerów
nie przekracza 10 bitów a zewnętrznych 16 bitów. Metoda SS wymaga z kolei stosowania dołączanego z
zewnątrz kondensatora, co jest jej oczywistą wadą. Zapewnia jednak stosunkowo prostą realizację
przetworników o większej rozdzielczości, na przykład 12- lub nawet 16-bitowej. Czas przetwarzania jest
jednak dłuższy niż w przypadku metody SAR. Przetworniki z nadpróbkowaniem (sigma-delta) są
urządzeniami mającymi największą rozdzielczość wynoszącą nawet 24bity, przy czym ich czas
przetwarzania nie jest zwykle mniejszy niż kilka mikrosekund.
W celu zwiększenia liczby wejściowych kanałów analogowych bardzo często przetworniki współpracują
z układami multiplekserów lub kluczy analogowych. W celu zwiększenia dokładności konwersji, wejścia
analogowe wykorzystują układy próbkująco-pamiętające (ang. sample&hold – S/H).
Realizacja przetworników A/C na przykładzie metody równoległej
Na rysunku 4.87 pokazano realizację przetwornika równoległego dla liczb trzybitowych. Liczba
trzybitowa umożliwia reprezentację ośmiu różnych liczb z zerem włącznie. Przetwornik wymaga wiec
zastosowania siedmiu komparatorów.
86
Rysunek 4.87. Równoległy przetwornik A/C
Siedem różniących się o stałą wartość napięć odniesienia wytwarza się za pomocą dzielnika
napięcia. Jeżeli podamy napięcie wejściowe mieszczące się przykładowo w zakresie 5/2...7/2 ULSB,
to na wyjściu komparatorów l ...3 otrzymamy l, a na wyjściu komparatorów 4... 7 - 0. Potrzebny jest
teraz układ logiczny, który przetworzy te stany komparatorów na liczbę 3. Na rysunku 4.88
przedstawiliśmy związek miedzy stanami komparatorów a odpowiadającymi im liczbami
dwójkowymi. Przekształcenie to można zrealizować za pomocą dekodera priorytetowego.
Rysunek 4.88. Stany zmiennych w równoległym przetworniku A/C w zależności od napięcia
wejściowego
Dekodera priorytetowego nie można jednak dołączyć bezpośrednio do wyjść komparatorów. Jeżeli
bowiem napięcie wejściowe nie jest stałe, to w kodzie dwójkowym mogą przejściowo wystąpić
błędne wartości liczb. Weźmy dla przykładu przejście z trzech na cztery, czyli w kodzie
dwójkowym z 011 na 100. Jeżeli z powodu krótszych czasów propagacji najwyższa pozycja zmieni
się wcześniej od pozostałych dwu, to przejściowo pojawi się liczba 111, czyli 7. Odpowiada to
87
błędowi równemu połowie zakresu pomiarowego. Ponieważ wynik przetwarzania A/C jest z reguły
przechowywany w pamięci, istnieje pewne prawdopodobieństwo zapamiętania tej całkowicie
błędnej wartości. Pomocą może tu być np. zapobieganie zmianom napięcia wejściowego w czasie
pomiaru za pomocą układu próbkująco-pamiętającego (S/H). Wpływa to jednak na osiągalną
częstotliwość napięcia wejściowego, ponieważ układ próbkująco-pamiętający wymaga określonego
czasu akwizycji. Poza tym nie gwarantuje to, że stany wyjść komparatorów nie ulegną zmianie,
ponieważ szybkie układy próbkująco-pamiętające mają duży dryft. Problemów tych można jednak
uniknąć, jeśli zamiast wartości analogowej (przed komparatorami), zapamięta się wartość cyfrową
(za komparatorami). Do tego celu służą przerzutniki D wyzwalane zboczem za każdym
komparatorem na rys. 4.87. Dzięki nim, przez cały okres przebiegu taktującego dekoder
priorytetowy otrzymuje ustalony sygnał wejściowy. Opisana wyżej możliwość zastosowania
cyfrowego układu próbkująco-pamiętającego jest zaletą metody równoległej, decydującą o dużej
szybkości przetwarzania A/C. Dla częstotliwości powyżej kilku MHz bowiem, nawet przy dużym
nakładzie środków, nie można zrealizować analogowych układów próbkująco-pamiętających o
wymaganej dokładności.
4.10.1. Konwersja analogowo-cyfrowa – przetwornik SAR
Przetwornik SAR składa się z układu próbkująco-pamiętającego (ang. sample&hold – S/H),
komparatora, rejestru aproksymacyjnego i układu sterowania realizującego algorytm SAR (rysunek
4.88). W rzeczywistych układach stosuje się zazwyczaj kilka (ba nawet kilkanaście) kanałów
przetwarzania A/C, multiplekser kanałów, źródło napięcia odniesienia i niekiedy oddzielny układ
zasilania części analogowej w celu wyeliminowania zakłóceń.
Rysunek 4.88. Uproszczony schematprzetwornika A/C pracującego na zasadziesukcesywnej
aproksymacji
Cykl konwersji w układzie SAR zaczyna się od pobrania próbki mierzonego napięcia wejściowego i
zapamiętania jej w pojemności C. Rejestr aproksymacyjny jest zazwyczaj inicjowany w taki sposób, że
ma ustawiony najbardziej znaczący bit, a pozostałe bity wyzerowane.
Zawartość rejestru reprezentuje zatem napięcie równe połowie maksymalnego napięcia (zakresu
pomiarowego). Wartość ta jest zamieniana przez przetwornik C/A na napięcie i porównywana z
napięciem mierzonym. W zależności od wyniku równania układ sterowania pozostawia najbardziej
znaczący bit rejestru niezmieniony albo go neguje. Pierwszy przypadek ma miejsce wtedy, gdy napięcie
mierzone jest większe od połowy napięcia maksymalnego, drugi natomiast - gdy jest mniejsze. Po
określeniu wartości najbardziej znaczącego bitu rejestru aproksymacyjnego układ SAR ustawia w
rejestrze kolejny bit i powtarza opisaną wyżej procedurę.
88
Przy n-bitowym rejestrze aproksymacyjnym, układ określa jego ostateczną zawartość po n cyklach
zegara (lub 2n cyklach zegara, jeśli jeden cykl aproksymacji jest wykonywany w czasie dwóch cykli
zegara).
Opisana metoda jest niekiedy określana w literaturze jako poszukiwanie dwudzielne lub binarne (ang.
binary search).
Ograniczenie dokładności konwersji napięcia wynika przede wszystkim z błędów wnoszonych przez
analogową pętlę sprzężenia zwrotnego.
Tablica 4.35. Przykłady układów przetworników analogowo-cyfrowych typu SAR
4.10.2. Konwersja analogowo-cyfrowa – przetwornik SS
Rysunek 4.89. Budowa przetwornika A/C opartego na zasadzie jednozboczowego ładowania zewnętrznej
pojemności
Początkowa część toru przetwornika SS ma podobną budowę jak w przetworniku SAR - zawiera układ
próbkująco-pamiętający i komparator (rysunek 4.89). Dodatkowo stosuje się zewnętrzną pojemność C
ładowaną przez źródło prądowe. Cykl pomiaru napięcia wejściowego zaczyna się od rozładowania
pojemności C1 przez zwarcie jej do masy. Jednocześnie układ próbkująco-pamiętający pobiera próbkę
mierzonego napięcia i zapamiętuje ją w pojemności C (w prostych układach nie stosuje się układu
sample&hold i napięcie mierzone jest ciągle podawane na wejście komparatora).
89
Różnica tych zawartości jest miarą czasu ładowania pojemności C1 i pozwala łatwo obliczyć napięcie
wejściowe, jeśli tylko znana jest wielkość prądu I oraz okres zegara wzorcowego. Uzyskanie dużej
rozdzielczości pomiaru wymaga stosowania małego prądu I, czyli długiego czasu ładowania.
Właściwa konwersja zaczyna się w chwili włączenia źródła prądowego, które ładuje pojemność C1. W
tym momencie licznik zaczyna zliczać impulsy generatora wzorcowego. Rosnące napięcie na
pojemności C1, jest porównywane z mierzonym napięciem przez komparator, a po zrównaniu się z nim
następuje zatrzymanie licznika.
W praktyce realizacja układu jest nieco inna, mianowicie licznik pracuje bez przerwy, natomiast jego
zawartość jest odczytywana w chwili startu ładowania pojemności i w chwili zrównania się napięć na
wejściu komparatora.
Z tego względu czas przetwarzania w metodzie SS jest w związku z tym długi (rzędu milisekund),
podczas gdy przetworniki SAR wykonują przetwarzanie w czasie rzędu mikrosekund.
Mimo długiego czasu konwersji przetworniki SS są stosowane, jeśli potrzebna jest duża rozdzielczość
pomiaru. Przetwornik tego typu jest wbudowany na przykład w mikrokontrolerze 68HC705JP7
(Motorola) i zapewnia rozdzielczość 12-bitową.
4.10.3. Konwersja analogowo-cyfrowa – przetwornik SigmaDelta (Σ
Σ∆)
Jedną z podstawowych zalet techniki sigma-delta jest to, że może ona wykorzystywać filtrację
cyfrową, a około 90% obszaru struktury półprzewodnikowej obwodu scalonego jest czysto cyfrowe.
Dzięki temu dostępne są teraz przetworniki sigma-delta o dużej rozdzielczości (np. 24 bitowe),
dobrych charakterystykach szumowych i cenie porównywalnej z innymi typami przetworników.
Przetworniki sigma-delta charakteryzują się wszystkimi tymi zaletami, które wynikają ze
stosowania technik cyfrowych, czyli dużej niezawodności, lepszej stabilności i wyższej
funkcjonalności. Ponadto, ze względu na wykorzystywanie podczas konwersji sigma-delta głównie
technik cyfrowych, możliwe jest zintegrowanie tego przetwornika z urządzeniem DSP na tej samej
strukturze półprzewodnikowej. Zmniejsza to liczbę niezbędnych obwodów scalonych systemu
redukując koszt, a co najważniejsze poprawia niezawodność systemu. Przetworniki SAR oraz z
całkowaniem wykorzystują identyczną zasadę próbkowania - częstotliwość próbkowania znajduje
się w pobliżu granicy Nyquista, co wymaga stosowania dobrego filtru antyaliasingowego (filtru
dolnoprzepustowego ograniczającego częstotliwość maksymalną sygnału podawanego na
przetwornik A/C, pozwalającego na spełnienie warunku: (Fpr > 2fmax sygnału)). Dobre parametry tych
przetworników osiągane są dzięki dobieraniu podzespołów i procesowi wyrównywania laserowego.
Natomiast przetwornik A/C typu sigma-delta wykorzystuje konwersję o niskiej rozdzielczości
(kwantyzator jednobitowy), lecz stosowana w nim szybkość próbkowania wielokrotnie przewyższa
częstotliwość Nyquista. Po procesie próbkowania, już w dziedzinie cyfrowej, następuje zgęszczenie
informacji (decymacja), co prowadzi do obniżenia częstotliwości wyjściowej i wzrostu dokładności.
Rysunek 4.90. Próbkowanie z częstotliwością czterokrotnie przewyższającą granicę Nyquista
Załóżmy próbkowanie przebiegu wejściowego z częstotliwością czterokrotnie przewyższająca
granicę Nyquista (Fpr=FS > 2fmax sygnału) i zbadajmy rezultat tej czynności (rysunek 4.90).
90
Z rysunku wynika, że wymagania na filtr antyaliasingowy znacznie się uprościły. Odnośny obszar,
w którym wymagana jest płaska odpowiedź impulsowa jest węższy, a nachylenie charakterystyki
filtru może być bardziej łagodne. W związku z tym sam filtr staje się o wiele łatwiejszy do
zaprojektowania.
Rysunek 4.91. Redukcja mocy szumów podczas nadpróbkowania
Próbkowanie przy wyższej częstotliwości, nazywane nadpróbkowaniem, ma jeszcze jedną istotną
zaletę. Podczas procesu kwantyzacji wynikająca z niego moc szumu rozkłada się równomiernie na
całe widmo.
Zatem stosując przetworniki A/C sigma-delta otrzymujemy taką samą całkowitą moc szumu, która
jest jednak rozłożona w szerszym paśmie częstotliwościowym. Dzięki temu moc szumu z
interesującego nas zakresu, mającego wpływ na szum końcowy (od -fm do + fm), jest niższa, co
pokazano na rysunku 4.91.
Stosowana w przetwornikach A/C jednobitowa kwantyzacja sigma-delta wykorzystuje
rozwinięcie metody znanej już w technice i nazywanej modulacją delta. Modulacja ta opiera się
o kwantyzację różnicy między wartościami kolejnych próbek, a nie wartości absolutnej próbki
sygnału wejściowego (rysunek 4.92).
91
Modulacja
Demodulacja
Rysunek 4.92. Modulacja/demodulacja typu delta
Modulacja sigma-delta osiągnięta jest przez przesuniecie drugiego układu całkującego z
demodulatora do stopnia wejściowego modulatora (rysunek 4.93).
Modulator
Demodulator
Rysunek 4.93. Zmodyfikowana modulacje/demodulacja typu delta
Całkowanie jest funkcją liniową i może być wykonane bez naruszenia prawidłowego
funkcjonowania systemu. Co więcej, dwa układy całkujące mogą być połączone w jeden zgodnie z
rysunkiem 4.94.
92
Modulator
Demodulator
Rysunek 4.94. Modulacja sigma-delta w połączeniu z całkowaniem
Nazwa sigma-delta pochodzi od węzła sumującego (sigma) po którym umieszczony jest
modulator delta (całkowanie i jednobitowy kwantyzator). Właściwości szumowe takiego kodera
zależą od częstotliwości. Sprzężenie zwrotne pełni tu rolę filtru dolnoprzepustowego dla sygnału
wejściowego oraz filtru górno przepustowego dla szumów wprowadzanych przez kwantyzator. Ta
właściwość kształtowania szumów dobrze nadaje się do cyfrowych zastosowań audio. Schemat
blokowy przetwornika A/C sigma-delta pokazano na rysunku 4.95.
Rysunek 4.95. Przetwornik A/C typu sigma-delta
Jednobitowe dane przesyłane są do filtru decymacyjnego (układu redukcji przepływu informacji),
który uśrednia wartości w dziedzinie cyfrowej oraz wytwarza wyjście n-bitowe o niższej
częstotliwości (rysunek 4.96).
Rysunek 4.96. Zasada działania cyfrowego filtru decymacyjnego
93
Tablica 4.36. Przykłady układów przetworników analogowo-cyfrowych typu Σ∆
4.10.4. Błędy konwersji w przetwornikach A/C
Błędy statyczne
Przy przetwarzaniu wielkości analogowej na liczbę o skończonej liczbie bitów ze względu na
ograniczoną rozdzielczość powstaje błąd systematyczny, który nosi nazwę błędu kwantyzacji
(rozdzielczości). Zgodnie z rys. 4.97 wynosi on ± ULSB/2 tzn. jest równy połowie zmiany napięcia
wejściowego, która wywołuje zmianę najniższej pozycji liczby. Jeżeli otrzymany ciąg liczb
przetworzymy za pomocą przetwornika C/A z powrotem na napięcie, błąd kwantyzacji ujawni się w
postaci szumu, którego wartość skuteczna wynosi:
Przy pełnym wysterowaniu przebiegiem sinusoidalnym w przypadku N-bitowego przetwornika wartość
skuteczna napięcia sygnału:
Otrzymujemy stąd stosunek sygnału do szumu:
Oprócz systematycznego błędu kwantyzacji występują większe lub mniejsze błędy pochodzenia
układowego. Jeżeli w idealnej charakterystyce przetwarzania na rys. 4.98 połączymy środki schodków, to
otrzymamy prostą o nachyleniu l , przechodzącą przez początek układów współrzędnych. W
rzeczywistym przetworniku A/C prosta ta nie przechodzi przez 0 (błąd zera), a jej nachylenie odbiega od
jedności (błąd wzmocnienia).
94
Błąd wzmocnienia wywołuje stałą dla zakresu wysterowania odchyłkę względną wielkości wyjściowej
od wartości zadanej, natomiast błąd zera - stałą odchyłkę bezwzględną.
Rysunek 4.97. Powstanie szumu
kwantyzacji.Napiecie Uwr(L) otrzymuje się z
przetworzenia C/A liczby L występującej na wyjściu
przetwornika A/C
Rysunek 4.98. Charakterystyka przetwarzania
przetwornika A/C z błędem liniowości
Oba te błędy można z reguły skorygować przez regulację zera i wartości odpowiadającej pełnemu
zakresowi. Pozostają wtedy tylko odchyłki wywołane niestałością (dryftem) i nieliniowością.
Nieliniowość wykraczająca poza systematyczny błąd kwantyzacji powstaje zawsze wówczas, gdy
schodki nie są jednakowo szerokie. W celu określenia błędu liniowości należy najpierw dokonać regulacji
zera oraz wzmocnienia i określić maksymalną odchyłkę napięcia wejściowego od idealnej prostej.
Wartość ta, po odjęciu systematycznego błędu kwantyzacji f/LSB/2, stanowi całkowity błąd liniowości.
Podaje się go zazwyczaj w postaci ułamka jednostki podstawowej równej najmniej znaczącemu bitowi.
W przykładzie z rys. 4.97 wynosi on ± ULSB/2. Inną miarą liniowości jest różniczkowy błąd liniowości.
Mówi on, o ile szerokość poszczególnych schodków różni się od wartości zadanej 1LSB. Jeżeli błąd
ten jest większy od LSB, to występuje „przeskakiwanie" niektórych cyfr (ang. missing code). Przy
jeszcze większych odchyłkach liczba L może nawet maleć przy wzroście napięcia wejściowego (błąd
monotoniczności).
Błędy dynamiczne
Można wyróżnić dwie dziedziny zastosowań przetworników A/C: jedną z nich są woltomierze
cyfrowe, a drugą - przetwarzanie sygnałów. W woltomierzach cyfrowych zakłada się, że w czasie
przetwarzania napięcie wejściowe ma wartość stałą, natomiast przy przetwarzaniu sygnału napięcie
wejściowe stale się zmienia. Z tego napięcia zmiennego, w celu poddania go obróbce cyfrowej,
pobiera się w równych odstępach czasu próbki za pomocą układu próbkująco-pamiętającego.
Przetwornik A/C przetwarza te próbki na liczby. Powstający ciąg liczb {L} reprezentuje ciągły sygnał
wejściowy bez utraty informacji tylko wówczas, gdy jest spełnione twierdzenie o próbkowaniu.
Zgodnie z tym częstotliwość próbkowania fp musi być wiec co najmniej dwa razy większa od
maksymalnej częstotliwości sygnału fmax. Wynika stąd wymaganie, by czas przetwarzania
przetwornika A/C i czas akwizycji układu próbkująco-pamiętającego były razem mniejsze niż
l/(2fmax). Aby móc zrealizować to wymaganie przy założonym nakładzie kosztów, ogranicza się
szerokość pasma sygnału do koniecznej wartości. W tym celu na wejście włącza się najczęściej filtr
dolnoprzepustowy. Do oceny dokładności należy rozważać wspólnie właściwości przetwornika
A/C i układu próbkująco-pamiętającego. Nie ma np. sensu współpraca dwunastobitowego
przetwornika A/C z układem próbkująco-pamiętającym, który w będącym do dyspozycji czasie
nie osiąga wartości ustalonej z dokładnością do 1/4096 « 0,025% zakresu wysterowania.
95
Inny błąd dynamiczny jest spowodowany niepewnością chwili pobrania próbki (niestałością
apertury). Czas opóźnienia apertury td układu próbkująco-pamiętającego powoduje pobranie próbki z
opóźnieniem. Gdy czas opóźnienia apertury jest stały, każda próbka jest opóźniona o ten sam czas.
Dzięki temu jest zapewnione próbkowanie w równych odstępach czasu. Jeżeli jednak czas opóźnienia
-jak na rys. 4.99 - zmienia się o wartość niestałości (drżenie) apertury ∆fd, to powstaje błąd pomiaru,
który jest równy zmianie napięcia ∆U.
Rysunek 4.99. Wpływ niestałości (drżenia) apertury
W celu obliczenia maksymalnego błędu ∆U załóżmy, że sygnał wejściowy jest przebiegiem
sinusoidalnym o maksymalnej przewidzianej częstotliwości fmax. Największe nachylenie występuje
przy przejściu przez zero
Otrzymujemy stąd błąd amplitudy:
Jeżeli ma on być mniejszy od jednostki podstawowej ULSB przetwornika A/C, to otrzymuje się warunek na
niestałość apertury
Przy wielkich częstotliwościach sygnału warunek ten jest bardzo trudno spełnić, jak to widać na
następującym przykładzie liczbowym:
Dla przetwornika ośmiobitowego ULSB/Umax = 1/255. Jeżeli maksymalna częstotliwość
sygnału wynosi 10 MHz, to niestałość apertury powinna być mniejsza niż 125 ps.
4.11. Układy próbkująco-pamiętające (S/H)
Ważną grupą układów współpracujących z przetwornikami analogowo-cyfrowymi są układy próbkującopamiętające (ang. sample&hold – S/H).
Podstawowe pojęcia
Napięcie wyjściowe układu próbkująco-pamiętającego (ang. sample&hold circuit) w stanie włączenia
powinno śledzić napięcie wejściowe. W tym stanie układ ten zachowuje się więc jak przełącznik
analogowy. W stanie wyłączenia napięcie wyjściowe nie powinno jednak spaść do zera, lecz powinno być
równe napięciu w chwili wyłączania. Ze względu na te właściwości układy próbkująco-pamiętające noszą
również nazwę układów śledząco-pamiętających (ang. track&hold circuits).
96
Rysunek 4.100. Podstawowy układ próbkująco-pamiętający
Zasadniczy schemat układu próbkująco-pamiętającego jest przedstawiony na rys. 4.100. Głównym
elementem układu jest kondensator pamiętający C. Gdy klucz K jest zamknięty, wówczas kondensator jest
ładowany do napięcia wejściowego. Aby nie powodowało to obciążenia źródła napięcia wejściowego,
stosuje się układ dopasowujący impedancję. Na rysunku 4.100 zrealizowano go za pomocą wtórnika
napięciowego WO1. Musi on dostarczać dużych prądów wyjściowych, umożliwiających szybkie
przeładowanie kondensatora pamiętającego. Jeżeli klucz K jest otwarty, to napięcie na kondensatorze C
powinno jak najdłużej pozostać bez zmian. Dlatego za kondensatorem jest włączony wtórnik napięciowy
separujący obciążenie. Oprócz tego przełącznik musi mieć dużą rezystancję w stanie wyłączenia, a
kondensator - izolację wysokiej jakości. Porównanie zmian napięcia na kondensatorze w idealnym układzie
i w rzeczywistym ukł. próbkująco-pamiętającym przedstawiono na rys. 4.101.
Rysunek 4.101. Definicje parametrów układu próbkująco-pamiętającego. Przykładowo podano dane
typowe układu LF 398 z kondensatorem pamiętającym 1nF. Czas trwania fazy śledzenia musi być co
najmniej równy czasowi akwizycji
Po zamknięciu klucza K napięcie wyjściowe nie osiąga natychmiast wartości napięcia wejściowego, lecz
narasta z szybkością określoną przez maksymalną szybkość zmian sygnału na wyjściu (ang. slew rate).
Ogranicza ją przede wszystkim maksymalny prąd wejściowego wtórnika napięciowego.
Potem następuje stan nieustalony, którego czas trwania zależy od tłumienia wprowadzanego przez wtórnik i
od rezystancji klucza w stanie włączenia.
Jako czas akwizycji tA (ang. acąuisition time) definiuje się czas, który upływa od chwili pojawienia się
sygnału zamykającego klucz do chwili, kiedy napięcie wyjściowe osiągnie wartość równą napięciu
wejściowemu z zadaną dokładnością. Jeżeli stopień naładowania kondensatora pamiętającego zależy
wyłącznie od rezystancji klucza w stanie włączenia RON, to czas aktywacji można obliczyć na podstawie
przebiegu ładowania układu RC i wymaganej dokładności ustalania.
Otrzymuje się wtedy:
Na początku fazy pamiętania od chwili pojawienia się sygnału otwierającego klucz do chwili jego otwarcia
upływa pewien czas. Czas ten nosi nazwę czasu opóźnienia apertury td (ang. aperture delay). Przeważnie
97
nie ma on stałej wartości, lecz ulega wahaniom, często zależnym od wartości napięcia wejściowego.
Wahania te noszą nazwę niestałości (drżenia) apertury atd (ang. aperture jitter).
Po upływie tego czasu napięcie wyjściowe najczęściej nie ma jeszcze stałej, zapamiętanej wartości, lecz
następuje niewielki skok napięcia zwany piedestałem (ang. hold step), z następującym po nim stanem
nieustalonym. Bierze się on stąd, że przy wyłączaniu pewien niewielki ładunek jest przekazywany przez
pojemność klucza CK z obwodu sygnału sterującego do kondensatora pamiętającego C. Występujący przy
tym skok napięcia wynosi
gdzie ∆Us jest amplitudą sygnału sterującego. Zakłócenie to jest więc tym mniejsze, im większą
wybierzemy wartość C.
Kolejnym parametrem układu jest przenik (ang. feedthrough). Wynika on stąd, że mimo otwartego
klucza napięcie wejściowe oddziałuje na wyjście. Zjawisko to jest wywołane głównie przez pojemnościowy
dzielnik napięcia, utworzony z pojemności otwartego klucza i kondensatora pamiętającego.
Najważniejszym parametrem w stanie pamiętania jest spadek napięcia na kondensatorze pamiętającym,
zwany zwisem (ang. droop). Zależy on głównie od prądu wejściowego wtórnika wyjściowego oraz prądu
upływu klucza.
Przy prądzie rozładowania IL otrzymuje się:
W celu minimalizacji prądu rozładowania, jako WO2 stosuje się wzmacniacz z wejściem na
tranzystorach polowych. Nietrudno zauważyć, że wszystkie parametry w stanie pamiętania są tym lepsze,
im większa jest wartość C, natomiast przy śledzeniu C powinno być jak najmniejsze. Dlatego też - w
zależności od zastosowania - musimy się zdecydować na kompromis. W dotychczasowych rozważaniach
zakładaliśmy, że kondensator pamiętający ma idealne właściwości. Istnieją kondensatory o praktycznie
pomijalnie małym prądzie wyładowania samoistnego. Mimo to w stanie pamiętania może wystąpić zmiana
napięcia wywołana magazynowaniem ładunku w dielektryku. Zjawisko to wyjaśnia schemat zastępczy
kondensatora pokazany na rys. 4.102. Kondensator C1 reprezentuje ładunek zmagazynowany w dielektryku.
Przy skokowej zmianie napięcia ładunek ten początkowo nie ulega zmianie; przeładowanie następuje
dopiero z upływem czasu. Jeżeli okres próbkowania jest krótki, to potrzebny do tego ładunek jest pobierany
z kondensatora C podczas fazy pamiętania. Przy skoku napięcia o wartość U otrzymuje się wskutek tego
dodatkową zmianę napięcia:
Rysunek 4.102. Schemat zastępczy kondensatora (parametry podane na rys. dotyczą kondensatora 1µF z
dielektrykiem mylarowym)
Przy parametrach takich, jak podane na rys. 4.102, stanowi to 0,6%. Stosunek C1/C zależy od rodzaju
dielektryka. Dobre właściwości pod tym względem mają teflon, polistyren i polipropylen, natomiast
właściwości poliwęglanu, mylaru i większości dielektryków ceramicznych nie są dobre.
Tablica 4.37. Typowe dane scalonych układów próbkująco-pamiętających
98
4.12. Układy kluczy i multiplekserów analogowych
Inną ważną grupą układów współpracujących z przetwornikami analogowo-cyfrowymi są układy kluczy
analogowych oraz multiplekserów analogowych pozwalającw na doprowadzenie do przetwornika
analogowo-cyfrowego większej liczby sygnałów analogowych.
Klucz (przełącznik) analogowy powinien włączać i wyłączać ciągły sygnał wejściowy. Jeżeli jest
włączony, to napięcie wyjściowe powinno być z możliwie dużą dokładnością równe napięciu
wejściowemu; jeżeli jest wyłączony powinno być równe zeru. Najważniejsze właściwości przełącznika
analogowego charakteryzują następujące parametry:
- rezystancja w stanie włączenia;
- rezystancja w stanie wyłączenia;
- zakres napięć analogowych;
- czasy przełączeń.
Układy kluczy
Istnieją różne układy pracy kluczy, spełniające stawiane im zadania. Pokazano je na rys. 4.103.
Rysunek 4.103. Klucze: a) szeregowy, b) równoległy, c) szregowo-równoległy
Na rysunku 4.103a przedstawiono klucz szeregowy. Jeśli jest on zamknięty, to Uwy = Uwe. Jeśli klucz
zostanie otwarty, to napięcie wyjściowe staje się równe zeru. Dzieje się tak jednak tylko przy braku
obciążenia. Przy obciążeniu pojemnościowym ze względu na skończoną wartość rezystancji wyjściowej
99
Rwy = R napięcie spada wolno do zera. Wady tej nie ma klucz równoległy pokazany na rys. 4.103b. Za
to w stanie włączenia, a więc przy otwartym zestyku, ma on skończoną rezystancję wyjściową Rwy = R.
Klucz szeregowo-równoległy z rys. 4.103c łączy zalety obu poprzednich układów. W obu stanach ma
małą rezystancję wyjściową. Rezystancja w stanie włączenia jest niewielka, a w stanie wyłączenia duża.
Zwarte w stanie wyłączenia wyjście może jednak stanowić przeszkodę. Jest tak np. wtedy, kiedy napięcie
wyjściowe chcemy zapamiętać na kondensatorze, jak w układach próbkująco-pamiętających
omówionych w poprzednim punkcie. Możemy wówczas dodać jeszcze jeden zestyk K3, jak na rys.
4.104.
Rysunek 4.104. Klucz szeregowy o
zwiększonym tłumieniu
Rysunek 4.105. Analogowy
multiplekser/demultiplekser
Gdy klucz jest otwarty, wówczas sygnał wejściowy sprzężony pojemnościowo przez K1 jest zwierany
przez zestyk K2; wyjście jednak - ze względu na K3 - jest w stanie wysokiej impedancji. Układ ten
zachowuje się więc na zewnątrz tak jak klucz szeregowy z rys. 4.103a; charakteryzuje się jednak
znacznie lepszym tłumieniem dla wielkich częstotliwości. Układ o większej liczbie wejść przedstawiono
na rys. 4.105. Z czterech zestyków jest zawsze zamknięty tylko jeden, wskutek czego napięcie wyjściowe
jest równe odpowiedniemu napięciu wejściowemu. Dlatego układ ten nosi również nazwę multipleksera
analogowego. Jeśli układ odwrócimy, zachowując tylko jedno wejście, to otrzymamy demultiplekser
analogowy.
Klucze elektroniczne
Do realizacji kluczy stosuje się tranzystory polowe, diody lub tranzystory bipolarne. Mają one różne
właściwości, ale ogólnie schemat układu, w którym te elementy grają rolę kluczy, jest zawsze taki sam.
Przedstawiono go na rys. 4.106.
Rysunek 4.106. Układ sterowania klucza
Sygnały sterujące, najczęściej zgodne ze standardem TTL, są wzmacniane przez bramkę mocy (bufor).
Za nią znajduje się układ dopasowania poziomu (tzw. translator), wytwarzający napięcia potrzebne do
otwierania i zamykania klucza.
Tranzystor polowy jako klucz
Tranzystor polowy przy małych napięciach dren-źródło zachowuje się tak jak rezystor, którego wartość
można zmieniać o kilka rzędów wartości za pomocą napięcia bramka-źródło UGS; może więc pracować
jako klucz.
Na rysunku 4.107 pokazano tranzystor polowy pracujący w układzie klucza szeregowego. Jeżeli napięcie
sterujące UST będzie co najmniej o napięcie odcięcia UP mniejsze od najniższego ujemnego napięcia
100
wejściowego, to tranzystor polowy nie będzie przewodził i napięcie wyjściowe będzie równe zeru. Żeby
tranzystor mógł przewodzić, napięcie UGS powinno być równe zeru.
Warunek ten nie jest łatwy do spełnienia, ponieważ potencjał źródła nie jest ustalony. Układ
umożliwiający spełnienie tego warunku przedstawiono na rys. 4.108.
Rysunek 4.107. Klucz z tranzystorem polowym
Rysunek 4.108. Uproszczenie sterowania klucza
Jeżeli w tym układzie UST będzie większe niż najwyższe dodatnie napięcie wejściowe, to dioda nie
przewodzi i mamy zgodnie z życzeniem UGS = 0.
Przy wystarczająco ujemnym napięciu sterującym dioda przewodzi i tranzystor jest zatkany. W tym
stanie pracy prąd ze źródła napięcia wejściowego płynie przez rezystor R1 do obwodu sterowania.
W normalnych warunkach nie stanowi to przeszkody, ponieważ napięcie wejściowe jest i tak równe
zeru.Trudności mogą wystąpić wówczas, gdy napięcie wejściowe jest podawane przez kondensator
sprzęgający, ponieważ w fazie nieprzewodzenia jest on ładowany napięciem ujemnym.
Problemy te nie występują, gdy jako klucz zastosujemy tranzystor MOS-FET. Tranzystor MOSFET z
kanałem typu n można wprowadzić w stan przewodzenia przez podanie napięcia sterującego większego
od najwyższego dodatniego napięcia wejściowego, nie obawiając się, że popłynie prąd bramka-kanał.
101
Można więc zrezygnować z diody D i rezystora Rt.
Aby zwiększyć zakres dopuszczalnych napięć wejściowych, zamiast pojedynczego tranzystora MOS
należy zastosować klucz CMOS, składający się z dwu komplementarnych tranzystorów MOSFET
połączonych równolegle, jak na rys. 4.109. Aby klucz przewodził, na bramkę tranzystora T1 z kanałem n
podajemy napięcie U+, a bramkę tranzystora T2 z kanałem p łączymy z masą.
Rysunek 4.109. Klucz szeregowy Rysunek 4.110. Zależność rezystancji od napięcia wejściowego
CMOS
dla Usr=USTON=U+=5V
Przy średnich napięciach wejściowych Uwe oba tranzystory MOSFET przewodzą. Jeżeli napięcie
wejściowe wzrośnie, to zmniejsza się UGS1. Wskutek tego rezystancja tranzystora T1 wzrasta. Nie
stanowi to jednak przeszkody, ponieważ równocześnie rośnie moduł UGS2, wskutek czego rezystancja
T2 maleje. Przedstawiono to na rys. 4.110, z którego wynika, że napięcie wejściowe może przyjąć każdą
wartość miedzy 0 i U+.
W przypadku standardowych kluczy CMOS napięcie wejściowe nie może przekroczyć tego zakresu,
ponieważ wskutek tzw. zatrzaśnięcia się (ang. latch up) klucz może ulec zniszczeniu. W tym bowiem
przypadku zaczyna przewodzić dioda kanał-podłoże, dostarczając nośników ładunku do podłoża.
Mogą one spowodować włączenie pasożytniczego tyrystora, który zwiera napięcie zasilania. Jeżeli nie
możemy zagwarantować bezpiecznego zakresu napięć wejściowych, to należy dołączyć szeregowo
rezystor ograniczający prąd do l mA. Prąd ten jest z reguły mniejszy od prądu włączania tyrystora.
Ze względu na te trudności większość scalonych kluczy CMOS jest wyposażona w dodatkowe
układy zabezpieczające lub ma izolację dielektryczną. Podłoże nie jest wówczas izolowane za
pomocą złącza pn, lecz za pomocą warstwy tlenku. Dlatego w elementach CMOS z izolacją
dielektryczną nie występuje zjawisko zatrzaskiwania.
W tablicy 4.38 przedstawiono parametry najczęściej używanych kluczy CMOS i multiplekserów.
Układy z serii 74HC są normalnymi bramkami CMOS o bardzo niskiej cenie. Mogą się jednak
zatrzaskiwać i mają ograniczony zakres dopuszczalnych napięć wejściowych. Pozostałe układy mają
izolację dielektryczną i ich stosowanie nie nastręcza kłopotów. Wymienieni producenci oferują ponadto
wiele innych typów kluczy, z których przykładowo wymieniono tylko kilka. Typowe prądy upływu
kluczy w temperaturze pokojowej wynoszą 0,1... l nA. Podwajają się one przy wzroście
temperatury o 10° i mogą wzrosnąć nawet do 100 nA.
Tablica 4.38. Przykłady kluczy analogowych CMOS
102
103
Tablica 4.39. Przykłady analogowych multiplekserów CMOS
4.13. Układy przetworników C/A
Przetworniki analogowo-cyfrowe (A/C, ang. analog to digital converter, ADC) umożliwiają
przedstawienie napięcia analogowego w postaci liczby L
gdzie ULSB jest napięciem odpowiadającym najmniej znaczącemu bitowi (ang. least significant bit,
LSB), czyli napięciem odpowiadającym L = l.
W celu przekształcenia odwrotnego: liczby na napięcie, stosuje się przetworniki cyfrowo-analogowe
(C/A, ang. digital to analog converter, DAC). Ich napięcie wyjściowe jest proporcjonalne do
wprowadzonej liczby zgodnie z zależnością
Zadaniem przetwornika C/A jest przetworzenie liczby na napięcie. Można wyróżnić trzy różniące się
zasadniczo metody przetwarzania:
- równoległą;
- wagową;
- zliczania.
Metody te przedstawiono poglądowo na rys. 4.111.
W metodzie równoległej (rys. 4.111a) dzielnik napięcia dostarcza wszystkich możliwych napięć, a
dekoder l z n powoduje zamknięcie tego klucza, któremu odpowiada żądane napięcie wyjściowe.
104
W metodzie wagowej (rys. 4.111 b) każdemu bitowi jest przyporządkowany jeden klucz. Napięcie
wyjściowe jest sumowane za pomocą rezystorów o odpowiednich wagach. Metoda zliczania (rys.
4.111c) wymaga zastosowania tylko jednego klucza, który jest okresowo otwierany i zamykany.
Impulsy prądu powodują ładowanie się kondensatora do napięcia proporcjonalnego do liczby zamknięć
klucza lub współczynnika wypełnienia (szerokości) impulsu.
Rysunek 4.111. Metoda przetwarzania cyfrowo-analogowego: a) metoda równoległa, b) metoda wagowa,
c) metoda zliczania
Porównanie tych trzech metod wskazuje, że metoda równoległa wymaga Lmax kluczy, metoda wagowa log2Lmax kluczy, a metoda zliczania - tylko jednego klucza. Ze względu na dużą liczbę kluczy metoda
równoległa jest stosowana rzadko. Coraz większe znaczenie zdobywa metoda zliczania, ponieważ
modulator szerokości impulsów jest układem cyfrowym dającym się łatwo scalić.
Jeżeli układ pracuje z częstotliwością znacznie większą od wymaganej częstotliwości próbkowania (z
tzw. próbkowaniem nadmiarowym, oversampling), upraszcza się dzięki temu wymagany filtr
dolnoprzepustowy.
Największe znaczenie mają przetworniki C/A pracujące według metody wagowej. Klucze są
realizowane dwoma sposobami: w układach CMOS są stosowane bramki transmisyjne, a w układach
bipolarnych stosuje się przełączanie prądów o stałej wartości za pomocą diod lub wzmacniaczy
różnicowych.
Sumowanie ważonych prądów
Prosty układ przetwarzający liczbę dwójkową na proporcjonalne do niej napięcie jest przedstawiony na
rys. 4.112. Rezystancje są dobrane tak, że przy zamkniętym kluczu płynie prąd odpowiadający wadze
danej pozycji. Klucze muszą być zamknięte zawsze wówczas, gdy na danej pozycji występuje jedynka
logiczna. Dzięki objęciu wzmacniacza operacyjnego ujemnym sprzężeniem zwrotnym za pomocą
rezystancji RF, wejście odwracające jest zawsze na potencjale równym zeru.
Rysunek 4.112. Zasada działania przetwornika A/C
105
Prądy składowe są więc sumowane, nie wpływając na siebie wzajemnie. Gdy zamknięty jest klucz
sterowany sygnałem 0, wówczas napięcie wyjściowe wynosi
W ogólnym przypadku mamy:
Wynika stąd:
106
5. Budowa i zasada działania mikrokontrolerów o arch. standardowej
Uproszczony schemat mikrokontrolera przedstawiony na rysunku 5.1 ilustruje jego najważniejsze
zespoły funkcjonalne. Są one skupione wokół jednostki centralnej (CPU), która realizuje ciąg
operacji (program) zapisany w pamięci programu.
Rysunek 5.1. Uproszczony schemat funkcjonalny mikrokontrolera
Przykład programu realizowanego przez CPU:
00001111
00000111
00000000
01111000
00000000
01111000
00011000
01100011
00001111
01111110
Program może mieć za zadanie przetworzenie danych zapisanych wcześniej w pamięci danych i/lub
współpracę z urządzeniami przyłączonymi z zewnątrz przez linie wejścia/wyjścia. Dane i program są
reprezentowane w postaci cyfrowej jako ciągi słów dwójkowych (binarnych) i przesyłane między
jednostką centralną a pamięciami danych i programu przez wewnętrzną szynę danych. Jeśli przez n
oznaczymy liczbę linii danych tej szyny, to mikrokontroler nazywamy n-bitowym, jest on bowiem
zdolny do wykonywania operacji na liczbach n-bitowych.
Większość dostępnych mikrokontrolerów operuje na danych o wielkości będącej wielokrotnością
bajtu, czyli ośmiu bitów, zatem n = 8k, ( k = l, 2, ...).
Liczba linii adresowych, którymi jednostka centralna adresuje pamięć danych i programu, jest
oznaczona przez m. Linie te tworzą wewnętrzną szynę adresową. Przez wielkość przestrzeni
adresowej wewnętrznej pamięci mikrokontrolera rozumie się liczbę wszystkich możliwych
adresów równą 2m. Dla przykładu, jeśli m = 16, to przestrzeń adresowa ma wielkość 64 kilosłów 8bitowych lub w skrócie 64 k (lk = 1024). W większości prostych mikrokontrolerów szyna adresowa
107
jest jednokierunkowa, ponieważ jedynym źródłem adresów jest jednostka centralna. Szyna danych
jest natomiast dwukierunkowa i umożliwia zarówno odczyt, jak i zapis danych przez CPU.
Jednostka centralna jest synchronicznym układem sekwencyjnym. W teorii układów
cyfrowych przez układ synchroniczny rozumie się układ, w którym zmiany stanów wewnętrznych,
a w konsekwencji również sygnałów wyjściowych, zachodzą w chwilach czasu określonych
przez sygnał synchronizujący. Najczęściej jest on okresowy i pochodzi z generatora nazywanego
zegarem (ang. clock). Częstotliwość impulsów zegarowych jest stabilizowana przez przyłączany
z zewnątrz rezonator kwarcowy. Termin „sekwencyjny" odnosi się natomiast do układów
cyfrowych, których stan w kolejnym cyklu zegara zależy nie tylko od sygnałów wejściowych, ale
również od stanu w poprzednim cyklu zegara.
Początkowy stan jednostki centralnej, któremu odpowiada ściśle określony adres
początkowy pamięci programu, jest wymuszany przy użyciu sygnału RESET. Może on być
generowany przez operatora ręcznie przez wciśnięcie odpowiedniego przycisku, wytwarzany
programowo, pochodzić z innego systemu cyfrowego lub być wynikiem włączenia zasilania (ang.
power-on).
Budowa i działanie układów wejścia/wyjścia oraz układów peryferyjnych są
zróżnicowane w zależności od konkretnego typu mikrokontrolera. Najprostsze mikrokontrolery
są wyposażone jedynie w zespoły linii wejścia/wyjścia z wewnętrznym buforowaniem, nazywane
portami (ang. ports).
Budowa i działanie układów wejścia/wyjścia oraz układów peryferyjnych są
zróżnicowane w zależności od konkretnego typu mikrokontrolera. Najprostsze mikrokontrolery
są wyposażone jedynie w zespoły linii wejścia/wyjścia z wewnętrznym buforowaniem, nazywane
portami (ang. ports). Każdy port zawiera zwykle osiem linii i służy do równoległej transmisji
bajtów danych.
Stosuje się też linie do szeregowej transmisji danych (ang. serial port) pracujące w
asynchronicznym trybie UART (ang. universal asynchronous receiver-transmitter) lub zdolne do
pracy w trybie synchronicznym bądź asynchronicznym, nazywanym USART (ang. universal
synchronous-asynchronous receiver--transmitter).
Bardziej rozbudowane mikrokontrolery zawierają ponadto wbudowane układy
przetworników analogowo-cyfrowych (A/C, ang. ADC - analog-to-digital converter) i rzadziej
również przetworników cyfrowo-analogowych (C/A, ang. DAĆ - digital-to-analog converter).
Ze strony cyfrowej mają one zwykle rozdzielczość ośmiu bitów, w bardziej zaawansowanych
mikrokontrolerach spotyka się natomiast przetworniki 10-, a nawet 12-bitowe.
Do układów peryferyjnych zalicza się również liczniki, nazywane niekiedy w literaturze
polskiej „tajmerami" (ang. timers). W zależności od sposobu zaprogramowania mogą one
zliczać impulsy zegara i służyć do wyznaczania ściśle określonych odstępów czasu lub liczyć
impulsy doprowadzone z zewnątrz. Ze względu na ścisłe powiązanie liczników z algorytmami
sterowania w czasie rzeczywistym są one często nazywane układami czasowymi. Najczęściej
spotyka się liczniki o długości 16 bitów.
Podana wyżej krótka lista typowych układów wejścia/wyjścia i układów peryferyjnych nie
wyczerpuje bogactwa ich odmian spotykanych w konkretnych typach mikrokontrolerów. Niektóre z
nich wykorzystują specyficzne interfejsy, np. SPI lub I2C, używane jako standard przemysłowy w
elektronice powszechnego użytku (Philips).
Na tle zarysowanej wstępnie wewnętrznej budowy mikrokontrolera można określić zasadnicze
różnice i podobieństwa między mikrokontrolerem i mikroprocesorem.
Standardowy mikroprocesor składa się z jednostki centralnej i szczątkowej pamięci danych w
postaci zbioru rejestrów. Większość nowoczesnych mikroprocesorów zawiera również generator
zegara. Mikroprocesory nie mają natomiast wbudowanej pamięci programu i układów we/wy
ani układów peryferyjnych.
108
Mikrokontroler może być zatem uważany w pierwszym przybliżeniu za mikroprocesor z
wbudowanymi dodatkowo układami pamięci i układami do komunikacji z otoczeniem.
Ważna różnica dotyczy ponadto zbioru operacji realizowanych przez CPU, nazywanego listą
instrukcji (ang. instruction set). W przypadku mikroprocesorów lista instrukcji jest
zaprojektowana pod kątem ułatwienia obliczeń numerycznych i transmisji danych, natomiast
mikrokontrolery mają rozbudowane grupy instrukcji do obsługi urządzeń peryferyjnych.
Jednostka centralna mikrokontrolera (a także mikroprocesora) składa się z dwóch
podstawowych zespołów funkcjonalnych, nazywanych układem sterowania i układem
wykonawczym, powiązanych ze sobą w sposób pokazany na rysunku 5.2.
Zadaniem układu sterowania (CU, ang. contro! unit) jest koordynacja pracy
poszczególnych zespołów funkcjonalnych mikrokontrolera w trakcie wykonywania
programu. Układ ten otwiera bądź zamyka przepływ danych między zespołami przyłączonymi do
szyny danych oraz generuje sygnały sterujące pracą zespołów funkcjonalnych.
Rysunek 5.2. Struktura jednostki centralnej mikrokontrolera (mikroprocesora)
Blok wykonawczy (EU, ang. execution unit) realizuje natomiast operacje określone przez
sygnały sterujące. Operacje mogą dotyczyć zarówno danych, jak i adresów. Decyzje o przebiegu
każdej kolejnej operacji blok sterowania podejmuje na podstawie zakodowanych rozkazów
przesyłanych przez szynę danych oraz sygnałów stanu generowanych przez układ wykonawczy.
Sygnały sterujące są przesyłane przez dwukierunkową szynę sygnałów sterowania, nazywaną w
skrócie szyną sterowania. Łączy ona układ sterowania z wszystkimi pozostałymi zespołami
funkcjonalnymi mikrokontrolera. Na uproszczonych schematach blokowych mikrokontrolerów i
mikroprocesorów szynę sterowania często pomija się, by poprawić czytelność rysunku
5.1. Standardowa architektura mikrokontrolera
Rozważmy standardowy mikrokontroler przedstawiony na rysunku 5.3. Jego struktura bywa
nazywana jednoszynową, ponieważ wszystkie bloki wewnętrzne mikrokontrolera są
połączone przez wspólną szynę danych. Szyna ta łączy się z zewnętrzną szyną danych przez
bufor, który spełnia dwa zadania. Zapewnia odpowiednie parametry elektryczne sygnałów na
wyprowadzeniach obudowy mikrokontrolera, w tym odpowiednią obciążalność wyjść oraz
umożliwia czasowe odłączenie mikrokontrolera od zewnętrznej szyny danych. W tym celu bufor
jest wyposażony w wyjścia trójstanowe (ang. three-state out-puts). W trzecim stanie,
charakteryzującym się wysoką impedancją, wyjścia bufora mogą być traktowane jako rozwarte.
109
Rysunek 5.3. Budowa wewnętrzna standardowego mikrokontrolera
W dużych systemach cyfrowych, w których do zewnętrznej szyny danych jest przyłączonych wiele
różnych układów cyfrowych (np. kilka mikrokontrolerów lub mikroproce-sorów), zablokowanie
buforów w wybranych układach pozwala uniknąć kolizji na szynie. Kolizja taka mogłaby powstać,
gdyby linie szyny danych były sterowane jednocześnie przez kilka różnych układów. Zazwyczaj
liczba linii zewnętrznej szyny danych jest taka sama, jak liczba linii wewnętrznej szyny danych.
Niekiedy stosuje się multipleksowanie szyny danych. W mikrokontrolerach tego rodzaju (np.
80C51) liczba linii zewnętrznej szyny danych jest mniejsza i do prawidłowego połączenia obu szyn
niezbędny jest multiplekser. Przesłanie n-bitowej liczby przebiega wtedy w dwóch lub w większej
liczbie kroków. Transmisja danych jest wówczas wolniejsza, ale za to obudowa mikrokontrolera ma
mniejszą liczbę wyprowadzeń. Z tego powodu często stosuje się również multipleksowanie szyny
danych z częścią linii szyny adresowej.
Rysunek 5.4. Budowa wewnętrzna mikrokontrolera z multipleksowaną szyną
Szyna adresowa mikrokontrolera z rys. 5.4 została przedstawiona w dużym uproszczeniu.
Pominięto na nim wewnętrzną szynę adresową, służącą do adresowania wewnętrznych pamięci.
Mechanizm generowania adresów wew. i zew. jest podobny. Pochodzą one z rejestru adresowego i
dotyczą danych albo zakodowanych rozkazów umieszczonych w pamięci programu. Liczba linii
wewnętrznej i zew. szyny danych zależy od typu mikrokontrolera. W najprostszych układach z
110
niewielką pamięcią wew. stosuje się 8-bitowe adresy danych (256 bajtów) i 12-bitowe adresy
rozkazów (4 kB pamięci programu). Zewnętrzna szyna adresowa ma natomiast 16 linii i umożliwia
zaadresowanie 64 kB pamięci zewnętrznej. Najbardziej rozbudowane układy, a zwłaszcza
procesory typu embedded, wykorzystują dłuższe adresy, nawet 32-bitowe.
5.2. Układ wykonawczy
Układ wykonawczy prostego mikrokontrolera ostał pokazany na rysunku 5.5
Rysunek 5.5. Budowa wewnętrzna standardowego mikrokontrolera
Składa się on z następujących elementów:
- jednostki arytmetyczno-logicznej ALU (ang. arithmetic-logic unit), akumulatora A (ang.
accumulator),
- rejestru przejściowego, nazywanego też tymczasowym (ang. temporaryregister),
- rejestru wskaźników, określanego też jako rejestr warunków, flag lub rejestr stanu (ang. status
flags).
5.2.1. Jednostka ALU
Zadaniem jednostki arytmetyczno-logicznej jest wykonywanie operacji arytmetycznych
(np. dodawania) i logicznych (np. sumy logicznej) na argumentach zawartych w akumulatorze
i rejestrze przejściowym.
Repertuar operacji realizowanych przez ALU jest określony przez listę instrukcji konkretnego
typu mikrokontrolera. Proste typy mikrokontrolerów wykonują bardziej złożone zadania w sposób
programowy, np. mnożenie jest realizowane przez sekwencję operacji dodawania. Na wyjściu ALU
znajduje się szybki rejestr przesuwający (ang. barrel shifter), który realizuje operacje przesunięcia
wyniku operacji ALU o jeden bit w prawo (\v stronę najmniej znaczącego bitu) oraz o jeden bit w
lewo (w stronę najbardziej znaczącego bitu). Możliwa jest też transmisja wyniku bez przesunięcia.
W realizowanych przez mikrokontroler algorytmach bardzo często oprócz wyników
produkowanych przez ALU istotne są także ich pewne szczególne konsekwencje, jak np.
wynik równy zeru, przeniesienie z najbardziej znaczącego bitu, znak wyniku itp. Informacje
te są pamiętane w rejestrze wskaźników. Specjalne instrukcje pozwalają testować stan
poszczególnych bitów tego rejestru i wykonywać na tej podstawie rozgałęzienia w programie.
Są też instrukcje, które uwzględniają ustawiony wcześniej stan bitu przeniesienia jako
trzeci argument. W ten sposób można np. zrealizować dodawanie z przeniesieniem, w którym
oprócz zawartości akumulatora i rejestru przejściowego uczestniczy bit przeniesienia w
rejestrze wskaźników. Zilustrowano to na rysunku 5.6, który przedstawia strukturę rejestru
111
wskaźników przykładowego mikrokontrolera (80C51 XA), wykorzystanie słowa wskaźników do
sterowania rozgałęzieniem programu oraz realizację dodawania z przeniesieniem.
Rysunek 5.6. a) rejestr wskaźników przykładowego mikrokontrolera (80C51 XA), b) przykład
wykorzystania bitu Z do organizacji pętli w programie, c) przykład dodawania z uwzględnieniem bitu
przeniesienia C
Bit przeniesienia C (ang. carry) pełni podwójną rolę: służy do pamiętania przeniesienia z
najbardziej znaczącego bitu przy operacjach arytme-tycznych oraz do zapamiętania bitu
opuszczającego rejestr przesuwający. W niektórych typach mikroprocesorów bywa oznaczany
symbolem CY. Jeśli bit C jest ustawiony (C = 1), to znaczy że przeniesienie wystąpiło. W
przykładzie z rysunku 5.6c bit C został użyty w operacji dodawania dwóch 8-bitowych liczb z
uwzględnieniem przeniesienia. Założono, że przed wykonaniem dodawania C = l. W wyniku
podanego w przykładzie dodawania nowa wartość bitu C jest także równa l.
W procesorze 80C51 rejestr wskaźników nosi nazwę PSW. Jego zawartość jak wspomniano opisuje
cechy wyniku ostatnio wykonywanej operacji.
bit 7 bit 6 bit 5
bit 4
bit 3
bit 2 bit 1 bit 0
C
AC
F0
RS1
RS0
OV
P
Słowo stanu PSW
Rysunek 5.7. Rejestr PSW
Znaczenie poszczególnych bitów jest następujące:
Bit nadmiaru V (ang. overflow) służy do detekcji błędu określenia znaku wyniku w operacjach
arytmetycznych na liczbach ze znakiem zapisanych w kodzie uzupełnień do dwóch (U2). Bit ten
jest ustawiany, gdy operacja arytmetyczna powoduje przeniesienie na pozycję znaku. W niektórych
typach mikrokontrolerów jest oznaczany symbolem O lub OV. Nadmiar ma miejsce, gdy bit V jest
ustawiony (V = 1).
Bit znaku N (ang. negative) jest określony przez najbardziej znaczący bit wyniku. Ustawiony bit N
(N = 1) oznacza wynik ujemny. Niektórzy producenci mikrokontrolerów oznaczają ten bit
symbolem S (ang. sign).
Bit przeniesienia pomocniczego AC (ang. auxiliary carry), nazywany też bitem przeniesienia
połówkowego i oznaczany symbolem H (ang. half carry), jest pomocny przy wykonywaniu operacji
arytmetycznych na liczbach zapisanych w kodzie BCD (ang. binary coded decimal). Ustawiony bit
112
AC (AC = 1) oznacza, że w wyniku wykonania operacji wystąpiło przeniesienie z mniej znaczącej
czwórki (tetrady) bitów, czyli z bitu b3 na bit b4, przy numeracji bitów od zera. Korzystając z bitu
AC można dokonać korekcji wyniku operacji arytmetycznej na liczbach zapisanych w kodzie BCD.
Bit zera Z (ang. zero] jest ustawiany (Z = 1), jeżeli wynikiem operacji jest zero. W przeciwnym
przypadku bit ten ma wartość równą zeru. W przykładzie z rysunku 2.4,b bit Z został użyty do
sterowania pętlą w programie. Początkowa wartość zapisana w akumulatorze jest równa 10.
Po każdym wykonaniu treści pętli, reprezentowanej w tym przykładzie przez pewną operację X,
następuje zmniejszenie zawartości akumulatora o jeden. Przy dziesiątym obiegu pętli odejmowanie
jedynki od zawartości akumulatora da wynik równy zero i bit Z zostanie ustawiony. Instrukcja
skoku warunkowego reprezentowana przez zapis w polu o kształcie rombu spowoduje wtedy
zakończenie pętli i przejście do dalszego fragmentu programu.
Niektóre typy mikrokontrolerów mogą oprócz wymienionych bitów zawierać w rejestrze
wskaźników inne, dodatkowe bity. Jednym z nich jest bit parzystości P (ang. parity), który jest
ustawiany, jeżeli wynik operacji zawiera parzystą liczbę jedynek. Parzystości P nie należy mylić
z parzystością wyniku w sensie arytmetycznym - w tym znaczeniu parzystość liczby dwójkowej
zależy bowiem wyłącznie od stanu najmniej znaczącego bitu tej liczby.
Zasady, według których bity wskaźników są ustawiane i zerowane, muszą być precyzyjnie
zdefiniowane w opisie listy rozkazów mikrokontrolera. Opis ten powinien ponadto określać wpływ
stanu poszczególnych wskaźników na przebieg realizacji rozkazu.
Układy wykonawcze mikrokontrolerów mogą być bardziej rozbudowane niż układ omówiony
tu jako standardowy. Niektóre zawierają na przykład kilka mogących pracować równolegle
jednostek arytmetyczno-logicznych. Jedna z nich, oznaczana jako FPU (ang. floatingpoint unii), jest
zazwyczaj przeznaczona do wykonywania operacji na liczbach zmiennoprzecinkowych, czyli
zapisanych w postaci mantysy i wykładnika. Struktura tego typu znacznie przyspiesza wykonywanie
programu, ale poważnie komplikuje sterowanie szynami.
5.2.2. Rejestry
Operacje wykonywane przez ALU wymagają dostarczenia na wejście jednego lub dwóch
argumentów, nazywanych też operandami. ALU z trzema lub większą liczbą wejść praktycznie
nie są stosowane. Przykładem operacji jednoargumentowej może być instrukcja zmiany znaku
liczby na przeciwny. Liczbę tę wpisuje się do akumulatora. Po wykonaniu operacji do akumulatora
trafia wynik w postaci liczby o zmienionym znaku i pierwotna zawartość akumulatora ulega
zniszczeniu.
Rysunek 5.8. Budowa wewnętrzna standardowego mikrokontrolera
W przypadku operacji dwuargumentowych, na przykład dodawania, jeden z argumentów jest
umieszczany w akumulatorze, a drugi w rejestrze przejściowym. Wynik dodawania również jest
umieszczany w akumulatorze. Oczywiście, z uwagi na jednoszynową strukturę procesora, czynności
113
te muszą być wykonane kolejno, w odpowiednich odstępach czasu. Z funkcjonalnego punktu
widzenia akumulator różni się od rejestru przejściowego tym, że jego zawartość może być
odczytana i wysłana do innego rejestru lub do pamięci, natomiast zawartości rejestru przejściowego
nie da się wyprowadzić na szynę. Na rysunku 5.8 cechę tę zaznaczono przez dwukierunkowe
połączenie akumulatora z szyną danych i jednokierunkowe połączenie rejestru przejściowego.
Konieczność umieszczania argumentów w akumulatorze i rejestrze przejściowym (dla operacji
dwuargumentowych) bądź w samym akumulatorze (dla operacji jednoargumentowych) wymaga
częstych operacji przesłań danych z udziałem akumulatora. Ponieważ, jak zobaczymy dalej,
transmisje między akumulatorem a pamięcią danych są relatywnie wolne, wymagają bowiem
przygotowania i wysłania adresu pamięci, do przechowywania wartości roboczych zmiennych
używa się szybszego sposobu.
Polega on na wykorzystaniu rejestrów roboczych, nazywanych rejestrami ogólnego
przeznaczenia (ang. general purpose registers) lub w skrócie po prostu rejestrami. Zbiór rejestrów
ma w rzeczywistości strukturę niewielkiej pamięci, jednak dostęp nie wymaga podawania adresu.
Zamiast adresu w zapisie programu używa się nazw symbolicznych rejestrów, np. A, B, C itd. lub
R0, Rl, R2 ... . Nazwy przypisane rejestrom roboczym, jak również ich liczba zależą od
konkretnego typu mikrokontrolera.
Typowe mikrokontrolery zawierają od kilku do kilkudziesięciu rejestrów. W dwójkowym
kodzie programu nazwy rejestrów mogą być zatem zapisane przy użyciu tylko kilku bitów. Kod
programu jest w związku z tym krótszy, a jego wykonanie szybsze niż w przypadku adresowania
argumentów w pamięci.
Przykładowa struktura zbioru rejestrów procesora 8051 została pokazana na rysunku 5.9.
R0
R0
R0
R0
R1
R1
R1
R1
R2
R2
R2
R2
R3
R3
R3
R3
R4
R4
R4
R4
R5
R5
R5
R5
R6
R6
R6
R6
R7
R7
R7
R7
Bank 3
Bank 2
Bank 1
Bank 0
Rys. 5.9. Struktura rejestrów ogólnego przeznaczenia procesora 8051
Rejestry RO – R7 są powielone jako cztery zestawy nazywane bankami (ang. Banked registers).
Można w nich przechowywać bajty. Podczas wykonywania programu w danym momencie dostępny
jest tylko jeden bank. Programista może przełączać aktywny bank przy użyciu odpowiednich
rozkazów.
Mechanizm ten wprowadzono po to, by uzyskać efekt nazywany szybkim, kontekstowym
przełączaniem rejestrów. Polega on na tym, że ten sam program (lub podprogram) może pracować
na różnych zestawach danych w zależności od aktywnego banku rejestrów.
Kolejną, ważną właściwością opisywanego zbioru rejestrów jest możliwość adresowania
poszczególnych bitów w rejestrach. Dla przykładu zapis R0.7 oznacza bit b7 w rejestrze R0.
Wyboru banku w procesorze 8051 dokonuje się przez zmianę wartości 2 bitów RS0 oraz RS1
znajdujących się w słowie stanu – PSW.
Bit 7 bit 6 bit 5
bit 4
bit 3
bit 2 bit 1 bit 0
C
AC
F0
RS1
RS0
OV
P
Rysunek 5.10. Słowo stanu PSW
Rysunek 5.11, pokazuje przykładowy podział rejestrów na grupy o różnych własnościach
funkcjonalnych w innym procesorze - 80C51 XA. Część rejestrów, oznaczona symbolami R4 - R15,
to rejestry globalne, a więc dostępne w dowolnym miejscu programu. Rejestry R8 - R15 są 16bitowe, przechowują zatem dwubajtowe słowa. Rejestry R4 - R7 mogą być natomiast używane
114
zarówno do przechowywania słów 16-bitowych, jak i pojedynczych bajtów. Na przykład R4H
oznacza bardziej znaczący bajt rejestru R4, natomiast R4L - mniej znaczący bajt tego rejestru.
Rysunek 5.11. Struktura rejestrów ogólnego przeznaczenia w mikrokontrolerze 80C51XA
Rejestry RO - R3 są powielone jako cztery zestawy nazywane bankami (ang. banked registers).
Można w nich również przechowywać albo bajty, albo słowa. Podczas wykonywania programu w
danym momencie dostępny jest tylko jeden bank. Programista może przełączać aktywny bank przy
użyciu odpowiednich rozkazów. Mechanizm ten wprowadzono po to, by uzyskać efekt nazywany
szybkim, kontekstowym przełączaniem rejestrów. Polega on na tym, że ten sam program (lub
podprogram) może pracować na różnych zestawach danych w zależności od aktywnego banku
rejestrów.
Dodatkową cechą zestawu rejestrów w mikrokontrolerze 80C51 XA jest możliwość łączenia
niektórych z nich w pary o długości 32 bitów. Dotyczy to par rejestrów (R0, Rl), (R2, R3), (R4, R5)
i (R6, R7). Kolejną, ważną właściwością opisywanego zbioru rejestrów jest możliwość adresowania
poszczególnych bitów w rejestrach. Dla przykładu zapis R0.7 oznacza bit b7 w rejestrze R0.
Rejestry R0 - R7 są implementowane we wszystkich odmianach mikrokontrolera 80C51 XA,
natomiast rejestry R8 - R15 są dostępne tylko w niektórych odmianach tego układu. Oprócz
zróżnicowania rejestrów wynikającego z ich długości, możliwości łączenia w pary i podziału na
banki, rejestry różnią się od siebie pod jeszcze innym, ważnym kątem. Niektóre rozkazy mogą
mianowicie współpracować tylko ze ściśle określonymi rejestrami. Wśród rejestrów występuje więc
pewna specjalizacja pod względem przeznaczenia.
Obok rejestrów ogólnego przeznaczenia mikrokontrolery zawierają dwie inne grupy
rejestrów.
Pierwsza z nich to rejestry specjalne (SFR, ang. special function registers), związane z układami
wejścia/wyjścia, układami peryferyjnymi oraz systemem sterowania zasilaniem,. W przypadku
procesora 8051 to między innymi: rejestr konfiguracji portu P1, rejestr konfiguracji układu
licznika/timera T0, rejestr konfiguracji portu szeregowego UART.
Drugą stanowią rejestry związane z pracą układu sterowania. Należą do nich w przypadku
procesora 8051 między innymi: rejestr rozkazów IR (ang. instruction register), licznik programu IP
(ang. program counter, instruction pointer) oraz niektóre z rejestrów specjalnych takie jak:
wskaźnik stosu SP, kontroler przerwań (ang. interrupt controller)
5.3. Tryby adresowania argumentów
115
Program dwójkowy zapisany w pamięci składa się z ciągu zakodowanych instrukcji. Przez
instrukcję rozumie się opis elementarnej operacji należącej do zbioru opisanego przez listę
instrukcji.
Każdy typ mikrokontrolera ma własną, zdefiniowaną przez producenta listę instrukcji, która
szczegółowo opisuje sposób wykonania poszczególnych instrukcji.
Lista instrukcji jest zatem rodzajem katalogu dostępnych operacji, których używa się przy pisaniu
programów. Lista instrukcji wraz z opisem zachodzących między nimi współzależności oraz
zbiorem reguł dotyczących składni zapisu programu tworzy opis języka programowania
nazywanego językiem asemblera (ang. assembly language) lub w skrócie po prostu
asemblerem.
W teorii języków programowania asembler określa się jako język maszynowy (ang. machinę
language), ponieważ instrukcje programu odpowiadają elementarnym operacjom realizowanym
przez procesor. Języki programowania oparte na zbiorze instrukcji zbliżonym do listy instrukcji
procesora nazywa się językami niskiego poziomu (ang. low-level language).
5.3.1. Formaty instrukcji
Programista piszący program w języku asemblera posługuje się symbolicznym zapisem instrukcji.
W zapisie takim polecenie: „dodaj do zawartości akumulatora liczbę szesnastkową 3CH i umieść
wynik w akumulatorze" ma postać:
ADD
A,#3CH
lub binarnie: 00100100,00111100, 24H,3CH
Symbol ADD oznacza rodzaj operacji i jest nazywany skrótem mnemotechnicznym (mnemonikiem)
lub nazwą symboliczną instrukcji. Podana instrukcja ma dwa argumenty. Pierwszy z nich wskazuje
na akumulator (A), drugi natomiast jest liczbą szesnastkową o wartości 3C. Litera H występująca
po wartości liczby wskazuje, że jest ona podana w kodzie szesnastkowym, natomiast znak # (ang.
hash) służy do wskazania, że argument jest liczbową wartością dodajnika, a nie jego adresem w
pamięci. Przy pisaniu programów dla różnych typów mikrokontrolerów pewną trudność sprawia to,
że nazwy symboliczne instrukcji, rejestrów, a także sposoby definiowania kodów liczbowych i
znaczenia argumentów są różne. Podany przykład symbolicznego zapisu instrukcji dodawania
dotyczy asemblera procesorów rodziny MCS 51 (Intel) i jest stosowany powszechnie przez wielu
innych producentów mikrokontrolerów. Inne oznaczenia symboliczne i reguły składni stosuje
przede wszystkim Motorola oraz niektórzy producenci japońscy.
Innym sposobem przedstawienia instrukcji jest jej opis funkcjonalny, który pokazuje, w jaki
sposób przebiega wykonanie operacji. Funkcjonalny opis podanej wcześniej instrukcji dodawania
ma postać:
(A) <- (A) + #3CH
W zapisie tym nawiasy okrągłe są użyte do wskazania zawartości obiektu, w tym przypadku
akumulatora A. Sam symbol A pozbawiony nawiasów oznaczałby symboliczny adres akumulatora,
natomiast zapis (A) oznacza liczbową zawartość akumulatora. Symbol strzałki opisuje natomiast
przesłanie, w tym przypadku wyniku dodawania do akumulatora, którego nowa zawartość staje się
równa sumie arytmetycznej poprzedniej zawartości akumulatora i liczby 3CH. Naturalnie, w
wyniku wykonania powyższej operacji poprzednia zawartość akumulatora (dodąjna) zostanie
zniszczona.
Program będący ciągiem zapisanych symbolicznie instrukcji, nazywany programem źródłowym,
tworzy się przy użyciu edytora i zapisuje zwykle na dysku komputerowym w postaci pliku ASCII.
Program źródłowy nie może być bezpośrednio wykonywany przez mikrokontroler. Wcześniej
należy go przetłumaczyć na postać dwójkową, dołączyć ewentualnie programy biblioteczne i
załadować do pamięci mikrokontrolera. Operacje te, nazywane odpowiednio kompilacją, łączeniem
(lub konsolidacją) oraz ładowaniem, są szczegółowo przedstawione w rozdziale 6.
116
Program dwójkowy, który można załadować do pamięci i wykonać, jest nazywany programem
wynikowym. Składa się z ciągu zakodowanych dwójkowo instrukcji odpowiadających kolejnym
instrukcjom programu źródłowego. Obraz analizowanej wcześniej instrukcji ADD wyglądałby w
pamięci w sposób pokazany na rysunku 5.12.
Rysunek 5.12. Fragment pamięci programu zawierający instrukcję ADD A,#3CH. Zapisany w pamięci
przykładowy rozkaz ADD zajmuje dwa kolejne bajty o adresach oznaczonych przez: x i x + 1.
Pierwszy bajt (o mniejszym adresie) zawiera kod operacji równy 00100100. Informuje on kontroler
nie tylko o tym, że należy wykonać dodawanie, ale także o sposobie dostępu do dodajnika. W
rozważanym przykładzie kod operacji określa, że dodajnik jest zapisany jako jednobajtowa liczba w
drugim bajcie rozkazu. Natomiast w opisywanym mikrokontrolerze dodąjna musi być zawsze
umieszczona w akumulatorze, dlatego wskazywanie jej lokalizacji jest zbędne. Zbędne jest też
specyfikowanie miejsca, do którego należy wysłać obliczoną sumę, ponieważ jak wynika z
podanego wcześniej opisu funkcjonalnego, znajdzie się ona w akumulatorze.
Podany przykład pokazuje, że instrukcja może być opisana trzema różnymi sposobami:
symbolicznie, funkcjonalnie oraz jako dwójkowa reprezentacja w pamięci. W taki właśnie
sposób instrukcje definiuje lista instrukcji, która jest podstawowym i najbardziej wyczerpującym
dokumentem pomocnym przy tworzeniu programów w języku asemblera.
Większość współczesnych mikrokontrolerów wykorzystuje instrukcje o zróżnicowanej
długości. W prostych układach 8-bitowych zajmują one zwykle od jednego do trzech bajtów
pamięci, w bardziej skomplikowanych mikrokontrolerach 32-bitowych spotyka się natomiast
instrukcje zajmujące nawet do ośmiu bajtów. Podstawowa reguła formatowania dwójkowego kodu
instrukcji wymaga, by w pamięci najpierw był umieszczony kod operacji, a dopiero po nim
argumenty (dane lub adresy). Warianty formatów instrukcji prostego mikrokontrolera 8-bitowego
przedstawiono na rysunku 5.13, na którym podano również przykład różnych formatów
dwójkowych tej samej instrukcji ORL mikrokontrolera 80C51 (ang. logical-OR), wykonującej
operację sumy logicznej dwóch 8-bitowych argumentów. Na rysunku 25.13a pokazano typowe
formaty rozkazów 1-, 2- i 3-bajtowych w prostych mikrokontrolerach 8-bitowych.
Najkrótszy format l-bajtowy jest stosowany wówczas, gdy instrukcja nie wymaga żadnych
argumentów lub gdy mogą być one zwarte w akumulatorze bądź rejestrach.
117
Rysunek 5.13. a) warianty formatów instrukcji w prostym mikrokontrolerze 8-bitowym, b) postać
instrukcji sumy logicznej ORL mikrokontrolera 80C51 w różnych formatach
Drugi i trzeci bajt kodu instrukcji służy wtedy do bezpośr. zapisu 16-bitowego argumentu, 16bitowego adresu operanda albo do zapisu 8-bitowego adr. jednego z argumentów i bezpośredniego
zapisu drugiego argumentu.
Przykład z rysunku 5.13b pokazuje natomiast, jak w praktyce korzysta się ze zróżnicowanych
formatów instrukcji. Widać z niego, że bajt kodu operacji, który jest w każdym z trzech wariantów
pierwszym bajtem kodu instrukcji, ma wartość zależną od użytego formatu. W podanym
przykładzie dla instrukcji ORL mikrokontrolera 80C51 tylko bardziej znacząca tetrada kodu
operacji jest w każdym formacie taka sama (0100). Pozostałe cztery bity służą do identyfikacji
użytego formatu i ewentualnie rejestrów uczestniczących w operacji.
Liczba różnych formatów instrukcji jest znacznie większa w przypadku mikrokontrolerów 16- i
32-bitowych. Mamy wówczas do czynienia z licznymi kombinacjami specyfikacji argumentów, a ta
sama podstawowa instrukcja może być użyta w programie na wiele różnych sposobów, w
zależności od tego, gdzie są umieszczone argumenty. Niełatwe zadanie biegłego posługiwania się
licznymi odmianami instrukcji jest podstawą przy pisaniu efektywnych programów, to znaczy
zajmujących mało pamięci i wykonywanych możliwie szybko.
Z pojęciem formatu instrukcji wiąże się jeszcze jedna ważna sprawa dotycząca terminologii.
Chodzi mianowicie o rozróżnienie pojęć instrukcja i rozkaz. W niektórych pracach pojęcia te są
używane zamiennie, co może prowadzić do nieporozumień.
- Przez rozkaz będziemy rozumieć rodzaj operacji opisanej przez określoną instrukcję.
- Kod operacji zapisany w pierwszym bajcie instrukcji będziemy w związku z tym nazywać
kodem rozkazowym lub w skrócie rozkazem.
- Instrukcja będzie natomiast oznaczać pojęcie szersze, czyli rozkaz wraz ze specyfikacją
argumentów, na których operacja ma być wykonana.
Dla przykładu, w tym rozumieniu obu terminów ADD oznacza symboliczny zapis rozkazu
dodawania, a zapis ADD A,#7H oznacza instrukcję o treści: dodaj liczbę 07H do zawartości
akumulator i umieść wynik w akumulatorze.
5.3.2. Podstawowe tryby adresowania
Przez tryb adresowania rozumie się sposób wskazywania na argumenty wykorzystywane w trakcie
wykonania instrukcji. Im bogatszy jest repertuar trybów adresowania realizowanych przez dany typ
mikrokontrolera, tym bardziej efektywny jest proces programowania pozwalający na zwięzły zapis
algorytmów. Standardowe mikrokontrolery 8- i 16-bitowe realizują zazwyczaj kilka bądź
kilkanaście różnych sposobów adresowania argumentów operacji, ustępując procesorom
stosowanym w dużych komputerach stacjonarnych. Ciągły rozwój techniki mikroprocesorowej
118
powoduje stale wzbogacanie repertuaru sposobów adresowania i nowoczesne procesory do aplikacji
typu embedded używają już podobnego arsenału adresowego co procesory stosowane w dużych
komputerach. Do najważniejszych trybów adresowania można zaliczyć adresowanie:
- implikowane, zwane też wewnętrznym lub rejestrowym (ang. implied, inherent, register),
- natychmiastowe (ang. immediate),
- bezpośrednie (ang. direct),
- pośrednie (ang. indirect),
- indeksowe (ang. indexed),
- względne (ang. relative).
Adresowanie implikowane
Adresowanie implikowane dotyczy jednobajtowych instrukcji, dla których zarówno operand (bądź
operandy) jak i miejsce przeznaczenia wyniku są określone przez słowo rozkazowe. Ten tryb
adresowania jest używany wyłącznie w odniesieniu do wewnętrznych rejestrów mikroprocesora, w
tym przede wszystkim w odniesieniu do akumulatora (lub akumulatorów, jeśli mikrokontroler
zawiera ich większą liczbę). Dwójkowy kod instrukcji nie zawiera więc ani argumentów, ani
adresów i składa się wyłącznie z kodu rozkazu. Wskazanie na argumenty jest niejako „ukryte"
wewnątrz kodu rozkazu, skąd bierze się nazwa tego trybu adresowania.
Rysunek 5.14 ilustruje implikowany tryb adresowania dla przytoczonego już wcześniej rozkazu
ADD.
Rysunek 5.14. Ilustracja implikowanego trybu adresowania na przykładzie rozkazu dodawania ADD w
mikrokontrolerze 80C51
Ze względu na krótki format instrukcji i brak konieczności adresowania argumentów w pamięci,
instrukcje wykorzystujące tryb implikowany przy adresowaniu argumentów są bardzo efektywne w
użyciu. Należy je w związku z tym stosować, jeśli jest to tylko możliwe. Ograniczenia w
wykorzystaniu tego trybu wynikają głównie z dostępnej liczby rejestrów. W skomplikowanych
algorytmach używających wielu zmiennych nie można zmieścić wszystkich danych i zmiennych
roboczych w rejestrach, dlatego korzy-nie z innych trybów adresowania jest nieuniknione. Niemniej
jednak należy próbować . rozmieścić zmienne w rejestrach i pamięci, by te, do których algorytm
odwołuje się najczęściej, znalazły się w rejestrach, a inne, rzadziej używane - w pamięci.
Adresowanie natychmiastowe
Adresowanie natychmiastowe ma miejsce wtedy, gdy operand jest podany w jawnej postaci w
kodzie instrukcji. Naturalnie, by móc skorzystać z tego trybu, programista musi znać wartość
argumentu w trakcie pisania programu. Tryb natychmiastowy może być zatem używany wyłącznie
w odniesieniu do stałych, nie ma natomiast zastosowania w przypadku zmiennych. W przykładzie z
rysunku 5.15 pokazującym zastosowanie natych-miastowego trybu adresowania, użyto 8-bitowej
stałej natych-miastowej, takiej bowiem długości dodajnika wymaga 8-bitowa jednostka ALU
rozważanego mikrokontrolera. W przypadku innych rozkazów tego mikrokon-trolera, a także
mikrokontrolerów 16- i 32-bitowych, można stosować dane natychmiastowe o większej długości.
119
Rysunek 5.15. Ilustracja natychmiastowego trybu adresowania na przykładzie rozkazu dodawania
ADD w mikrokontrolerze 80C51
W pamięci programu zajmują one wtedy dwa lub więcej kolejnych bajtów następujących po
kodzie rozkazu. W większości typów mikrokontrolerów wielobajtowe argumenty natychmiastowe
są zapisywane w kodzie instrukcji zaczynając od najbardziej znaczącego bajtu, tzn. bajt ten jest
umieszczony jako pierwszy po kodzie rozkazu. Instrukcje wykorzystujące natychmiastowy tryb
adresowania zajmują, oczywiście, więcej miejsca w pamięci i wykonują się wolniej niż instrukcje
zapisane w trybie implikowanym.
Adresowanie bezpośrednie
Adresowanie bezpośrednie odnosi się do instrukcji wielobajtowych, w których po kodzie rozkazu
następuje adres argumentu umieszczonego w pamięci danych. Niektóre typy mikrokontrolerów
dopuszczają adresowanie tą metodą tylko ograniczonego fragmentu pamięci danych.
la przykładu, w mikrokontrolerze 80C51 można w ten sposób adresować wewnętrzny obszar
pamięci o adresach od 0 do 255, natomiast w układzie 16-bitowym typu 80C51 XA początkowy l
kB pamięci danych. Mikrokontrolery 8-bitowe produkowane przez firmę Motorola posługują się
rozszerzonym adresowaniem bezpośrednim (ang. extended mode) i umożliwiają adresowanie 64 kB
pamięci. W nowoczesnych mikrokontrolerach 16- i 32-bitowych adresowanie bezpośrednie jest
najczęściej kombinowane z bardziej zaawansowanymi metodami dostępu, opartymi na segmentacji
pamięci. W przykładzie z rysunku 5.16a pokazano działanie rozkazu dodawania ADD w
mikrokontrolerze x51. Natomiast na rysunku 5.16b przedstawiono schemat funkcjonalny
bezpośredniego adresowania rozszerzonego w procesorze 68HC05 (Motorola). Przy okazji warto
prześledzić różnice w zapisie symbolicznym, dwójkowym i funkcjonalnym instrukcji, stosowanym
przez obie firmy. W symbolicznym zapisie Motoroli pominięto symbol akumulatora, który w tym
przypadku jest domyślnym miejscem ulokowania dodajnej i wyniku. W zapisie funkcjonalnym
użyto natomiast symbolu (M), który oznacza zawartość komórki pamięci o podanym adresie
bezpośrednim (M od ang. memory).
120
Rysunek 5.16. Bezpośrednie adresowanie pamięci: a) rozkaz ADD z krótkim adresem –x51, b) rozkaz
ADD z rozszerzonym trybem adresowania 16 bitowego – 68HC05
Adresowanie indeksowe
Adresowanie indeksowe nie jest stosowane we wszystkich mikrokontrolerach (na przykład x51 nie
realizuje tego trybu). Polega na obliczaniu adresu przez sumowanie zawartości specjalnie
przeznaczonego do indeksowania rejestru, nazywanego rejestrem indeksowym, z adresem
bezpośrednim, zapisanym w instrukcji. Obliczony w ten sposób fizyczny adres pamięci bywa
nazywany adresem efektywnym (rys. 5.17).
Adresowanie indeksowe jest szczególnie użyteczne przy operowaniu na blokach danych, czyli
ciągach bajtów bądź słów zapisanych w kolejnych komórkach pamięci. Umieszczając w instrukcji
adres początku bloku danych można uzyskać wygodny dostęp do kolejnych bajtów danych przez
samą tylko zmianę zawartości rejestru indeksowego.
Rysunek 5.17. Adresowanie indeksowe
Adres efektywny jest sumą dwóch składników, zatem rola, jaką te składniki spełniają, jest czysto
umowna. W niektórych mikrokontrolerach adres początku bloku danych jest umieszczony w
121
rejestrze indeksowym, a składnik określający przesunięcie (ang. offset, displacement) adresowanego
bajtu względem początku bloku jest umieszczony w instrukcji. Ten wariant adresowania
indeksowego jest nazywany adresowaniem bazowym, a rejestr indeksowy - rejestrem bazowym.
Często też stosuje się krótki, 8-bitowy adres zapisany w drugim bajcie dwubajtowej instrukcji. W
niektórych typach mikrokontrolerów przesunięcie adresu względem adresu bazowego jest
traktowane jako liczba ze znakiem zapisana w kodzie U2, co umożliwia dostęp zarówno do
komórek o adresach większych, jak i mniejszych od adresu bazowego. Odmianą adresowania
indeksowego jest adresowanie postindeksowe, polegające na obliczaniu adresu efektywnego jako
sumy zawartości rejestru indeksowego z zawartością komórki pamięci adresowanej przez adres
bezpośredni instrukcji. Metodę takiego obliczania adresu pokazano na rysunku 5.18.
Rysunek 5.18. Adresowanie postindeksowe
Jeżeli jednocześnie mikrokontroler umożliwia również podstawowy tryb adresowania indeksowego,
to jest ono dla rozróżnienia nazywane adresowaniem proindeksowym. Długość rejestru
indeksowego oraz adresu bazowego i adresu pośredniego jest różna dla różnych typów
mikrokontrolerów. Różne są też zestawy instrukcji, które mogą korzystać z tego trybu adresowania.
Ponadto niektóre mikrokontrolery zawierają więcej niż jeden rejestr indeksowy. Z tego powodu
na rysunkach 25.17 i 5.18 podano jedynie ogólny schemat ilustrujący adresowanie indeksowe, nie
zaś jak wcześniej, ilustrację dotyczącą konkretnej instrukcji wybranego mikrokontrolera.
Adresowanie pośrednie
Adresowanie pośrednie ma miejsce, gdy część adresowa instrukcji wskazuje na komórkę pamięci
(lub pierwszą z kilku sąsiednich komórek) zawierającą adres efektywny.
Sytuację taką przedstawiono na rysunku 5.19. Odmianą adresowania pośredniego jest adresowanie
zawartością rejestrów (ang. pointer addressing), w którym adres efektywny jest zawarty w rejestrze
lub w parze rejestrów mikrokontrolera. W tym przypadku identyfikacja tych rejestrów odbywa się
na podstawie słowa rozkazowego. Zazwyczaj nic wszystkie rejestry mikrokontrolera mogą być
użyte do przechowywania adresów pośrednich, lecz tylko niektóre z nich.
122
Rysunek 5.19. Adresowanie pośrednie
Adresowanie względne
Adresowanie względne służy do adresowania pamięci względem adresu aktualnie wykonywanej
instrukcji w pamięci programu. Adres ten jest przechowywany w specjalnie do tego celu
przeznaczonym rejestrze, nazywanym licznikiem programu (PC, ang. program counter), licznikiem
rozkazów lub wskaźnikiem instrukcji (1P, ang. instruction pointer), przedstawionym wcześniej.
Instrukcja wykorzystująca względny tryb adresowania zawiera jedno- lub kilkubajtowe przesunięcie
nazywane adresem względnym (ang. relative address). Adres efektywny jest obliczany. jako suma
zawartości licznika programu i adresu względnego, w sposób przedstawiony na rysunku 5.20.
Jednobajtowe przesunięcie zapisane jako liczba ze znakiem w kodzie U2 umożliwia dostęp do
komórek pamięci położonych w obszarze [-128, +127] bajtów względem instrukcji używającej tego
trybu adresowania. Odpowiednio większy zakres dostępu zapewniają instrukcje z wielobajtowym
przesunięciem.
Rysunek 5.20. Adresowanie względne
Tryb ten jest używany przede wszystkim w instrukcjach skoków i umożliwia tworzenie programów
relokowalnych, to znaczy takich, które mogą być prawidłowo wykonywane niezależnie od
fizycznego adresu obszaru pamięci, w którym zostały umieszczone. Dodatkową korzyścią ze
stosowania adresowania względnego jest skrócenie kodu instrukcji skoków, które zamiast pełnego
adresu bezpośredniego zawierają jedynie krótkie, zwykle jednobajtowe przesunięcie (adres
względny).
Innym, ciekawym zastosowaniem względnego trybu adresowania jest pisanie programów, które
w czasie wykonywania modyfikują swój własny kod. Właściwość ta może być użyta na przykład
przy programowaniu algorytmów z dziedziny metod sztucznej inteligencji. Niezbędne jest jednak
przy tym duże doświadczenie w programowaniu w języku asemblera, ponieważ błędnie napisany
program tego typu może łatwo doprowadzić do zniszczenia zawartości pamięci i nieprzewidzianych
123
reakcji całego systemu. Naturalnie, programy zdolne do modyfikowania własnego kodu muszą być
zapisane w pamięci typu RAM.
Przedstawione tryby adresowania są typowymi, najczęściej stosowanymi sposobami dostępu do
argumentów. W niektórych mikrokontrolerach spotyka się dalsze ich odmiany, powstające
najczęściej w wyniku kombinacji omówionych trybów podstawowych. Nowoczesne
mikrokontrolery, przystosowane do operowania dużymi przestrzeniami adresowymi, wykorzystują
podział pamięci na mniejsze fragmenty nazywane segmentami. Segmentacja wiąże się ściśle z
metodami dostępu do argumentów i wymaga stosowania trybów adresowania o odpowiednio
zmodyfikowanym działaniu. Są one jednak zawsze oparte na omówionych wcześniej elementarnych
zasadach generowania adresów.
5.3.3. Przykładowa lista instrukcji - mikrokontroler 80C51
W celu pokazania zastosowania różnych trybów adresowania oraz możliwości jednostki ALU
poniżej zaprezentowano listę instrukcji procesora 80C51.
Rysunek 5.21. Lista instrukcji procesora 80C51
124
Rysunek 5.22. Lista instrukcji procesora 80C51 – cd.
Rysunek 5.23. Lista instrukcji procesora 80C51 – cd.
5.4. Układ sterowania
Przedstawiony w zarysie układ sterowania mikrokontrolera jest fragmentem większego zespołu
funkcjonalnego, nazywanego podsystemem sterowania. Oprócz samego układu sterowania
obejmuje on następujące elementy:
− układ oscylatora
− układ resetu
− rejestr rozkazów IR (ang. instruction register),
− dekoder rozkazów,
− licznik programu IP (ang. program counter, instruction pointer).
Do podsystemu sterowania należą ponadto niektóre rejestry specjalne SFR, wskaźnik stosu SP (ang.
stack pointer), kontrolery szyn, układy transmisyjne oraz kontroler przerwań (ang. interrupt
controller).
5.4.1. Układ oscylatora
W mikrokontrolerze (mk) można wyróżnić dwa źródła sygnału zegarowego:
− sygnał zegarowy generowany „wewnątrz” mk (wewnętrzny układ RC),
− sygnał zegarowy generowany z wykorzystaniem zewnętrznych elementów.
Każdy mk posiada dedykowane dwie końcówki służące wyłącznie do podłączenia zewnętrznych
elementów wykorzystywanych do generacji (stabilizacji) sygnału zegarowego. Jedna z nich jest
wejściem (najczęściej oznaczana OSC1 lub XTAL1), druga wyjściem (OSC2 lub XTAL2)
wewnętrznego układu generatora. Można do nich podłączyć oscylator kwarcowy, ceramiczny, układ
RC lub podać na końcówkę wejściową zewnętrzny sygnał prostokątny.
W przypadku mikrokontrolera 80c51 układ oscylatora jest bardzo prosty, ponieważ możliwa jest
praca jedynie z zewnętrznym rezonatorem kwarcowym lub z podaniem zew sygnału prostokątnego
na wejście XTAL1.
125
Rysunek 5.24. Połączenia zewnętrzne układu oscylatora 80c51
Tablica 5.1. Parametry układu oscylatora 80c51
Poniżej przedstawiono schematy układów połączeń zewnętrznych oraz wewnętrznych oscylatora
80C51.
Rysunek 5.25. Połączenia wewnętrzne układu oscylatora mikrokontrolera 80C51 – schemat ideowy
Rysunek 5.26. Połączenia wewnętrzne układu oscylatora mikrokontrolera 80C51 – schemat dokładny
126
Mikrokontroler PIC16F873 ma więcej możliwości generacji sygnału zegarowego. Umożliwia
wykorzystanie:
- rezonatora kwarcowego/ceramicznego (rys. 5.27a),
- rezonatora RC (najtańszy ale najgorsze parametry generowanego przebiegu) (rys. 5.27b),
- zewnętrznego sygnału prostokątnego podanego na wejście OSC1 (rys. 5.27c),
- wewnętrznego rezonatora RC (rys. 5.27d).
Ponadto możemy wyróżnić następujące tryby pracy oscylatorów kwarcowych/ceramicznych:
- LP – generowanie niskich częstotliwości dla zapewnienia min. poboru mocy (ang. Low
Power Crystal),
- XT – generowanie średnich częstotliwości (ang. Crystal/Resonator),
- HS – generowanie wysokich częstotliwości (ang. Hight Speed Crystal/Resonator).
Producenci zawierają w dokumentacji mk tabele wartości kondensatorów dla poszczególnych
trybów pracy oscylatora/rezonatora. Dla mikrokontrolera PIC16F873 zostały one przedstawione
poniżej na rysunku 5.27. Dla przykładu w tablicy 5.2 podano wartości kondensatorów C1 i C2 dla
wszystkich możliwych trybów pracy oscylatora kwarcowego tego mikrokontrolera.
Rysunek 5.27. Sposoby generowania sygnału zegarowego
Tablica 5.2. Wartości kondensatorów w zależności od trybu pracy oscylatora kwarcowego
Metodę generacji sygnału zegarowego jak i tryb pracy oscylatora wybiera się na etapie
programowania mk, czyli podczas wprowadzania kodu programu do jego pamięci FLASH. Służą do
tego dwa bity zawarte w rejestrze konfiguracyjnym (rys. 5.28). Rejestr ten znajduje się w pamięci
FLASH pod adresem 2007H i jest dostępny (można do niego pisać i z niego czytać) wyłącznie w
trybie programowania wykorzystując w tym celu programator i dołączone do niego
oprogramowanie np. MPLAB. Rejestr konfiguracyjny jest 14-bitowy. Na rys. 2.15 pokazano jego
127
fragment związany z omawianymi zagadnieniami. Układ pracy oscylatora mk musi być zgodny z
tym, co zostało zaprogramowane. W przeciwnym razie mk nie będzie działał!
Rysunek 5.28. Fragmenty rejestru konfiguracyjnego mk PIC16F873
Ponieważ od mk wymaga się niezawodności niektóre z nich wyposażone są w specjalne generatory
zapewniające ciągłą, bezawaryjną generację sygnału zegarowego oraz jego filtrację, np. mk
ST72215G. Ponadto cechą charakterystyczną współczesnych mk są rozbudowane układy generacji i
dystrybucji sygnałów zegarowych. Potrzeba ta wynika z dużej ilości pracujących autonomicznie
modułów we/wy wymagających różnych sygnałów zegarowych. Same procesory rdzeniowe często
są wyposażone w 2 generatory zegarowe, jeden o częstotliwości zapewniającej maksymalną
szybkość pracy i drugi pozwalający na pracę z częstotliwością 32,768 kHz, np. Rabbit2000
Na rys. 5.29. pokazano układ dystrybucji sygnałów zegarowych mk DS87C530. Dostarcza on
sygnał zegarowy do jednostki centralnej oraz urządzeń peryferyjnych. Składa się z
programowalnego preskalera i układu dostarczającego sygnał do zewnętrznych urządzeń. Preskaler
pozwala na ustawienie odpowiedniej częstotliwości sygnału zegarowego, co w przypadku jej
zmniejszenia, powoduje zmniejszenie pobieranej przez mk mocy (moc pobierana przez układy
CMOS jest proporcjonalna do ich częstotliwości pracy).
CD1
CD0
SWB
XTOFF ALEOFF
DME1 DME0
1/65536
z zewnętrznego
oscylatora
f
osc
1/4, 1/64, 1/1024
f
wewnętrzny
oscylator
RING
f
cpu
ring
2-4MHz
układ
wyboru
Rysunek 5.29. Układ oscylatora mikrokontrolera DS87C530
W układzie występuje dodatkowy oscylator zwany Ring, którego cechami charakterystycznymi są:
bardzo szybkie wejście w stan generacji oraz niestabilna praca. Oscylator ten pozwala na szybkie (w
ciągu kilku mikrosekund) podjęcie pracy przez mikrokontroler, w odróżnieniu od normalnego
układu oscylatora, który do stabilnej pracy wymaga czasu 65536 okresów oscylacji.
128
5.4.2. Układ resetu
Sygnał RESET służy do inicjalizacji pracy mk, czyli wprowadzenia go w stan początkowy.
Inicjalizacja polega najczęściej na wyzerowaniu licznika rozkazów, ustawienia go na początek
wykonywania programu. Urządzenia we/wy i rejestry sterujące są ustawiane w tryb standardowy
(spoczynku). Uniwersalne końcówki we/wy są ustawione jako wejścia o wysokiej impedancji, aby
minimalnie wpływać na otoczenie mk (w dokumentacji każdego mk znajduje się informacja o
stanie wszystkich rejestrów i portów po resecie mk). Dla niektórych mk po resecie może być
czytany rejestr stanu określający tryb pracy mk, stany (poziomy) sygnałów na niektórych
końcówkach, a następnie czytany adres początku programu znajdujący się w obszarze obsługi
resetu. Dla mk o architekturze harwardzkiej po resecie wykonywana jest instrukcja najczęściej spod
adresu 00h (np. 80C51, AT90S8515, PIC16F873, COP880). Natomiast dla mk bazujących na
architekturze Von-Neumanna adres ten znajduje się zazwyczaj na końcu obszaru adresowania
pamięci, gdyż początkowe adresy najczęściej przypisane są urządzeniom we/wy i pamięci RAM
(np. ST72215G – po resecie wykonywana jest instrukcja spod adresu FFFEH-FFFFH). Możemy
wyróżnić następujące źródła resetu:
− reset po włączeniu zasilania,
− reset wywołany zewnętrznym sygnałem RESET,
− reset programowy wywołany przez ustawienie odpowiedniego bitu,
− reset wywołany przez układ watchdog,
− reset wywołany przez układy nadzorujące poprawność pracy mk (np. od układu
wykrywającego spadek napięcia zasilania LVD (ang. Low Voltage Detector) w ST72215G,
− BOR (ang. Brown-out Reset) w PIC16F873).
Każdy mk posiada dedykowaną końcówkę (pin) do której przypisany jest zewnętrzny sygnał resetu.
Sygnał ten umożliwia asynchroniczny reset mk..
Najczęściej jest on aktywny poziomem niskim (z wyjątkiem mk 80C51).
Najprostszy, często stosowany układ resetu przedstawiono na rys. 5.30. Zapewnia on niski poziom
sygnału pojawiający się bezpośrednio po włączeniu zasilania i trwający przez określony czas. Jest to
układ RC, zatem czas trwania resetu zależy od stałej czasowej RC. Na rys. 5.31 pokazano układ
resetu procesora 80C51.
VCC
u(t)
Mikrokontroler
R
u(t)
RESET
stan
C
t
Praca
Reset
t
Rysunek 5.30. Najczęściej spotykany - najprostszy układ resetu mikrokontrolera
129
VCC
C
u(t)
u(t)
Mikrokontroler
80C51
RST
stan
R
C=10uF
R=8.2K
t
Praca
Reset
t
Rysunek 5.31. Najprostszy układ resetu mikrokontrolera 80C51
Na rysunku 5.32 pokazano reakcję mikrokontrolera 80C51 na zewnętrzny sygnał resetu.
Rysunek 5.32. Reakcja układu mikrokontrolera z rodziny 80C51 na zewnętrzny sygnał reset
Obecnie mk posiadają rozbudowane układy resetu, które poza resetem mk również monitorują
poprawność pracy systemu i reagują na sytuacje awaryjne. Na rys. 5.33 pokazano taki układ.
Rysunek 5.33. Układ resetu mk PIC16F873
130
Reset po włączeniu zasilania jest generowany przez specjalny blok (VDD ang. Rise Detect), w
przypadku wykrycia przez niego narastającego zbocza sygnału zasilającego. Dzięki temu układ z
rys. 5.31 jest zbędny. Sygnał resetu może być również wywołany przez bloki nadzorujące
poprawność pracy mk takie jak BOR, czy LVD. BOR sprawdza napięcie zasilające. Jeżeli spadnie
ono poniżej VBOR i jego spadek trwać będzie przynajmniej przez TBOR to układ wysyła sygnał
resetu. Działanie układu LVD jest bardziej złożone. Można powiedzieć, iż spełnia on funkcje
detektora narastania napięcia zasilania jak i układu BOR. Na rys. 5.34 pokazano na przebiegach
działanie takiego układu.
Rysunek 5.34. Przebiegi sygnałów VDD i RESET dla układu LVD mk ST72215G
Układ generuje sygnał resetu dopóki VDD podczas narastania nie osiągnie założonego napięcia
VIT+ oraz gdy to napięcie spadnie poniżej VIT- podczas opadania. Kolejnym źródłem resetu jest
układ watchdog. Generuje on sygnał resetu, gdy nastąpi zawieszenie programu w mk. Układy resetu
posiadają również dodatkowe układy wydłużające sygnał reset (rys. 5.35). Ma to zapewnić pracę mk
z już ustalonym napięciem zasilania i ustalonym sygnałem z oscylatora. W PIC16F873 licznik
PWRT, z własnym wewnętrznym oscylatorem RC, wydłuża sygnał resetu o TPWRT=72ms, a
licznik OST o dodatkowe 1024 cykle sygnału z oscylatora kwarcowego (TOSC), oczywiście o ile są
włączone.
Dla mk DS87C530 wydłużenie sygnału resetu spowodowane czasem oczekiwania na stabilną pracę
głównego oscylatora jest stałe i wynosi 65536.
Rysunek 5.35. Przebiegi sygnałów w układzie resetu mk PIC16F873
Do konfiguracji układu resetu są przeznaczone specjalne rejestry. Znajduje się w nich również
informacja o przyczynie resetu, np. czy reset nastąpił sygnałem zewnętrznym, czy po włączeniu
zasilania, czy też został wywołany przez układ watchdog. (Przykładowe nazwy rejestrów
zawierających wspomniane informacje w przypadku mikrokontrolera DS87C530 są następujące
WDCON - D8H, EIE - E8H, EXIF – 91H, PCON – 87H.)
5.4.3. Cykl wykonania rozkazu
Po wykonaniu cyklu resetu, mk zaczyna wykonywać instrukcje programu zapisane w pamięci
programu.
131
Mikrokontroler o prostej strukturze wykonuje instrukcje programu w dwóch fazach:
- pobranie kodu rozkazu z pamięci programu do rejestru rozkazów IR (ang. fetch),
- wykonanie odpowiedniej sekwencji mikrooperacji zgodnie z sygnałami generowanymi
przez układ sterowania (ang. execution).
Etap pobrania kodu rozkazu jest zunifikowany dla wszystkich rodzajów instrukcji, ponieważ
dwójkowy format instrukcji przewiduje, że kod rozkazu jest zawsze zapisany w pierwszym bajcie.
Faza ta składa się z następujących czynności:
- podanie zawartości licznika programu IP przez rejestr adresowy na szynę adresową,
- wygenerowanie przez układ sterowania sygnału odczytu pamięci programu i
doprowadzenie go do pamięci przez szynę sterowania,
- przesłanie kodu rozkazu z wyjść pamięci przez szynę danych do rejestru rozkazów I R,
- zwiększenie zawartości licznika programu IP o jeden (inkrementacja IP).
Przepływ informacji podczas fazy pobierania kodu rozkazu ilustruje rysunek 5.36.
Rysunek 5.36. Przepływ sygnałów podczas fazy pobrania rozkazu
Faza wykonania instrukcji przebiega różnie w zależności od konkretnej operacji. Pierwszym etapem
jest jednak zawsze dekodowanie rozkazu realizowane przez dekoder wykonany jako układ
kombinacyjny. Na podstawie zdekodowanego stanu rejestru rozkazów układ sterowania generuje
właściwą sekwencję sygnałów sterujących. Sekwencja ta jest uzależniona głównie od liczby
odwołań do pamięci (wewnętrznej lub zewnętrznej), potrzebnych do wykonania instrukcji.
Rozważmy wykonanie przykładowych instrukcji różniących się zastosowanym formatem zapisu
oraz trybem adresowania. Załóżmy przy tym dla uproszczenia, że szyna danych jest 8-bitowa,
natomiast szyna adresów ma 16 bitów. Typową instrukcją o formacie jednobajtowym jest operacja
przesłania zawartości rejestru Ri do akumulatora A, której zapis funkcjonalny przedstawiamy jako:
(A) <- (Ri). Instrukcja ta nie wymaga odwołań do pamięci (wewnętrznej ani zewnętrznej), a jej
wykonanie ilustruje rysunek 5.37.
132
Rysunek 5.37. Wykonanie instrukcji przesłania zawartości rejestru RI do akumulatora
Bardziej skomplikowany przebieg ma operacja przesłania zawartości akumulatora do komórki
pamięci adresowanej w sposób pośredni, przez złożenie (konkatenację) zawartości rejestrów RO i
RI. Operację tę możemy oznaczyć jako M(RO, RI) <- (A). Wykonanie tej instrukcji pokazano na
rysunku 5.38, na którym dodatkowo podano przebiegi czasowe sygnałów związanych z
wykonaniem instrukcji. Ponieważ rozważana instrukcja ma format jednobajtowy (adres pośredni
mieści się w rejestrach), do jej wykonania potrzebny jest jednokrotny dostęp do pamięci programu
(cykl fetch) i jednokrotny dostęp do pamięci danych.
Rysunek 5.38. Faza wykonania instrukcji M(R0,R1)<-(A).a) przepływ danych, b)przebiegi czasowe w
fazie pobrania i wykonania instrukcji
Znaczenie parametrów określających czasy trwania impulsów z. rysunku 5.38b jest następujące
(według oznaczeń firmy Intel):
- tr - czas trwania impulsu odczytu z pamięci,
- tar - czas wyprzedzenia ustalonego stanu szyny adresowej względem impulsu odczytu,
- tdr - czas wyprzedzenia ustalonego stanu szyny danych względem końca impulsu odczytu,
- thr - czas utrzymywania stanu szyny danych po zakończeniu impulsu odczytu,
- tw - czas trwania impulsu zapisu do pamięci,
- taw - czas wyprzedzenia ustalonego stanu szyny adresowej względem impulsu zapisu danych do
pamięci,
- tdw - czas wyprzedzenia stabilnego stanu szyny danych względem impulsu zapisu do pamięci,
thw - czas utrzymania stanu szyny danych po zakończeniu impulsu zapisu.
Wartości tych parametrów (nominalne i minimalne) zależą od szybkości mikrokontrolerów, czyli od
maksymalnej częstotliwości zegara oraz od czasu dostępu do pamięci. Mają one znaczenie wtedy,
gdy wykorzystywana jest zewnętrzna pamięć danych i programu. Przy współpracy z pamięciami
wewnętrznymi instrukcje tego typu są wykonywane z maksymalną szybkością, w ciągu zaledwie
jednego cyklu zegara. Wykonanie instrukcji wielobajtowych przebiega w bardziej skomplikowany
sposób.
Przykładem takiej instrukcji może być operacja: (A) <- (A) + #dana, oznaczająca dodanie do
akumulatora natychmiastowego argumentu zapisanego w pamięci programu. Jeśli dla uproszczenia
przyjmiemy, że akumulator i stała natychmiastowa są 8-bitowe, to instrukcja wymaga dwukrotnego
dostępu do pamięci programu w celu pobrania rozkazu i argumentu. Czynności układu sterowania
133
podczas pobierania instrukcji z pamięci i jej wykonania mogą być zapisane symbolicznie w
następujący sposób:
(IR)
<M(PC)
;pobranie słowa rozkazowego
(PC)
<(PC)+1
;inkrementacja licznika programu
B(ALU) <M(PC)
;pobranie argumentu #dana
(PC)
<(PC)+1
;inkrementacja licznika programu
(A)
<ALU+
;wykonanie dodawania
gdzie B(ALU) oznacza zawartość rejestru przejściowego ALU (bufora), natomiast ALU+ oznacza
stan wyjść ALU przy wysterowaniu jednostki arytmetyczno-logicznej w sposób odpowiadający
operacji dodawania.
Jako przykład instrukcji trzybajtowej rozważmy operację: (A) <- (A) + M(adres), gdzie symbol
adres oznacza dwubajtowy adres bezpośredni.
Instrukcja ta wymaga trzykrotnego dostępu do pamięci, zgodnie z zapisem symbolicznym:
(IR)
<M(PC)
;pobranie słowa rozkazowego
(PC)
<(PC)+1
;inkrementacja licznika programu
(RAH) <M(PC)
;załadowanie bardziej znaczącego bajtu adresu
(PC)
<(PC)+1
;inkrementacja licznika programu
(RAL)
<M(PC)
;załadowanie mniej znaczącego bajtu adresu
(PC)
<(PC)+1
;inkrementacja licznika programu
B(ALU) <M(RA)
;załadowanie dodajnika do rejestru przejściowego
(A)
<ALU+
;wykonanie dodawania
Symbole RAL i RAH oznaczają odpowiednio mniej i bardziej znaczący bajt 16-bitowcgo rejestru
adresowego RA, przy czym założono, że drugi bajt kodu instrukcji zawiera bardziej znaczący bajt
adresu. W nowoczesnych mikrokontrolerach transmisja z/do pamięci (również zewnętrznych) może
się odbywać nie tylko bajtami, ale również słowami, a niekiedy nawet podwójnymi słowami.
Przedstawiony powyżej cykl pracy układu sterowania jest wtedy prostszy, faza wykonania wymaga
bowiem tylko jednego dostępu do nieci programu.
Czas wykonywania instrukcji przyjęto określać podając liczbę cykli maszynowych potrzebnych do
jej realizacji.
Przez cykl maszynowy rozumie się sekwencję cykli zegara potrzebnych do realizacji
pojedynczego odwołania do pamięci lub układu wejścia/wyjścia.
Cykl instrukcyjny (nazywany niekiedy cyklem rozkazowym) składa się z kilku kolejno
następujących cykli maszynowych.
Zwykle tworzy on sekwencję następujących cykli maszynowych:
- cykl pobrania rozkazu,
- cykl (bądź cykle) pobrania argumentów,
- cykl zapisu wyniku.
Pojęcie cyklu maszynowego stopniowo wychodzi jednak z użycia. Powodem jest to, że
standardową architekturę mikrokontrolera w swojej czystej, podstawowej postaci stosuje się coraz
rzadziej. Współczesne procesory wykorzystują bardziej zaawansowane warianty architektoniczne,
które umożliwiają jednoczesne wykonywanie faz instrukcji, nawet ciągu kolejnych instrukcji. Czas
wykonania instrukcji jest w tej sytuacji określany przez liczbę cykli zegara. Wykonanie większości
stawowych instrukcji zajmuje tylko jeden cykl zegara.
Cykl maszynowy mikrokontrolera 8051 składa się z sześciu stanów oznaczonych S1 do S6. Każdy
ze stanów trwa dwa okresy sygnału taktującego, oznaczonych jako fazy P1 i P2. Wynika z tego, że
czas trwania cyklu maszynowego wynosi 12 taktów zegara, co dla częstotliwości rezonatora równej
12MHz daje czas 1us. Czas wykonywania instrukcji wynosi jeden, dwa lub cztery cykle
maszynowe, w zależności od instrukcji. Na rysunku 5.39 przedstawiono cztery różne cykle
rozkazowe dla czterech różnych instrukcji.
134
Przebieg a) przedstawia cykl rozkazowy instrukcji jednobajtowej wykonywanej w pojedynczym
cyklu maszynowym,
przebieg b) przedstawia przypadek wykonywania instrukcji dwubajtowej wykonywanej w
pojedynczym cyklu maszynowym,
przebieg c) obrazuje wykonanie instrukcji jednobajtowej wykonywanej w ciągu dwóch cykli
maszynowych.
Rysunek 5.39. Cykle rozkazowe dla różnych instrukcji
W związku z multipleksowaniem szyny adresowej A0-A7 i szyny danych, mikrokontroler musi
generować dodatkowy sygnał sterujący zewnętrznym buforem zatrzaskowym - tym sygnałem jest
ALE. Sygnał ten jest generowany podczas pobierania każdego słowa rozkazu dwukrotnie w
każdym cyklu maszynowym. Wyjątek stanowi rozkaz MOVX (oraz MOVC przy dostępie do
zewnętrznej pamięci programu) realizujący dostęp do pamięci zewnętrznej. Instrukcja ta jest
jednobajtowa, wykonywana w dwóch cyklach maszynowych. W pierwszym cyklu następuje odczyt
kodu instrukcji (pierwszy sygnał ALE) oraz ustawienie adresu żądanej komórki pamięci (drugi
sygnał ALE). W drugim cyklu maszynowym następuje odczyt/zapis szyny danych - nie może
wówczas wystąpić sygnał ALE, gdyż zniszczyłby on wcześniej ustawiony adres komórki pamięci
5.4.4. Przerwania i sytuacje wyjątkowe
Dotychczasowe milczące założenie, że mikrokontroler pracuje w pełni autonomicznie i jedynym
czynnikiem określającym jego pracę jest program zapisany w pamięci, nie jest zazwyczaj spełnione
w praktyce. Mikrokontroler współpracuje z rozmaitymi urządzeniami zewnętrznymi, które w
określonych sytuacjach wymagają obsługi ze strony mikrokontrolera. W systemach pracujących w
czasie rzeczywistym (ang. real-time) często definiuje się maksymalny dopuszczalny czas
oczekiwania urządzenia na obsługę.
Zapewnienie odpowiednio szybkiej reakcji mikrokontrolera na żądania obsługi zgłaszane przez
urządzenia zewnętrzne wymaga wprowadzenia mechanizmu przerywania programu wykonywanego
przez mikrokontroler. Na sygnał przerwania pochodzący z urządzenia zewnętrznego
mikrokontroler przerywa aktualnie wykonywany program i przechodzi do procedury obsługi
przerwania. Po jej zakończeniu mikrokontroler powinien powrócić do poprzednio
135
realizowanych czynności. Właściwa praca systemu wymaga zatem, by przed wystąpieniem do
obsługi przerwania zapamiętać stan mikrokontrolera oraz adres instrukcji, od której należy wznowić
program po zakończeniu obsługi przerwania.
Oprócz przerwań wywoływanych przez urządzenia zewnętrzne, mikrokontrolery obsługują w
podobnym trybie nadzwyczajne sytuacje zaistniałe w wyniku realizacji programu lub wynikłe ze
specyficznych warunków pracy bloków funkcjonalnych układu. Generalnie przerwania dzieli się
zwykle na cztery kategorie zdarzeń:
- sytuacje wyjątkowe (ang. exception interrupts),
- maskowalne przerwania sprzętowe (ang. event interrupts),
- przerwania programowe (ang. software interrupts),
- pułapki (ang. traps).
Do sytuacji wyjątkowych zalicza się zdarzenia o największym znaczeniu dla poprawnego
działania systemu, których obsługi nie można odłożyć na później.
Jest tak na przykład w przypadku wystąpienia operacji dzielenia przez zero (ang. divide-byzero exception) lub żądania obsługi przez urządzenie zewnętrzne przyłączone do wejścia
przerwań niemaskowalnych NMI (ang. non-maskable interrupt). Zgłoszenia pochodzące z tego
wejścia nie mogą być zablokowane (zamaskowane) w sposób programowy, skąd bierze się
nazwa przerwań tego typu. Sytuacje wyjątkowe są obsługiwane przez mikro-kontroler
niezwłocznie po skompletowaniu aktualnie realizowanego cyklu rozkazowego, niezależnie od
priorytetu, który ma wykonywany program.
Przerwania maskowalne są generowane przez urządzenia peryferyjne, zarówno
wbudowane w scalony układ mikrokontrolera, jak i przyłączone do niego z zewnątrz. Mogą
być blokowane (maskowane) programowo przez ustawienie specjalnego bitu (bądź bitów)
nazywanego maską przerwań. Bit lub bity maski są zwykle umieszczone w rejestrze wskaźników
lub w wydzielonym rejestrze specjalnym SFR. Zgłoszenia przerwań tego typu mogą pochodzić na
przykład od układu transmisji UART, liczników lub urządzeń zewnętrznych. Większość
współczesnych mikrokontrolerów umożliwia nadawanie określonym źródłom przerwań
priorytetów, według których ustalana jest kolejność obsługi przerwań.
Przerwania programowe w rozbudowanych mikrokontrolerach również wykorzystują
system priorytetowej obsługi. Są wywoływane przez umieszczenie w programie rozkazu
przerwania, a więc wynikają z intencji programisty, a nie z nieprzewidywalnych, często
losowych zdarzeń zachodzących w otoczeniu mikrokontrolera. W zaawansowanych metodach
programowania przerwania programowe są wykorzystywane do manipulowania priorytetem
fragmentów kodu programu.
Pułapki, podobnie jak przerwania programowe, są rezultatem umieszczenia w programie
odpowiedniego rozkazu, w tym przypadku rozkazu TRAP. Od przerwań programowych różnią
się przeznaczeniem. Najczęściej są używane do śledzenia wykonywania programu w fazie jego
testowania.
Program nadzorujący śledzenie definiuje w wybranych punktach testowanego programu punkty
zatrzymań (ang. breakpoints) i wstawia w te miejsca rozkazy generowania pułapek. Procedura
obsługi przerwania (pułapki) polega w tym przypadku najczęściej na wyprowadzeniu zawartości
rejestrów i wybranych obszarów pamięci. Pułapki są też przydatne jako wygodny mechanizm
wywoływania procedur globalnych, dostępnych w całym programie, oraz do tworzenia
oprogramowania, które może pracować w dwóch trybach: systemowym i użytkownika.
Można wyróżnić następujące systemy przerwań:
- system przerwań z programowym przeglądaniem urządzeń,
- system przerwań z automatyczną detekcją źródła przerwania
- system przerwań wektoryzowany.
Przykładowy system przerwań z programowym przeglądaniem urządzeń pokazano na rys. 5.40.
136
Rysunek 5.40. Schemat układu przerwań mk PIC16F873
Każde urządzenie wewnętrzne jest wyposażone w przerzutnik służący do zapamiętania stanu
urządzenia – zawiera flagę przerwania (np. INTF – flaga przerwania zewnętrznego). Żądanie
przerwania powoduje ustawienie przerzutnika, czyli tej flagi. Każdemu przerwaniu może być
przypisana maska (np. INTE). Gdy jest ona ustawiona i nastąpi zgłoszenie przerwania - ustawienie
flagi przerwania, to do jednostki centralnej jest przekazywany sygnał przerwania, o ile globalna
maska przerwań (GIE) jest ustawiona. W tym systemie jednostka centralna nie zna źródła
(przyczyny) przerwania. Najczęściej obsługa wszystkich przerwań jest pod jednym wspólnym
adresem (np. 04h). Zatem jednostka centralna musi programowo przejrzeć (przepytać) wszystkie
urządzenia tak, jak przy programowym testowaniu stanu urządzeń, z tą różnicą, iż wykonuje ona tę
czynność tylko w trakcie obsługi przerwania. Również i tutaj kolejność priorytetu przerwań zależy
od przyjętej kolejności odpytywania. W tym systemie przerwań flagi poszczególnych przerwań nie
są kasowane sprzętowo przy wejściu w obsługę przerwań, zatem należy je kasować programowo w
trakcie ich obsługi. Zaletą tego systemu przerwań jest prostota struktury sprzętowej potrzebnej do
jego realizacji. Jego główną wadą jest długi czas potrzebny na identyfikację źródła przerwania.
Tablica 5.3. Zestawienie wektorów przerwań mk AT89C52
Najbardziej zaawansowanym i często stosowanym w mk jest system przerwań wektoryzowanych.
W systemie tym na sygnał potwierdzenia przyjęcia przerwania przez to urządzenie, które zgłosiło
przerwanie, podaje na szynę danych kod identyfikacyjny, który jest traktowany jako numer
elementu w wektorze przerwań. Zatem każdemu przerwaniu przypisany jest adres obsługi
przerwania w pamięci programu (np. tablica 5.3).
137
W przedstawionym przykładzie występuje 6 różnych źródeł przerwań:
- PT0, PT1 – przerwania od licznika T0 lub od licznika T1
- PS – przerwanie od portu szeregowy
- PX0, PX1 - przerwanie od zewnętrznych wejść INT0 lub INT1
- TF2, TXF2 – przerwanie od dodatkowych układów występujących w wersji AT89C52.
Przerwania te mogą zostać odblokowane poprzez ustawienie bitu o wartości 1 w odpowiadającym
temu przerwaniu bicie sterującym znajdującym się w rejestrze specjalnym sterującym systemem
przerwań. W rejestrze tym znajduje się również bit EA włączający globalnie cały system przerwań
(patrz rysunek).
Rejestr IE: Adres: A8H
EA
-
-
ES
ET1
EX1
ET0
EX0
Rysunek 5.41. Rejestr IE
W tym systemie każdemu przerwaniu jest przypisany na stałe priorytet. Jeżeli pojawi się w tym
samym czasie kilka przerwań to najpierw obsługiwane jest to o najwyższym priorytecie, a następnie
według ważności priorytetów kolejne przerwania. Często przerwanie o wyższym priorytecie może
przerwać obsługę przerwania o niższym (nigdy nie odwrotnie). Istnieje również możliwość zmiany
kolejności priorytetów. Służy do tego celu rejestr poziomu priorytetów, np. rejestr IP dla 80C51:
Rejestr IP: Adres: B8H
-
-
PT2
PS
PT1
PX1
PT0
PX0
Rysunek 5.42. Rejestr IP
Gdzie:
- PT0, PT1 – liczniki/timery 0 oraz 1
- PS - port szeregowy
- PX0, PX1 - przerwanie zewnętrzne z wejścia INT0 lub INT1
Ustawienie w rejestrze IP znacznika dla danego źródła przerwania powoduje, że przerwanie to
osiąga wyższy priorytet od przerwań, dla których znaczniki mają stan 0. Natomiast wzajemna
relacja pomiędzy źródłami przerwań, których znaczniki mają ten sam stan, nie ulega zmianie.
Zatem do obsługi przerwań przeważnie używane są trzy rejestry: rejestr z flagami przerwań, z
maskami poszczególnych przerwań i maską globalną oraz rejestr poziomu priorytetów. W tym
systemie flagi przerwań są zerowane sprzętowo przez obsługę przerwań.
W mk 80C51 w przypadku jeżeli równocześnie wystąpi więcej przerwań niż jedno o takim samym
priorytecie, są one obsługiwane w następującej kolejności: IE0, TF0, IE1, TF1, RI oraz TI.
138
Rysunek 5.43. Rejestr IE mk 80C51
Rysunek 5.44. Rejestr IP mk 80C51
139
Rysunek 5.45. System kontroli wejść mk 80C51
5.4.5. Tryby redukcji mocy mikrokontrolera
Wszystkie współczesne mikrokontrolery mogą w czasie pracy wykonywać działania z normalną
szybkością lub też mogą znajdować się w jednym z kilku stanów charakteryzujących się obniżonym
poborem mocy.
Właściwość ta jest szczególnie ważna, gdy mikrokontroler jest zasilany z baterii i musi pracować w
czasie wielomiesięcznych, a nawet wieloletnich sesji, na przykład podczas misji kosmicznych.
W stanie uśpienia (ang. sleep mode, idle mode) wykonywanie programu jest zatrzymane, pracuje
natomiast zegar i niektóre urządzenia peryferyjne. Pobór mocy jest przy tym mniejszy od
nominalnego około 2-10 razy. Wyprowadzenie mikrokontrolera ze stanu uśpienia następuje po
sygnale RESET, zewnętrznym sygnale przerwania lub gdy wystąpi błąd adresu DMA albo też błąd
identyfikacji źródła przerwania.
Drugi ze stanów obniżonego poboru mocy jest nazywany stanem czuwania (ang. stand-by mode,
power-down mode). W stanie tym zegar jest wyłączony, a mikrokontroler pobiera minimalną moc
potrzebną do podtrzymania zawartości wewnętrznej pamięci i rejestrów. Zazwyczaj prąd potrzebny
do tego celu nie przekracza kilkudziesięciu mikroamperów. Wyprowadzenie mikrokontrolera ze
stanu czuwania odbywa się na sygnał przerwania zewnętrznego lub na sygnał RESET.
Kolejnym sposobem redukcji poboru mocy jest zastosowanie dwóch oscylatorów. Jeden pracuje z
maksymalną częstotliwością – główny oscylator – (np. 10MHz lub 40MHz), drugi z częstotliwością
niską np. 32,768 kHz. Przejście z wysokiej do niskiej częstotliwości powoduje spadek pobieranej
mocy o około trzy rzędy. Np. Rabbit 2000.
Innym sposobem jest dzielenie podstawowego sygnału zegara przed przekazaniem do dalszych
układów mikrokontrolera. Tego typu rozwiązanie zastosowane zostało w np. DS87C530.
Sieć dystrybucji sygnałów zegarowych umożliwia również odłączanie od sygnału zegarowego jc,
jak i urządzeń peryferyjnych lub wręcz wstrzymanie pracy oscylatora. Stąd mk może znaleźć się w
następujących specjalnych trybach pracy:
- tryb pełnej aktywności (RUN),
- tryb, w którym nie pracuje procesor, a pracują wszystkie urządzenia peryferyjne (WAIT lub
SLEEP) – inaczej tryb uśpienia,
140
-
tryb, w którym nie pracuje procesor, a pracują niektóre urządzenia peryferyjne (układ
przerwań, porty równoległe, przetworniki A/C zasilane zewnętrznym sygnałem zegarowym),
tryb pełnego wstrzymania (zamrożenia) pracy mk – zatrzymany układ oscylatora, zatem żadne
urządzenie nie pracuje, stan rejestrów i pamięci RAM jest „zamrożony” (STOP lub HALT).
Rysunek 5.46. Fragment schematu blokowego mk Rabbit 2000
Mikroprocesor 80C51 nie używa bardzo rozbudowanych metod redukcji mocy. Pozwala na
wprowadzenie w stan HALT oraz IDLE.
Od sterowania trybem pracy wykorzystuje się jeden z rejestrów specjalnych o nazwie PCON.
Rysunek 5.47. Rejestr PCON mk 80C51
W trybie IDLE działają wszystkie układy peryferyjne co pozwala mikrokontrolerowi na wyjście z
tego stanu w przypadku przyjęcia przerwania. W trybie HALT układy peryferyjne są również
wyłączone, a wprowadzenie mikrokontrolera w tryb normalnej pracy wiąże się z podaniem sygnału
reset.
5.5. Architektura systemu pamięci mikroprocesora
Architektura podsystemu pamięci ma duży wpływ na projektowanie i programowanie
systemów cyfrowych z mikrokontrolerami. Ze względu na to, że część pamięci mieści się wewnątrz
scalonego układu mikrokontrolera, a część jest dołączana z zewnątrz, budowa i działanie tego
141
podsystemu jest na ogół bardziej skomplikowane niż w przypadku konwencjonalnych systemów
mikroprocesorowych.
W zależności od typu, mikrokontroler może być wyposażony w kilka rodzajów wbudowanej
pamięci wewnętrznej.
Ze względu na technologię wykonania pamięci jak już wspomniano we wcześniejszym
rozdziale dzieli się na sześć podstawowych odmian:
- pamięć RAM (ang. random access memory) - może być zarówno odczytywana, jak i
zapisywana przez CPU. Zawartość pamięci jest podtrzymywana tak długo, jak długo jest
włączone zasilanie układu. Rozróżnia się statyczne i dynamiczne pamięci RAM.
W mikrokontrolerach stosuje się również wbudowane statyczne pamięci RAM z
podtrzymywaniem bateryjnym (ang. battery backed-up static RAM). Pamięci
dynamiczne są zwykle używane jako zewnętrzne pamięci RAM.
- Pamięć ROM (ang. read-only memory) może być tylko odczytywana. Zawartość pamięci jest
określona na stałe podczas procesu produkcji. Pamięci tego typu są używane jako
wewnętrzna pamięć programu do przechowywania kodu firmowego oprogramowania
dostarczanego wraz z mikrokontrolerem (ang. firmware). Oprogramowanie to zawiera
najczęściej procedury diagnostyczne oraz program do ładowania, uruchamiania i
nadzorowania programów użytkownika, zwany monitorem.
Rozróżnia się pamięci OTP (ang. one time programmable), EPROM (ang. erasable
programmable ROM), EEPROM (ang. electrically erasable PROM), FLASH (ang. bulk
erasable non-volatile memory).
Pamięć EPROM (ang. erasable programmable ROM) służy do przechowywania programów i
danych użytkownika. Zawartość pamięci może być zmieniana przez skasowanie poprzedniej
zawartości i wpisanie nowej. Operacja ta wymaga zwykle wyjęcia układu z podstawki. Kasowanie
przeprowadza się naświetlając pamięć promieniami ultrafioletowymi, natomiast programowanie
odbywa się w sterowanym przez komputer programatorze, przy użyciu napięcia o wartości równej
kilkanaście woltów. Liczba cykli kasowania-programowania jest ograniczona. Podobnie jak pamięć
ROM, pamięć EPROM jest nieulotna, to znaczy po wyłączeniu zasilania zachowuje swoją
zawartość.
Pamięć jednokrotnie programowalna OTP (ang. one time programmable) ma budowę
identyczną jak EPROM, ale proces programowania można wykonać tylko jeden raz. W odróżnieniu
od pamięci EPROM, których obudowy są wyposażone w okno z kwarcu umożliwiające kasowanie
w ultrafiolecie, pamięci OTP nie mają takiego okienka, nie mogą być więc kasowane. Ściślej
biorąc, zawartość zaprogramowanej pamięci OTP można modyfikować, ale tylko przez zmianę
jedynek na zera. Zaprogramowane wcześniej zera nie mogą być już przeprogramowane na jedynki.
Pamięć EEPROM (ang. electrically erasable PROM) może być przeprogramowana
elektrycznie, bez potrzeby kasowania ultrafioletem. Jest pamięcią nieulotna, stosowaną do
przechowywania programów i danych. Wadą pamięci tego typu jest długi czas zapisu wynoszący
zwykle od kilkuset nanosekund do około l milisekundy. Liczba cykli zapisu-kasowania jest
ograniczona i wynosi typowo 10 000.
Pamięć błyskowa FLASH (ang. bulk erasable non-volatile memory) ma cechy podobne do
pamięci EEPROM. Jest nieulotna i może być przeprogramowana elektrycznie. W porównaniu z
pamięcią EEPROM jest szybsza i zapewnia zwykle większą liczbę cykli zapisu-kasowania. Jest
stosowana jako pamięć wewnętrzna lub zewnętrzna w nowoczesnych mikrokontrolerach. Ważną
zaletą pamięci błyskowej jest możliwość szybkiego kasowania wybranych sektorów pamięci lub
całej jej zawartości.
Ten sam podstawowy typ mikrokontrolera jest zazwyczaj produkowany w wielu odmianach
różniących się między innymi rodzajami i pojemnością wbudowanych pamięci. Niektóre bardziej
popularne typy mikrokontrolerów są dostępne nawet w kilkudziesięciu różnych wersjach. W tablicy
142
5.4 przedstawiono dla przykładu zestawienie pojemności wbudowanej pamięci w podstawowych
odmianach mikrokontrolerów rodziny 8051. Symbolem SRAM oznaczono statyczną pamięć RAM
(ang. static RAM) używaną jako szybka, wewnętrzna pamięć danych.
Tablica 5.4. Wybrane wersje mikrokontrolerów x51
Niektóre odmiany tego mikrokontrolera zawierają ponadto wydzielony, specjalizowany układ TPU
(ang. timing processor unii) do operacji w czasie rzeczywistym. Jest on wyposażony we własną
pamięć RAM o pojemności 2 kB.
Wybierając typ mikrokontrolera do konkretnej aplikacji należy pamiętać, że wielkość
wewnętrznej pamięci ma wpływ nie tylko na koszt układu, ale również na pobór mocy. Nie należy
zatem stosować niepotrzebnie zbyt dużej, niewykorzystywanej w praktyce pamięci, zwłaszcza w
układach zasilanych bateryjnie.5.5.1. Mapy pamięci mikroprocesorów
Dla projektanta systemu, a także dla programisty piszącego oprogramowanie użytkowe
mikrokontrolera ważny jest nie tylko rozmiar i rodzaj pamięci wewnętrznej oraz zewnętrznej, ale
także rozmieszczenie poszczególnych pamięci w przestrzeni adresowej jednostki centralnej.
Rozmieszczenie to opisuje się najczęściej w wygodnej postaci graficznej nazywanej mapą pamięci
(ang. memory map). Oprócz adresów obszarów RAM, ROM i innych rodzajów pamięci mapa
pamięci podaje także usytuowanie rejestrów uniwersalnych, adresów procedur obsługi przerwań,
rejestrów specjalnych (SFR) oraz rejestrów układów wejścia/wyjścia. Kompletna, poprawnie
zbudowana mapa pamięci powinna jednoznacznie określać adresy wszystkich obiektów dostępnych
dla jednostki CPU i realizowanych przez nią programów.
Najprostszą strukturę mają mapy pamięci w systemach z jednolitą przestrzenią adresową, w których
wszystkie pamięci, rejestry i układy wejścia/wyjścia są umieszczone w jednej, wspólnej przestrzeni
adresowej. Koncepcja jednolitej przestrzeni adresowej ma ważne odniesienie do architektury
mikrokontrolera. Zakłada ona mianowicie, że podział przestrzeni adresowej na pamięć programu,
pamięć danych oraz obszar wejścia/wyjścia jest czysto umowny i zależy wyłącznie od
rozmieszczenia tych elementów w obszarze adresowym podczas projektowania systemu.
Architektura tego rodzaju jest nazywana architekturą Von-Neumanna, od nazwiska wybitnego
matematyka amerykańskiego (pochodzenia węgierskiego), który pierwszy podał teoretyczne
143
podstawy budowy komputerów. Komputer (procesor) Von-Neumanna ma jedną szynę danych
wspólną dla danych i programu, a podział obszaru pamięci na dane i program jest umowny.
Mikrokontroler z rysunku 5.3 ma właśnie taką architekturę, choć zaznaczono na nim oddzielne
bloki pamięci danych i programu. Rozdziału tego dokonano jednak wyłącznie dla pokazania
typowej organizacji (czyli implementacji) mikrokontrolera, natomiast na poziomie opisu
architektury, czyli sposobu funkcjonowania procesora, obie pamięci mogą być używane zamiennie,
jeśli są tylko odpowiedniego rodzaju (RAM, ROM itp.).
Na rysunku 5.48 przedstawiono w uproszczeniu typową mapę pamięci mikro-kontrolera z jednolitą
przestrzenią adresową. Pominięto na nim wartości adresów przypisanych początkom każdego z
cząstkowych obszarów przestrzeni adresowej oraz przyjęto przykładowe usytuowanie tych
obszarów, które dla konkretnych typów mikrokontrolerów może być nieco inne. Liczba znaków
szesnastkowych (tetrad bitów) użyta do opisu adresów zależy oczywiście od liczby bitów szyny
adresowej mikrokontrolera.
Rysunek 5.48. Przykładowa struktura mapy pamięci mikrokontrolera z jednolitą przestrzenią adresową
Pierwsze 256 bajtów przestrzeni adresowej ma szczególnie ważne znaczenie, dostęp bowiem do
tego fragmentu pamięci może się odbywać przy użyciu krótkich, 8-bitowych adresów
bezpośrednich. W obszarze tym umieszcza się zatem najczęściej używane obiekty, a więc rejestry
uniwersalne, podręczną pamięć danych i stos, o którym więcej nieco później. Usytuowanie
pozostałych elementów w wewnętrznym obszarze adresów nic jest już tak krytyczne. Zewnętrzna
przestrzeń adresowa jest wykorzystywana opcjonalnie, jeśli w konkretnej aplikacji wewnętrzna
pamięć ma niewystarczającą pojemność lub gdy w fazie uruchamiania systemu łatwiej jest
modyfikować programy i dane ulokowane poza mikrokontrolerem. Zazwyczaj nawet wtedy pewna
część zewnętrznej przestrzeni adresowej pozostaje nie wykorzystana.
Planując mapę pamięci należy pamiętać, że dostęp do pamięci wewnętrznej jest szybszy niż do
pamięci zewnętrznej. Często używane procedury i dane należy zatem, jeśli to tylko możliwe,
lokować wewnątrz układu mikrokontrolera.
144
Architektura Von-Neumanna z jednolitą przestrzenią adresową wyróżnia się pro-i przejrzystością.
Programowanie jest ułatwione, dostęp bowiem do danych, programu i urządzeń wejścia/wyjścia
odbywa się przy użyciu zunifikowanych rozkazów wykorzystujących te same tryby adresowania.
Architekturę tego typu najszerzej stosuje w prostych mikrokontrolerach firma Motorola.
Niestety, elegancka struktura procesora Von-Neumanna ma również wady. Najważniejszą jest
powolna realizacja cyklu rozkazowego, co wynika z wykorzystywania wspólnej szyny do pobierania
rozkazów i danych. Z tego powodu większość współczesnych mikrokontrolerów wykorzystuje
bardziej złożoną architekturę, nazywaną architekturą harwardzką (ang. Harvard architecture).
Opiera się ona na użyciu dwóch oddzielnych szyn dla danych i rozkazów, dzięki czemu w trakcie
pobierania argumentów wykonywanej właśnie instrukcji można równocześnie zacząć pobieranie
następnego słowa rozkazowego (ang. pre-fetch). W procesorach tego typu obszary adresowe
pamięci danych i programu, a także pamięci wewnętrznej i zewnętrznej nie są już jednolite, jak
pokazano na rysunku 5.49.
Rysunek 5.49. Uproszczona przykładowa mapa pamięci mikrokontrolera o architekturze harwardzkiej
Zróżnicowane obszary adresowe dla pamięci danych i programu oraz pamięci wewnętrznej i
zewnętrznej pociągają za sobą niejednoznaczność adresów. W przykładowej mapie z rysunku 2.22
jednostka centralna „widzi" pod adresem 0...00H cztery różne obiekty: wewnętrzną pamięć
programu, zewnętrzną pamięć programu oraz zewnętrzną i wewnętrzną pamięć danych. By uniknąć
tych niejednoznaczności konieczne staje się zatem stosowanie innych rodzajów rozkazów przy
dostępie do poszczególnych obszarów pamięci, albo zróżnicowanych trybów adresowania.
Prześledźmy to na przykładzie odwołań do pamięci danych. Załóżmy, że chcemy pobrać do
akumulatora zawartość komórki o adresie 00H z wewnętrznej pamięci danych. W typowym
mikrokontrolerze instrukcja realizująca takie przesłanie ma postać:
MOV
A,00H
przy czym mnemonik (kod mnemotechniczny) zapisany jako MOV jest skrótem od angielskiego
słowa move (przesuń, przemieść). Użyto bezpośredniego adresu 8-bitowego. Jeżeli natomiast
chcemy wykonać takie przesłanie, ale z komórki zewnętrznej pamięci danych o adresie 00H, należy
najpierw do rejestru R0 wpisać liczbę 00H, a następnie zastosować instrukcję:
MOVX
A,@R0
Symbol @ (czyt. at) oznacza tu adresowanie pośrednie zawartością rejestru RO. Jak widać,
zastosowano rozkaz o innym mnemoniku (MOVX - MOVe eXternal) oraz inny tryb adresowania.
Jeszcze innych odmian rozkazu MOV i innych trybów adresowania należałoby użyć przy dostępie
do pamięci programu.
145
Przytoczony przykład pokazuje, że architektura harwardzka znacznie komplikuje programowanie
mikrokontrolera, wymaga bowiem operowania rozmaitymi odmianami rozkazów i trybów
adresowania.
5.5.2. Segmentacja pamięci
Innego rodzaju problemy powstają wtedy, gdy chcemy, by mikrokontroler miał dużą przestrzeń
adresową. Używany przez nas dotąd mechanizm adresowania, nazywany adresowaniem liniowym,
staje się bowiem nieefektywny. Przy adresowaniu liniowym adres podany w instrukcji jest
kompletnym, fizycznym adresem komórki pamięci. Jego długość wynika zatem z rozmiaru
przestrzeni adresowej. Na przykład dla przestrzeni równej 64 k adres ma 16 bitów, natomiast dla
przestrzeni 1M potrzebny jest już adres 20-bitowy. Bardzo duże przestrzenie adresowe wymagają
więc długich adresów liniowych. Kod instrukcji i czas jej wykonania stają się zatem dłuższe.
Ponadto we współczesnych systemach mikroprocesorowych bardzo ważna jest ochrona (protekcja)
pamięci przed niepowołanym dostępem. Dotyczy to zwłaszcza systemów wielozadaniowych, które
dopuszczają równoczesne rezydowanie w pamięci i współbieżne wykonywanie wielu zadań
(programów). Z potrzebą protekcji mamy również do czynienia w systemach jednozadaniowych. W
tym przypadku istotna jest ochrona obszaru programu, danych i stosu przed wzajemną interferencją.
Wymienione problemy rozwiązuje segmentacja pamięci, która polega na podziale obszaru pamięci
na mniejsze fragmenty nazywane segmentami. Długość segmentu zależy od typu mikrokontrolera,
ale najczęściej stosuje się segmenty o długości 64 k. W najprostszej wersji segmentacji liczba i
usytuowanie segmentów w przestrzeni adresowej są stałe. W pełnej wersji system ten pozwala
natomiast swobodnie definiować położenie segmentów przy użyciu rejestrów segmentów (ang.
segment registers), które podają adresy początków segmentów (adresy bazowe). W praktyce
najczęściej wymaga się, by segment zaczynał się od adresu podzielnego przez 2k (k = 1,2,...). Jeśli
przyjmiemy ; = 4, początki segmentów będą przypadać przy adresach podzielnych przez 16, to
znaczy że końcowe cztery bity adresów początków segmentów będą zawsze zerami. Dzięki temu
zamiast pamiętać cały adres początku segmentu, można pominąć mniej znaczące cztery bity.
Adres efektywny przy segmentacji pamięci oblicza się zawsze jako sumę dwóch składników:
przesuniętej o k bitów w lewo zawartości odpowiedniego rejestru segmentu i adresu wewnątrz
segmentu, nazywanego przesunięciem (ang. offset, displacement).
Jeśli teraz przyjmiemy, że określone grupy instrukcji współpracują tylko z określonym segmentem,
np. tylko z segmentem kodu programu (ang. code segment) lub tylko z segmentem danych (ang.
data segment), to w części adresowej instrukcji wystarczy podawać tylko przesunięcie.
Jednocześnie mamy zatem rozwiązany problem protekcji i długości adresów. Ilustrację segmentacji
pamięci podano na rysunku 5.50.
146
Rysunek 5.50. Obliczanie adresu efektywnego w systemie z segmentacją pamięci
Dodatkową korzyścią z segmentacji jest możliwość łatwej realizacji pamięci wirtualnej (ang. virtual
memory). Koncepcja ta polega na tym, że w danej chwili w rzeczywistej (fizycznej) pamięci
przebywa tylko część programu i danych, natomiast reszta jest ulokowana na innym nośniku (np. w
pamięci dyskowej). W zależności od potrzeb, do pamięci fizycznej sprowadzane są kolejne porcje
kodu i danych, stwarzając wirtualne wrażenie dysponowania dużą pamięcią fizyczną. Podział
pamięci na mniejsze fragmenty jest niezbędny, by móc tę koncepcję zrealizować w praktyce.
Oprócz segmentacji stosuje się w tym celu podział pamięci na strony (ang. paging). Zagadnienie
pamięci wirtualnej i stronicowania dotyczy rozbudowanych mikrokontrolerów z procesorami klasy
embedded. Jego szersze omówienie można znaleźć w pracach dotyczących systemów operacyjnych
i architektury mikroprocesorów.
5.5.3. Stos
Wszystkie stosowane obecnie w mikrokontrolerach rodzaje pamięci półprzewodnikowych
umożliwiaj ą bezpośredni dostęp do komórki o podanym adresie. W pewnych przypadkach
wygodna jest jednak inna organizacja dostępu, nazywana stosem. Przypomnijmy, że pojęcie stosu
pojawiło się już wcześniej, przy omawianiu rejestrów mikrokontrolera. Wyróżniono tam rejestr SP,
który przechowuje adres szczytu stosu, w sposób pokazany na rysunku 5.51.
Rysunek 5.51. Stos: a) operacja zapisu, b)operacja odczytu
Obszar stosu jest fragmentem pamięci RAM, zapisywanym i odczytywanym zgodnie z algorytmem
LIFO (ang. Lasl-In First-Out). Przy zapisie kolejne bajty są umieszczane w komórkach o kolejnych
adresach, podobnie jak warstwy na stosie. Zawartość rejestru SP pokazuje adres szczytu stosu i po
każdym zapisie jest zwiększana o jeden. Przy odczycie informacje są „zdejmowane" ze stosu w
odwrotnej kolejności, przy czym odczyt każdego bajtu powoduje zmniejszenie zawartości rejestru
SP o jeden. Korzystając ze standardowych rozkazów zapisu i odczytu ze stosu (oznaczanych zwykle
odpowiednio przez PUSH i POP), nie można ominąć tej kolejności i dostać się do wnętrza stosu. W
trakcie wykonywania programu stos „pulsuje'', to znaczy jego obszar wzrasta lub maleje.
Rysunek 5.51 i podany wyżej komentarz dotyczą stosu, który rozbudowuje się w stronę
wzrastających adresów. Konwencję tę stosuje większość producentów mikrokontrolerów, można
jednak spotkać i takie typy, w których stos rozbudowuje się w stronę malejących adresów. Kierunek
rozbudowywania się stosu jest ważny o tyle, że programista powinien zadbać, by stos miał
dostatecznie dużo miejsca w pamięci RAM i nic spowodował zniszczenia danych lub sytuacji
wyjątkowej. Po sygnale RESET przyjmowana jest ustalona wartość wskaźnika stosu (różna dla
147
różnych typów mikrokontrolerów). Programista może ją zmienić wpisując do rejestru SP inną
wartość. Stos jest wykorzystywany w trzech sytuacjach:
- do zapamiętywania stanu CPU przed przejściem do obsługi przerwań,
- do zapamiętywania adresu powrotu z podprogramów i procedur obsługi przerwań,
- do chwilowego zapamiętywania (chronienia) zawartości rejestrów i zmiennych w programie
użytkownika.
Jeśli programista korzysta ze stosu, powinien zbilansować liczbę operacji zapisu i od-w każdej
procedurze, w przeciwnym przypadku nastąpi zaburzenie mechanizmu automatycznego
zapamiętywania i odtwarzania adresów powrotu oraz stanu jednostki centralnej.
148
6. Dodatkowe bloki funkcjonalne mikrokontrolerów
Lista bloków funkcjonalnych mikrokontrolerów przedstawiona w poprzednich rozdziałach została
ograniczona tylko do tych zespołów, które są niezbędne do autonomicznej prac CPU. Pominięto
natomiast wszystkie inne, najczęściej opcjonalne bloki, zapewniając współpracę z otoczeniem.
Należą do nich:
- zespoły wejść i wyjść cyfrowych (porty),
- przetworniki analogowo-cyfrowe i cyfrowo-analogowe,
- bloki sterowania szynami i współpracą z pamięciami zewnętrznymi,
- liczniki, układy czasowe, modulatory szerokości impulsów itp.,
- zespoły obsługi przerwań,
- specjalizowane bloki transmisji danych w postaci szeregowej i równoległej.
6.1. Porty wejścia wyjścia
Do równoległej transmisji danych cyfrowych służą w mikrokontrolerach zespoły linii
wejścia/wyjścia nazywane portami równoległymi (ang. parallel ports lub I/O ports). W
przeważającej liczbie przypadków porty zawierają po 8 linii, mogą zatem transmitować dane
bajtami. Liczba portów i ich wyprowadzeń (ang. pins) jest ograniczona przez liczbę wyprowadzeń
obudowy mikrokontrolera. Wyróżnia się trzy rodzaje linii portów: dwukierunkowe (ang. quasibidirectional), z otwartym obwodem drenu tranzystora (ang. open drain), o zwiększonej
obciążalności (ang. push-pull output).
Najbardziej uniwersalne są linie dwukierunkowe, które mogą służyć zarówno jako wejście, jak
i wyjście sygnału bez potrzeby rekonfiguracji portu, to znaczy bez programowego przełączania
buforów.
Jest to możliwe dzięki temu, że przy stanie wysokim na wyjściu, linia zewnętrzna jest sterowana
małym prądem, umożliwiając urządzeniu zewnętrznemu na wprowadzenie końcówki w stan niski,
wpływając na kierunek transmisji. Natomiast jeśli wyjście jest w stanie niskim, jest sterowane w
taki sposób, że może przyjąć duży prąd z obwodów zewnętrznych.
Właściwość tę uzyskuje się stosując do sterowania linii trzy tranzystory w konfiguracji
pokazanej na rysunku 6.1. Tranzystor T2 jest włączany, gdy mikrokontroler ustawia na wyjściu stan
wysoki. Na nieobciążonym wyjściu jest wówczas stan logiczny “l”. Tranzystor T3 jest włączany
wtedy, gdy mikrokontroler wyprowadził na linię stan wysoki, a obciążone wyprowadzenie również
znajduje się w stanie wysokim. Zapewnia to odpowiedni prąd wyjściowy w stanie wysokim.
Obciążalność wyjścia w stanie wysokim pozwala na sterowanie przynajmniej kilkoma wejściami
TTL. Jeśli na linii ustawionej przez mikrokontroler w stan ,,1" został wymuszony z zewnątrz stan
niski, tranzystor T3 wyłącza się, natomiast tranzystor T2 pozostaje włączony.
Rysunek 6.1. Układ dwukierunkowej linii portu
Układ wymuszający z zewnątrz stan "0" musi w związku z tym przyjąć odpowiednio duży prąd.
Tranzystor Tl jest wykorzystywany do przyspieszenia przełączania linii przy przejściu z ,,0" na
149
,,1" . Tranzystor ten jest włączany na krótki czas (zwykle dwa okresy zegara) i skraca czas
narastania napięcia na wyjściu. Przedstawiona konfiguracja dwukierunkowej linii portu, aczkolwiek
prosta w realizacji, ma istotne wady. Najważniejszą z nich jest mały prąd wyjściowy, toteż linia ma
ograniczone zdolności sterowania układami przyłączonymi z zewnątrz. W szczególności nie nadaje
się do bezpośredniego sterowania baz tranzystorów n-p-n używanych powszechnie do zwiększania
prądu wyjściowego układów.
Innym rodzajem układów wyjściowych są układy z otwartym obwodem drenu, które są obciążane z
zewnątrz, zazwyczaj przez rezystory przyłączone do napięcia zasilania - Vcc. Zaletą takich linii jest
możliwość realizacji poza mikrokontrolerem funkcji "zwartego iloczynu" przez połączenie dwóch
lub większej liczby wyjść. Strukturę układu sterującego linią z otwartym obwodem drenu przedst.
na rys. 6.2.
Rysunek 6.2. Linia z otwartym obwodem drenu
Jeśli mikrokontroler musi sterować układami zewnętrznymi bezpośrednio, wymagana jest
zwiększona obciążalność wyjść portów, czyli większy prąd wyjściowy w stanie wysokim na
wyjściu. Najprostszą konfigurację wyjścia o takich właściwościach pokazano na rysunku 6.3.
Przedstawione odmiany sposobów sterowania linii portów są stosowane w mikrokontrolerach w
różny sposób. Dla przykładu, mikrokontrolery z rodziny x5l są wyposażone w cztery porty
oznaczone symbolami PO, Pl, P2 i P3. Wszystkie porty są dwukierunkowe, wyposażone w rejestr
zatrzaskowy danych wyjściowych i bufor danych wejściowych. Port PO, którego linie są sterowane
układami o strukturze przedstawionej na rysunku 6.4, nie ma wewnętrznego obciążenia obwodu
drenu tranzystora wyjściowego. Tranzystor FET umieszczony w tym obwodzie jest włączony tylko
wtedy, gdy na wyjściu linii mikrokontroler ustawił stan "l". W rezultacie wyjście zachowuje się jak
układ z otartym obwodem drenu.
Rysunek 6.3. Linia o zwiększonym prądzie wyjściowym
150
Rysunek 6.4. Praktyczna realizacja układu sterowania linią portu o zwiększonej obciążalności (port P0 w
mikrokontrolerze x51)
Zapis" l" do przerzutnika zatrzaskowego powoduj e wyłączenie obu tranzystorów i linia może
pracować jako wejście o dużej impedancji. W omawianym przykładzie wyjścia PO i P2 oraz
wejście PO są używane do współpracy z zewnętrznymi pamięciami. Port PO wyprowadza mniej
znaczący bajt adresu, multipleksowany z danymi, które mogą przepływać w dwóch kierunkach. Port
P2 wyprowadza bardziej znaczący bajt adresu, jeśli potrzebne są adresy 16-bitowe, lub służy jako
port wejścia/wyjścia.
Linie portu P3 spełniają podwójne funkcje. Mogą służyć do równoległej transmisji danych, ale
alternatywnie mogą być też wykorzystywane jako wejścia zgłoszeń przerwań, linie układu
transmisji szeregowej, linie strobu zapisu i odczytu zewnętrznej pamięci oraz linie wejściowych
impulsów napełniających liczniki wbudowane do mikrokontrolera. Alternatywne funkcje tych linii
są dostępne tylko wtedy, gdy do rejestru zatrzaskowego zostały wpisane stany" l ".
Rysunek 6.5. Linia portu z wewnętrznym obciążeniem (port P1 mikrokontrolera x51)
W przeciwnym przypadku stan linii jest niski, niezależnie od sterowania z zewnątrz. Rejestry
zatrzaskowe portów składają się z przerzutników typu D, które zatrzaskują stan na wewnętrznej
szynie danych. Stan rejestrów może być odczytywany, jeśli CPU wyśle sygnał odczytu rejestru.
Mikrokontroler ma zatem dwie możliwości odczytu portu: 1) rejestru zatrzaskowego oraz 2) stanu
wyprowadzenia sterowanego z zewnątrz jako wejście. Fakt ten często utrudnia zrozumienie
działania portów przez początkujących programistów, którzy nie rozróżniają obu operacji. W istocie
odczyt rejestru jest tylko "przypomnieniem" sobie przez program wartości, którą sam tam wcześniej
zapisał, natomiast odczyt stanu końcówek jest rzeczywistą operacją odczytu danych z portu
mikrokontrolera traktowanego jako wejście. Obie operacje są wykonywane przez różne instrukcje,
które należy właściwie stosować, w zależności od tego czy pożądany jest odczyt rejestru, czy też
151
stanu linii.
Rysunek 6.6. Linia portu ze sterowanym obciążeniem (port P2 mikrokontrolera x51)
Porty P0 i P2, ze względu na to, że w omawianym mikrokontrolerze służą również do przesyłania
adresów i danych przy współpracy z pamięciami zewnętrznymi, są wyposażone w odpowiednie
linie sterujące przełączaniem źródła informacji. Przełączanie to odbywa się przy użyciu
multiplekserów doprowadzających sygnał na bramkę tranzystora wyjściowego linii.
Rysunek 6.7. Linia portu z alternatywną funkcją (port P3 mikrokontrolera x51)
W rozważanym przypadku mikrokontrolerów rodziny x5l linie portów Pl, P2 i P3 mogą sterować
trzema wejściami TTL LS. Porty traktowane jako wejścia mogą być sterowane przez wyjścia z
otwartym kolektorem lub drenem, ale przełączanie linii ze stanu ,,0" do ,,1" jest relatywnie wolne.
Na rysunku 6.8 pokazano układ ilustrujący sterowanie linii portu przez obwód tranzystora TN z
otwartym drenem. Pojemność pasożytnicza obciążająca wejście jest równa typowo około 100 pF.
152
Rysunek 6.8. Warunki sterowania linii portu przez tranzystor z otwartym drenem
Dynamiczna analiza procesów przełączania linii portów ma znaczenie w systemach sterowania
w czasie rzeczywistym, kiedy często wymaga się, aby czasy przełączania nie przekraczały zadanych
wartości krytycznych. Niekiedy ważna jest również stromość zboczy sygnału. Parametry te są
podawane w katalogach jako wartości maksymalne i typowe. Niektóre mikrokontrolery są
wyposażone w specjalne, szybkie układy wejścia/wyjścia, dla których czas przełączania, zarówno ze
stanu ,,0" do stanu "l ", jak i odwrotnie jest bardzo krótki i wynosi kilkaset nanosekund. W
przypadku standardowych mikrokontrolerów czas przełączania może być o rząd wielkości dłuższy.
Rysunek 6.9. Przełączenie linii portu mikrokontrolera x51 ze stanu „0” do stanu”1”
Na rysunku 6.9 przedstawiono typowy przebieg przełączania linii portu ze stanu niskiego do
wysokiego odniesiony do układu z rysunku 6.8. W obszarze oznaczonym literą A pojemność
obciążenia jest ładowana tylko przez tranzystor T2. Po upływie około 5 us napięcie na
wyprowadzeniu osiąga wartość 2V. W obszarze B włącza się tranzystor T3 i szybkość ładowania
wzrasta około l0-krotnie. Mimo to napięcie wyjściowe osiąga wartość zbliżoną do V cc dopiero po
około 10 us. Podany przykład wskazuje, że od chwili wysłania do portu danych do chwili ustalenia
się na wyprowadzeniach odpowiednich napięć może upłynąć nawet kilkadziesiąt cykli zegara.
6.2. Układy licznikowe/czasowe
Współpraca mikrokontrolera z otoczeniem w czasie rzeczywistym wymaga odliczania czasu lub
generowania złożonych sekwencji binarnych. Jest to realizowane przez specjalizowane bloki
nazywane licznikami (ang. counters) lub układami czasowymi (ang. timers) z dokładnością
oscylatora kwarcowego mk. Liczba liczników stosowanych w mk i ich długość wyrażona w bitach,
różnią się dla konkretnych typów mk. Większość mk ma przynajmniej dwa liczniki 16- bitowe,
każdy mk posiada choćby jeden licznik 8-bitowy. Najprostszą strukturę takiego układu pokazano na
rys. 6.10. Składa się on z rejestru o określonej długości i niezaznaczonych na rys. rejestru
zawierającego np. bity przepełnienia, ustawiające tryb pracy, bit startu zliczania licznika itd. Rejestr
przesuwny zliczający liczbę zmian poziomów doprowadzonych do niego sygnałów jest dostępny z
poziomu programu użytkownika, jako rejestr (dla liczników 8-bitowych) lub para rejestrów (dla
liczników 16- bitowych) o określonych adresach w obszarze pamięci danych.
153
Rysunek 6.10. Schematyczna budowa układu czasowego
Z rys. 6.10 widać, że najprostsze układy czasowe mogą pracować w dwóch podstawowych
konfiguracjach:
− jako właściwe układy czasowe (timers) – Są wtedy taktowane wewnętrznym sygnałem
zegarowym przeznaczonym do taktowania jednostki centralnej. Timery wykorzystywane są
w programie użytkownika jako wzorce czasu. W celu generowania wzorców czasu o różnej
długości wewnętrzny sygnał zegarowy, przed doprowadzeniem do układu czasowego,
przechodzi przez programowalny dzielnik częstotliwości.
− jako liczniki (counters) – Są one wtedy taktowane zewnętrznymi sygnałami
doprowadzanymi poprzez linie wejściowe portów i wykorzystywane w programie
użytkownika np. jako liczniki zmian poziomów sygnałów zewnętrznych
Kolejna właściwość liczników to sposób zliczania impulsów. Liczniki mogą zliczać impulsy w
górę, tzn. inkrementować lub w dół czyli dekrementować. W praktyce mk są wyposażone w
bardziej rozbudowane układy licznikowe. Liczniki te są używane zazwyczaj do realizacji
następujących funkcji:
− określenia (mierzenia) odstępów czasu między zdarzeniami zachodzącymi na zewnątrz mk,
sygnalizowanymi przez impulsy elektryczne doprowadzone do mk. Funkcja ta bywa
nazywana rejestracją zdarzeń (ang. input event capture),
− generowania impulsów (sekwencji impulsów) w odstępach czasu o zaprogramowanej
wartości (ang. output compare) lub przebiegu okresowego o zadanej częstotliwości,
− generowania sygnałów impulsowych o określonym czasie trwania lub sygnałów okresowych
o zadanym współczynniku wypełnienia (PWM – ang. puls width modulation),
− sterowania szybkością transmisji w portach szeregowych, zarówno w trybie
synchronicznym, jak i asynchronicznym (ang. baud rate generator),
− realizacji zadań licznika nadzorcy – watchdoga, omówionych w następnym rozdziale.
Podstawową konfigurację licznika jako rejestratora zdarzeń pokazano na rys. 6.11.
Rysunek 6.11. Licznik w konfiguracji rejestratora zdarzeń
154
Jego zadaniem jest określenie czasu wys-tąpienia zdarzenia zewnętrznego sygnalizowanego przez
impuls elektryczny podany na wejście. Czas ten jest mierzony w sposób względny, tzn. w stosu-nku
do chwili zezwolenia na rozpoczęcie zliczenia w liczniku. Przed uruchomieniem zliczania program
zeruje licznik i określa zbocze sygnału zewnętrznego, które ma spowodować rejestrację zdarzenia.
Po wystąpieniu tego zbocza zawartość licznika jest przepisywana do rejestru zatrzaskowego
rejestratora. Układ może równocześnie wygenerować przerwanie informujące jc o zarejestrowaniu
zdarzenia, jeśli wcześniej ustawiono zezwolenie przerwania. W tym układzie odczyt rejestru
zatrzaskowego musi nastąpić przed wystąpieniem kolejnego zdarzenia, ponieważ pracujący cały
czas licznik przy następnym sygnale zewnętrznym zmieni zawartość rejestru zatrzaskowego.
Rejestrując czas wystąpienia kolejnych zboczy można łatwo określić częstotliwość sygnału
okresowego lub szerokość impulsów. W pierwszym przypadku rejestruje się dwa następujące po
sobie zbocza o tej samej polaryzacji, natomiast w drugim – dwa zbocza o różnej polaryzacji.
Szczególne zastosowanie tej konfiguracji polega na generowaniu impulsów o programowalnym
czasie opóźnienia w stosunku do zewnętrznych impulsów odniesienia.
W tym przypadku układ pracuje w mieszanym trybie rejestrator – generator. Po zarejestrowaniu
zdarzenia licznik odmierza zaprogramowaną liczbę impulsów i generuje sygnał wyjściowy.
W konfiguracji programowanego generatora impulsów licznik pracuje zgodnie z zasadą pokazaną
na rys. 6.12. Jc wpisuje do rejestru komparatora liczbę określającą chwilę wygenerowania impulsu,
po czym uruchamia licznik. Po upływie zaprogramowanej liczby cykli zegara, komparator wykrywa
zrównanie się zawartości licznika i rejestru, po czym generuje sygnał wyjściowy. Jednocześnie
licznik może wysyłać do jc przerwanie, o ile zostało odblokowane. Większość liczników/
generatorów wytwarza impulsy o zadanej polaryzacji. Ponadto po wygenerowaniu impulsu przez
układ licznika jc może zlecić nowy cykl generacji z innym początkowym ustawieniem rejestru
komparatora.
Rysunek 6.12. Licznik w układzie programowalnego generatora impulsów
W ten sposób mk jest w stanie generować przebieg o dowolnie ustalanych czasach trwania
kolejnych impulsów. Wadą przedstawionej prostej konfiguracji generatora jest to, że przy generacji
kolejnych impulsów powstaje błąd wynikający z czasu działania jc (zwykle dwa okresy sygnału
zegarowego), ponieważ jc musi po każdej operacji wpisywać nową zawartość do rejestru
komparatora.
W celu wyeliminowania tej wady stosuje się ulepszone układy liczników z podwójnymi rejestrami i
komparatorami, nazywane licznikami z buforowaniem (ang. buffered output compares). W tych
układach aktualnie zaprogramowana wartość opóźnienia jest przechowywana w rejestrze jednego z
kanałów, natomiast wartość kolejnego opóźnienia w rejestrze drugiego kanału (rys. 6.13). Blok
licznika autonomicznie steruje układem selekcji kanału. W najprostszym przypadku kanały pracują
naprzemiennie. Należy pamiętać aby nie wpisywać danych do rejestru aktualnie pracującego kanału.
155
Rysunek 6.13. Licznik w układzie programowalnego generatora impulsów z podwójnym kanałem
W konfiguracji PWM licznik pracuje jako generator fali prostokątnej o programowanym
współczynniku wypełnienia. Układ ten pokazano na rys. 6.14. Zasada jego pracy jest następująca.
Jeśli zawartość licznika osiągnie zaprogramowaną liczbę NT określającą okres impulsów,
komparator ustawia przerzutnik wyjściowy. Sygnał przepełnienia licznika określa zatem początek
okresu generowanego przebiegu. W czasie zliczania kolejnych impulsów zegara zawartość licznika
jest porównywana z zawartością rejestru szerokości impulsów, a po zrównaniu się z nią generowany
jest sygnał „=”, który zeruje przerzutnik wyjściowy. Tym samym impuls wytwarzany przez PWM
kończy się. Rozdzielczość wyjściowa układu PWM jest określona przez częstotliwość sygnału
zegara i długość słowa licznika. Rejestr sterujący PWM zawiera dodatkowo wydzielone bity, które
pozwalają na wyjściu uzyskać sygnał stały na poziomie „0” lub „1”. Jako przykład prostego układu
licznikowego można przedstawić 8-bitowy licznik TIMER0 mk PIC16F873.
Rysunek 6.14. Licznik w trybie PWM
W konfiguracji PWM licznik pracuje jako generator fali prostokątnej o programowanym
współczynniku wypełnienia. Układ ten pokazano na rys. 6.14. Zasada jego pracy jest następująca.
Jeśli zawartość licznika osiągnie zaprogramowaną liczbę NT określającą okres impulsów,
komparator ustawia przerzutnik wyjściowy. Sygnał przepełnienia licznika określa zatem początek
okresu generowanego przebiegu. W czasie zliczania kolejnych impulsów zegara zawartość licznika
jest porównywana z zawartością rejestru szerokości impulsów, a po zrównaniu się z nią generowany
jest sygnał „=”, który zeruje przerzutnik wyjściowy. Tym samym impuls wytwarzany przez PWM
kończy się.
W przypadku mk 80c51 blok liczników/timerów składa się z 2 układów 16 bitowych, których
działanie jest uzależnione od konfiguracji zapisanej w rejestrach TCON oraz TMOD
przedstawionych rysunku 6.15 i 6.16.
Mogą one pracować zarówno jako Timery (liczą impulsy z rezonatora kwarcowego podzielone przez 12),
jak i jako liczniki (liczą impulsy podłączone do linii wejściowej mikrokontrolera). Naliczanie odbywa się
156
na liczbach 16-bitowych, znaczy to, że maksymalna wartość wynosi 65536. Przepełnienie w liczniku, tzn.
przejście ze stanu FFFFH do 0000H, jest sygnalizowane odpowiednią flagą. W tym momencie może być
również zgłaszane przerwanie do mikrokontrolera, co jest przedstawione w lekcji 12. Stan początkowy
liczników może być dowolnie ustawiany tak, aby zakończenie zliczania (ustawienie flagi bądź przerwanie)
oznaczało odliczenie zadanego czasu. Timery w mikrokontrolerze 8051 mogą pracować w czterech różnych
trybach. Będą one przedstawione na przykładzie pracy timera jako licznika impulsów zewnętrznych.
Timer może liczyć impulsy zewnętrzne podłączone do linii procesora: Timer0 z linii P3.4 zwanej też T0,
Timer1 z linii P3.5 zwanej też T1.
Wszystkie rejestry związane z timerami są położone w obszarze rejestrów specjalnych. Należą do nich:
TL0 - młodsza część Timera0 (8 bitów)
TH0 - starsza część Timera0 (8 bitów)
TL1 - młodsza część Timera1 (8 bitów)
TH1 - starsza część Timera1 (8 bitów)
TMOD - ustawia tryby pracy timerów 0 i l
(Cztery młodsze bity rejestru TMOD ustawiają tryb pracy Timera0, natomiast 4 starsze w sposób
analogiczny ustawiają Timer 1.)
TCON - 4 bity z tego rejestru sterują pracą timerów.
Rysunek 6.15. Rejestr TMOD mk 80c51
Rysunek 6.16. Rejestr TCON mk 80c51
W rejestrze TMOD:
- Bit C / T decyduje o pracy jako timer lub jako licznik. Stan 0 powoduje zliczanie impulsów
wewnętrznego zegara mikrokontrolera (rezonator kwarcowy /l2), natomiast stan l impulsów zewnętrznych z wejścia Tx.
- Bit GATE decyduje o sposobie kontrolowania pracy timera. Przy ustawieniu 0, start/stop
timera odbywa się przez ustawienie bitu TRx (z rejestru TCON). Przy ustawieniu l
dodatkowo o pracy timera decyduje stan linii INTx.
- Dwa bity Ml, M0 ustawiają odpowiedni tryb pracy timera - 0...3.
W rejestrze TCON znajdują się po 2 bity sterujące dla każdego timera:
- TRx: l - start timera, 0 - zatrzymanie timera.
- TFx flaga przepełnienia - ustawiona automatycznie na 1 w momencie przekroczenia zakresu
timera.
Jak wspomniano wyżej, ustawienie bitu GATE w rejestrze TMOD powoduje, że praca timera jest dodatkowo
kontrolowana przez linię INTx.
Poniżej przedstawiono schematy blokowe ilustrujące poszczególne konfigurację pracy
liczników/timerów mikrokontrolera 80C51.
157
Rysunek 6.17. Układ TIMERA0 w przypadku pracy w modzie 0 i 1
W trybie 0 timer pracuje jako rejestr 13-bitowy, tzn. TL1 traktowany jest jako rejestr 5-bitowy. Rejestr
ten jest w rzeczywistości nadal rejestrem 8-bitowym i cały jest zwiększany, ale przeniesienie z rejestru
TLI do rejestru THl jest generowane przy przepełnieniu młodszych 5 bitów rejestru TLI. Tak
skonfigurowany timer może liczyć do wartości 8192. W trybie l timer pracuje jako pełny rejestr 16-bitowy.
W tym trybie ustawienie flagi TF1 następuje przy doliczeniu do wartości 65536.
Rysunek 6.18. Układ TIMERA0 w przypadku pracy w modzie 2
W trybie 2 timer pracuje jako rejestr 8-bitowy. Wykorzystany jest do tego TLI. W momencie
przekroczenia jego zakresu (256) następuje ustawienie flagi TF1 i jednoczesne załadowanie rejestru TLI
zawartością rejestru THl. Wpisując do rejestru THl odpowiednią wartość, na przykład 256-10, można
uzyskać ustawienie flagi TF1 co 10 impulsów wejściowych.
158
6.2. Układy licznikowe/czasowe – cd. (80c51)
Rysunek 6.19. Układ TIMERA0 w przypadku pracy w modzie 3
W trybie 3 Timerl jest zatrzymywany, natomiast Timer0 pracuje jako dwa niezależne liczniki 8-bitowe.
Licznik TL0 sterowany jest przez te same bity, tak jak cały Timer0 w innych trybach. Natomiast licznik
TH0 może pracować tylko jako timer i jest sterowany bitem TR1 oraz ustawia flagę TF1. Timerl może w
tym momencie pracować w innym, dowolnym trybie, ale nie będzie można go zatrzymać i nie ustawi on flagi
TF l.
6.3. Układy nadzorujące – układ watchdog
Do układów nadzorujących poprawność pracy mk można zaliczyć:
- autonomiczne liczniki watchdog (licznik nadzorcy),
- monitory sygnału zegarowego,
- układy detekcji zaniku i powrotu napięć zasilających,
- układy detekcji przyczyn awarii systemowych.
Część z tych układów została już przedstawiona przy omawianiu układu oscylatora i dystrybucji
sygnału zegarowego oraz układu resetu. Najczęściej stosowanym układem nadzorującym pracę mk
jest licznik watchdog. Poprawnie pracujący mk charakteryzuje się pewną sygnaturą
częstotliwościową lub czasową zawierającą się w ściśle określonych granicach. Wynika to z zasady
pisania oprogramowania na mk (rys 6.20).
Rysunek 6.20. Struktura programu użytkownika w mk
159
Program użytkownika, po części inicjalizacyjnej, jest wykonywany w niekończącej się pętli od
czasu do czasu przerywanej przez obsługę przerwań. Program ten jest jedynym programem jaki
znajduje się w mk – w przeciwieństwie do komputerów PC, gdzie program użytkownika jest
uruchamiany przez pracujący na okrągło system operacyjny. W mk nie ma systemu operacyjnego.
Zatem mk wykonuje tylko to co napiszemy. Stąd aby mk działał prawidłowo nasz program musi
pracować w nieskończonej pętli. Pętla ta jest wykonywana z określoną częstotliwością możliwą do
obliczenia przez programistę (znamy częstotliwość oscylatora, z dokumentacji wiemy ile cykli
zegarowych potrzebuje każda instrukcja i oczywiście wiemy ile jest tych instrukcji w pętli). Jeżeli w
jakimś momencie pętla ta zawiesi się (np. błąd w programie) lub będzie wykonywana zdecydowanie
wolniej niż powinna (np. nieprawidłowa praca urządzeń peryferyjnych) jest to równoważne z
wykryciem sytuacji alarmowej. Układem, który to wykrywa jest autonomiczny licznik watchdog.
Gdy wykryje on tę sytuację wysyła sygnał reset zerujący mk oraz ustawia odpowiednie bity w
rejestrze przechowującym informację o przyczynach wyzerowania procesora. Zasada jego działania
jest następująca: Układ ten jest licznikiem zasilanym sygnałem z własnego oscylatora RC (np. dla
PIC16F873 i AT90S8515) lub oscylatora kwarcowego (rys. 6.21). Jeśli nastąpi jego przepełnienie to
wysyła on sygnał reset. Czyli trzeba ten licznik co jakiś czas zerować. Służą do tego specjalne
instrukcje np. CLRWDT dla PIC16F873, które należy umieścić w nieskończonej pętli programu
(lub inaczej – głównej pętli programu). Czyli jak program pracuje prawidłowo to rozkaz zerujący
watchdog jest wykonywany cyklicznie z założoną częstotliwością. Natomiast gdy program się
zawiesi to instrukcja ta nie zostanie wykonana na czas i licznik watchdoga przepełni się wywołując
reset mk.
Rysunek 6.21. Układ watchdog mk ST72215G
W przypadku mk ST72215G należy cyklicznie wpisywać do rejestru CR watchdoga bajt o wartości
od FFH do C0h w zależności od tego ile zliczeń 12288 impulsów zegara założyliśmy. Licznik zlicza
w dół (dekrementuje). Bit WDGA służy do włączenia/wyłączenia watchdoga. Natomiast
wyzerowanie bitu T6 generuje sygnał resetu. Bit ten można również programowo wyzerować
wywołując w ten sposób reset programowy. Po uruchomieniu (inicjalizacji) mk, analiza śladu
programu (np. stosu, zawartości rejestrów, itp.) oraz znajomość przyczyny zerowania daje podstawy
do tworzenia programów auto-korekcyjnych, które po wykryciu błędu oprogramowania sygnalizują
i zapamiętują numer błędu i mogą dokonywać blokady odpowiedniego fragmentu kodu
zabezpieczając system przed ciągłym blokowaniem się w sytuacjach alarmowych. W przypadku mk
DS87530 schemat układu watchdog przedstawia rysunek 6.22.
160
Rysunek 6.22. Konfiguracja rejestru sterującego układem WDOG w mk DS87530
6.4. Specjalizowane układy komunikacji szeregowej
Sterowniki komunikacji szeregowej służą do wymiany informacji pomiędzy mk, a jego otoczeniem.
Przesyłanie danych odbywa się w sposób szeregowy. Zasadę działania tych układów pokazano na
rys. 6.23.
Rysunek 6.23. Schematyczna budowa sterownika komunikacji szeregowej
Urządzenie to umożliwia wysyłanie zawartości określonego rejestru, tzw. Bufora nadajnika, w
postaci szeregowej poprzez określone wyprowadzenia portu. Oznacza to, że na wyjściu linii portu
pojawia się ciąg binarny odpowiadający zawartości wysyłanego rejestru (funkcja nadajnika –
transmiter). W funkcji odbiornika (ang. receiver) sterownik komunikacji szeregowej potrafi
przetworzyć ciąg binarny doprowadzony do wejścia określonej linii portu na zawartość rejestru,
zwanego buforem odbiornika. Bufory nadajnika i odbiornika są dostępne z poziomu programu
użytkownika. Wyróżnia się dwa rodzaje transmisji szeregowej:
− asynchroniczną,
− synchroniczną.
161
Dane przesyłane asynchronicznie nie są związane z żadnym sygnałem synchronizującym, w
szczególności nie towarzyszy im sygnał zegara. Transmisja przebiega zwykle bajtami przesyłanymi
w postaci ciągów bitów. Oprócz ośmiu bitów danych przesyła się dodatkowo bit startu oraz
opcjonalnie bit parzystości do detekcji błędów i bit stopu. Pomiędzy nadajnikiem, a odbiornikami
musi być ustalona częstotliwość przesyłania danych. Przy transmisji synchronicznej równolegle z
ciągiem bitów danych przesyła się sygnał synchronizujący (zegarowy), który określa chwile, w
których stan linii danych odpowiada ważnym wartościom kolejnych bitów. Po każdym bajcie może
być dodatkowo przesłany bit parzystości. Sterownik komunikacji szeregowej (w skrócie: port
szeregowy) nazywa się dwukierunkowym (dupleksowym), jeśli może równocześnie odbierać i
nadawać dane. Jest to możliwe, gdy jest wyposażony w dwie oddzielne linie do nadawania i do
odbioru. Można wyróżnić między innymi następujące interfejsy szeregowe stosowane w mk:
− UART (ang. Universal Asynchronous Receiver/Transmitter),
− SPI (ang. Serial Peripherial Interface), ISP (In-System Programmable)
− I2C (ang. Inter-Integrated Circuit),
− CAN (ang. Cotroller Area Network),
− USB (ang. Universal Serial Bus).
6.4.1. Interfejs UART
Interfejs ten przewidziany jest zazwyczaj do zapewnienia łączności mk z komputerem PC lub
innym mk. Mk posiadają często rozbudowane układy UART posiadające własne generatory
sygnałów odniesienia, bufory, dekodery kodów sterujących, mogące pracować w trybie
dwukierunkowym z protokołem potwierdzeń sprzętowych (Xon/Xoff). W praktyce jednak nie
spotyka się tak często zewnętrznych układów scalonych wyposażonych w ten system interfejsowy.
Nie może więc on być traktowany jako platforma rozszerzenia mse, lecz jedynie jako interfejs
dedykowany budowie specjalizowanego łącza, np. do komunikacji z komputerem PC. Port
szeregowy UART kontaktuje się ze światem zewnętrznym za pomocą dwóch wyprowadzeń:
wejścia odbiornika (oznaczanego najczęściej RxD) i wyjścia odbiornika (TxD). Interfejs UART jest
interfejsem asynchronicznym, najczęściej posiada swój własny generator taktujący.
Rysunek 6.24. Format danych dla standardu UART
Format danych w tym standardzie pokazano na rys. 6.24. Jak widać, transmisja zaczyna się od bitu
startu, po którym następuje osiem bitów danej (czasami dziewięć, gdzie dziewiąty bit jest
najczęściej bitem parzystości) i jednego bitu stopu (w skrócie: 8N1).
Jako przykład takiego urządzenia przedstawiono urządzenie UART mikrokontrolera 80C51 (rys.
6.25). Do rejestru SBUF użytkownik wpisuje dane przeznaczone do wysłania wyjściem TxD i
odczytuje z niego dane, które przyszły wejściem RxD. Fizycznie są to dwa rejestry pod wspólną
nazwą, ponieważ operacja zapisu dotyczy innego rejestru niż operacja czytania. Zapis danej do rej.
SBUF automatycznie uruchamia procedurę wysyłania danej przez interfejs.
162
Rysunek 6.25. Schematyczna budowa urządzenia UART mk 80C51
Rejestr SCON służy do sterowania pracą interfejsu oraz zawiera informację o jego stanie. Jego
postać jest następująca:
Rysunek 6.26. Rejestr SCON
SM0, SM1 – wybór trybu pracy:
0 0 tryb 0 – rejestr przesuwny (8 bitów), fosc/12,
0 1 tryb 1 – UART (8 bitów), częstotliwość zmienna,
1 0 tryb 2 – UART (9 bitów), fosc/64 lub fosc/32,
1 1 tryb 3 – UART (9 bitów), częstotliwość zmienna.
SM2 - maskowanie odbioru znaku:
tryb 0 – powinno być SM2 = 0,
tryb 1 – przy SM2 = 1 znacznik przerwania RI nie jest uaktywniany przy braku bitu stopu w
odbieranym słowie,
tryb 2 i 3 – przy SM2 = 1 znacznik przerwania RI nie jest uaktywniany jeżyli 9-ty bit
odbieranego słowa jest równy 0; w tych trybach znacznik ten jest wykorzystywany przy
komunikacji wieloprocesorowej.
REN - znacznik uaktywnienia odbiornika:
0 odbiór zablokowany,
1 odbiór dozwolony.
TB8 - znacznik używany w transmisji dziewięciobitowej:
tryb 0 i 1 – nie używany,
tryb 2 i 3 – dziewiąty bit w nadawanym słowie.
RB8 - znacznik używany w transmisji dziewięciobitowej:
tryb 0 – nie używany,
tryb 1 – gdy SM2, do RB8 jest wpisywany bit stopu odbieranego słowa,
tryb 2 i 3 – do RB8 jest wpisywany dziewiąty bit odbieranego słowa.
TI - znacznik przerwania nadajnika. Ustawiany w stan 1 przez mikrokontroler tylnym zboczem 9tego bitu wysyłanego słowa w trybie 0 lub przednim zboczem bitu stopu w pozostałych trybach.
Może być zerowany tylko programowo.
RI - znacznik przerwania odbiornika. Ustawiany w stan 1 przez mikrokontroler tylnym zboczem 9tego bitu przyjmowanego słowa w trybie 0 lub w połowie bitu stopu w pozostałych trybach z
wyjątkiem gdy w trybach 2 i 3 bit SM2 = 1, a dziewiąty bit odbieranego słowa jest równy 0.
163
Jednym z elementów konfiguracji urządzenia UART jest ustawienie prędkości transmisji. Dla trybu
1 i 3 interfejs taktuje się za pomocą liczników mk. W celu uzyskania jednej ze standardowych
prędkości transmisji np. 9600 bitów na sekundę niezbędne jest zastosowanie oscylatora np. o
częstotliwości 11,059MHz. „Okrągłe” częstotliwości pożądane w układach pomiarowych np.
12MHz nie zapewniają prawidłowej prędkości transmisji, która jest obarczona błędem. Gdy błąd
ten nie jest duży (poniżej jednego procenta), to nie wpływa on na poprawność wymiany danych.
Rysunek 6.27. Serial Port, Mode 0
164
Rysunek 6.28. Przebiegi czasowe sygnałów dla portu w trybie, Mode 0
Rysunek 6.29. Serial Port, Mode 1
165
Rysunek 6.30. Przebiegi czasowe sygnałów dla portu w trybie, Mode 1
Rysunek 6.31. Serial Port, Mode 2
166
Rysunek 6.32. Przebiegi czasowe sygnałów dla portu w trybie, Mode 2
Rysunek 6.33. Serial Port, Mode 3
167
Rysunek 6.34. Przebiegi czasowe sygnałów dla portu w trybie, Mode 3
Drugim przykładem jest interfejs UART mk AT90S8515. Umożliwia on transmisję szeregową
asynchroniczną z pełnym dupleksem. Posiada następujące cechy :
− full duplex (posiada oddzielne rejestry do odbioru i nadawania),
− można ustawić wiele prędkości transmisji,
− wysyłanie/odbieranie 8 lub 9 bitów danej,
− zapewnia filtrację szumów,
− ma detekcje błędu kolizji i błędu ramki,
− zapewnia detekcję błędu nieprawidłowego startu,
− generuje 3 oddzielne przerwania (Tx zakończone, Tx rejestr danej pusty, Rx zakończone).
Układ ten składa się z trzech oddzielnych bloków: układu do nadawania danej (nadajnika), układu
do odbioru danej (odbiornika) oraz generatora taktującego.
W układzie nadajnika (rys. 6.35) transmisja jest inicjowana przez wpis danej do rejestru danej
układu UART (rej. UDR).
Rysunek 6.35. Schemat blokowy układu nadajnika UART w mk AT90S8515
Dana jest transferowana z rej. UDR do rejestru przesuwnego gdy :
168
− Nowa dana została wpisana do rej. UDR po tym jak wysłany został ostatni bit danej
poprzedniej. Rejestr przesuwny jest ładowany natychmiast.
− Nowa dana została wpisana do rej. UDR zanim zakończono wysyłanie poprzedniej. Rejestr
przesuwny jest ładowany dopiero po wysłaniu bitu stopu danej poprzedniej.
Przesłanie danej z rej. UDR do rejestru przesuwnego powoduje ustawienie flagi UDRE w rejestrze
statusowym USR. Flaga ta sygnalizuje gotowość przyjęcia następnej danej do nadawania. Zaraz po
załadowaniu rejestru przesuwnego czyszczony jest jego najmłodszy bit (bit startu), a bit 9-ty lub 10ty jest ustawiany (bit stopu). W przypadku wysyłania danej dziewięciobitowej (patrz bit CHR9 w
rejestrze sterującym UCR), 9-ty bit danej jest przepisywany na 9-ty bit rejestru przesuwnego. Z
prędkością ustawianą za pomocą rej. UBRR, następuje przesyłanie bitów, rozpoczynając od bitu
startu, następnie od bitu LSB, kończąc na bicie stopu. Bity są wystawiane na pin TxD. Po wysłaniu
bitu stopu, następuje przesłanie nowej danej z rej. UDR do rejestru przesuwnego (o ile nowa dana
została tam wpisana w czasie transmisji). Podczas przesyłania ustawiana jest flaga UDRE.W
przypadku braku nowej danej, bit UDRE pozostaje ustawiony, aż do momentu wpisania danej do
rej. UDR. Jeśli nie ma już danych do przesłania, a bit stopu pozostaje na TxD przez czas potrzebny
na przesłanie 1 bitu, ustawiana jest flaga TxC w rej. USR. Bit TXEN w rej. UCR włącza tryb
nadawania UART. Jeśli jest wyczyszczony, pin PD1 może być użyty jako końcówka ogólnego
przeznaczenia. Jeśli jest ustawiony, pin PD1 będzie ustawiony jako wyjście i to niezależnie od stanu
rejestru kierunku danych portu D. Drugim układem w interfejsie UART jest odbiornik, którego
schemat blokowy pokazano na rys. 6.36.
Rysunek 6.36. Schemat blokowy układu odbiornika UART w mk AT90S8515
Układ odbioru próbkuje sygnał wejściowy (RxD) z częstotliwością 16 * BAUD, gdzie BAUD –
częstotliwość układu taktującego. Gdy linia jest w stanie spoczynkowym, pojedyncza próbka o
stanie „0” jest interpretowana jako zbocze opadające bitu startu i rozpoczyna się procedura
sprawdzająca. Testuje ona, czy rzeczywiście stan „0” na linii jest bitem startu czy też zakłóceniem, i
w tym drugim przypadku ignoruje zbocze. Jeśli bit startu jest stwierdzony poprawnie (3 próbki z
rzędu to „0”), następuje odczyt kolejnych bitów danej, rozpoczynając od LSB. Każdy bit
próbkowany jest 3 razy i jako prawdziwa wartość interpretowana jest ta, która pojawia się w
przynajmniej 2 próbkach. Pozwala to na eliminację zakłóceń. Kiedy do odbiornika trafia bit stopu,
przechodzi on procedurę sprawdzenia poprawności i jeśli z 3 próbek 2 lub 3 są zerami, ustawiana
169
jest flaga FE (błąd ramki). Przed odczytaniem rej. UDR należy więc zawsze sprawdzać stan flagi
FE. Niezależnie od ewentualnego błędu ramki, dana jest przesyłana do rej. UDR i ustawiana jest
flaga RxC. W rzeczywistości rej. UDR nie jest jednym rejestrem, lecz dwoma oddzielnymi dla
wysyłania i odbioru. W przypadku zapisu do rej. UDR dana jest wpisywana do rejestru wysłania, a
w przypadku odczytu podstawiana jest zawartość rejestru odbioru. Jeśli ustawiony jest tryb odbioru
danej 9–bitowej (patrz bit CHR9 w rej. UCR), bit RXB8 w rej. UCR jest ładowany wartością 9-tego
bitu danej odebranej. Jeśli po odebraniu danej stwierdzi się brak pobrania z rej. UDR danej
poprzedniej, ustawiana jest flaga kolizji OR w rej. UCR. Oznacza ona, że ostatnio odbierana dana
nie mogła zostać przesłana do rej. UDR i została utracona. Flaga OR jest czyszczona przy odczycie
prawidłowej danej z rej. UDR. Przed odczytem rej. UDR należy więc zawsze sprawdzić flagę OR.
Kiedy bit RXEN w rej. UCR jest wyczyszczony, odbiornik jest wyłączony. Pin PD0 może być użyty
jako linia portu równoległego. Gdy RXEN = „1” do linii PD0 podłączone jest wejście odbiornika,
co oznacza, że staje się on pinem wejściowym, niezależnie od ustawień w rejestrze kierunku pinów
DDRD portu D.
Kiedy ustawiony jest bit CHR9 w rej. UCR, dane odbierane i nadawane mają długość 9 bitów plus
bit startu i stopu. 9-ty bit danej do nadania należy wpisać pod bit TXB8 w rej. UCR, a odebrany 9-ty
bit danej znajduje się w RXB8 rej. UCR. Wpis bitu do TXB8 musi nastąpić wcześniej niż wpis
reszty danej do rej. UDR, co rozpoczyna transmisję. Do sterowania układem UART mk
AT90S8515 wykorzystuje się cztery rejestry:
− Danej, rej. UDR (dana odbierana lub nadawana),
− Statusowy, rej. USR (flagi błędów, zakończenie transmisji, etc.),
− Sterowania, rej. UCR (włączenie przerwań, włączenie / wyłączenie UART),
− Prędkości, rej. UBRR (BAUD = fck / ( 16 ( UBRR+1 ) )).
Rejestr statusowy – rej. USR o adresie $0B ( $2B ) posiada następujące flagi:
− 7 : RXC – Odbiór zakończony. Gdy flaga jest ustawiona, odebrana dana została przesłana do
rej. UDR. Flaga ta jest ustawiana niezależnie od błędów transmisji. W przypadku włączenia
przerwania ( RXCIE w rej. UCR), ustawienie RXC oznacza wywołanie obsługi przerwania
zakończenia odbioru. RXC czyszczona jest przez odczyt rej. UDR. Obsługa przerwania
zakończonego odbioru musi odczytać rej. UDR i wyczyścić flagę RXC.
− 6 : TXC – Nadawanie zakończone. Zakończono nadawanie bitu stopu, a w rej. UDR nie ma
nowej danej. Flaga ta jest użyteczna w trybie half-duplex, kiedy urządzenie po nadaniu danych
musi zwolnić linię i ustawić się w tryb odbioru. Jeśli ustawiona jest flaga TXCIE w rej. UCR,
wykona się obsługa przerwania zakończonego nadawania. TXC czyści się wtedy automatycznie.
W przypadku wyłączonego przerwania TXC można wyczyścić poprzez wpisanie logicznej „1”.
− 5 : UDRE – Rejestr danej pusty. Flaga ta ustawia się przy przesłaniu danej z rej. UDR do
rejestru przesuwnego celem nadania i oznacza, że do rej. UDR można wpisać kolejną daną.
− 4 : FE – Błąd ramki. Ustawia się gdy zamiast bitu stopu stwierdza się „0”. Czyści się
automatycznie po prawidłowym odbiorze bitu stopu. 3 : OR – Błąd kolizji. Ustawia się, gdy nie
można przesłać odebranej danej do rej. UDR, ponieważ nie odczytano z tego rejestru danej
poprzedniej. Zeruje się przy prawidłowym przepisaniu danej do rej. UDR.
− 2..0 : – Zarezerwowane.
Do sterowania pracą portu UART wykorzystuje się rej. UCR spod adresu $0A ( $2A ). Znaczenie
bitów jest następujące:
170
Rysunek 6.37. Znaczenie bitów rejestru UCR
− 7 : RXCIE – Włączenie przerwania zakończonego odbioru. Gdy flaga jest ustawiona, ustawienie
flagi RXC w rej. USR powoduje wywołanie obsługi przerwania (oczywiście przy odblokowanej
globalnej masce przerwań).
− 6 : TXCIE – Włączenie przerwania zakończonego nadawania. Gdy flaga jest ustawiona,
ustawienie flagi TXC w rej. USR powoduje wywołanie obsługi przerwania (oczywiście przy
odblokowanej globalnej masce przerwań).
− 5 : UDRIE – Włączenie przerwania „rejestr danej pusty”. Gdy flaga jest ustawiona, ustawienie
flagi UDRE w rej. USR powoduje wywołanie obsługi przerwania (oczywiście przy
odblokowanej globalnej masce przerwań).
− 4 : RXEN – Bit ten włącza tryb odbioru (gdy RXEN=”1”). Gdy RXEN=”0” flagi TXC, OR i FE
nie mogą mieć wartości „1”. Jeśli flagi te są ustawione, wyłączenie RXEN nie powoduje ich
czyszczenia.
− 3 : TXEN – Bit ten włącza tryb nadawania (gdy TXEN=”1”). Wyłączenie tego bitu w czasie
transmisji ma efekt dopiero po zakończeniu nadawania zarówno aktualnej danej, jak i
ewentualnie następnej już wpisanej do rej. UDR.
− 2 : CHR9 – Włączenie trybu transmisji danej 9–bitowej. Patrz opis bitów RXB8 i TXB8.
Dziewiąty bit może być użyty jako dodatkowy bit stopu lub do kontroli parzystości.
− 1 : RXB8 – Dziewiąty bit odebranej danej. Czyta się go, jeśli bit CHR9 jest ustawiony.
− 0 : TXB8 – Dziewiąty bit danej do nadania. Należy go modyfikować, jeśli dana przesłana ma
być 9–bitowa (czyli gdy CHR9=”1”).
Ostatnim układem interfejsu UART jest generator taktujący. Jest on dzielnikiem częstotliwości,
który generuje sygnał zegarowy o częstotliwości BAUD = fck / ( 16 ( UBRR+1 ) ), gdzie: rej UBRR
jest rejestrem prędkości interfejsu UART (rejestr o adresie $09 ($29)), a fck częstotliwością
oscylatora kwarcowego. Przykładowe prędkości transmisji dla czterech częstotliwości oscylatora
przedstawiono w tablicy 6.1. Zawiera ona wartości jakie należy wpisać do rej UBRR, aby uzyskać
daną prędkość transmisji. Dodatkowo umieszczono w niej procentowy błąd rzeczywistej prędkości
transmisji w stosunku do standardowej. Zaleca się stosować takie prędkości transmisji, aby ten błąd
był mniejszy niż 1 %.
Tablica 6.1. Przykładowe prędkości transmisji układu UART i odpowiadające im wartości rej. UBRR
Jak wspomniano, interfejs UART przeważnie służy do komunikacji mk z komputerem PC. Odbywa
się to najczęściej za pomocą standardu RS232. Sposób realizacji sprzętowej standardu RS232C
pokazano na rys. 4.38.
171
Rysunek 6.38. Realizacja sprzętowa standardu RS232C
Zadaniem układu ADM232 jest konwersja sygnałów między poziomem TTL na wyprowadzeniach
mk, a poziomem sygnału +/- 12V wykorzystywanym podczas transmisji łączem RS232C. Łącze to
wymaga co najmniej trzech przewodów: linii nadajnika, odbiornika oraz linii odniesienia, czyli tzw.
masy. Jest to zatem łącze asymetryczne. Umożliwia ono komunikację ze sobą tylko dwóch
jednostek przy zastosowaniu transmisji full duplex.
6.4.2. Interfejs SPI
Interfejs SPI służy do dwukierunkowej (full-duplex), synchronicznej, szeregowej transmisji danych
pomiędzy mk, a zewnętrznymi układami peryferyjnymi, np. przetwornikami A/C i C/A,
szeregowymi pamięciami EEPROM, innymi mk, układami scalonymi z regulowanymi cyfrowo
potencjometrami, dekadami pojemnościowymi, itd. Jest interfejsem trójżyłowym: składa się z
dwóch linii synchronicznie przesyłających dane w przeciwnych kierunkach i linii z sygnałem
zegarowym synchronizującym ten transfer.
Rysunek 6.39. Przykład połączenia interfejsu ISP pomiędzy układem master i slave
Na rys. 6.39 pokazano sposób połączenia interfejsu SPI pomiędzy układem nadrzędnym (master) i
układem podrzędnym (ang. slave), gdzie pin MISO jest wejściem danych, pin MOSI wyjściem
danych, a pin SCK wyjściem zegara dla układu master i wejściem zegara dla układu slave. Z
rysunku widać, że protokół transmisji (w najprostszej postaci) wymaga dwóch rejestrów
przesuwnych (ang. shift register) połączonych w licznik pierścieniowy (wejście jest połączone z
wyjściem). Transmisja jest synchroniczna - jeden z układów dostarcza sygnału zegara,
odseparowanego od sygnału danych, zgodnie ze zboczami zegara taktującego. Układ generujący
sygnał zegara jest określony jako nadrzędny, bez względu na to czy dane są przez niego nadawane
czy odbierane.
Wszystkie pozostałe układy na magistrali są określone jako podrzędne.
Sygnały danych i zegara są przesyłane oddzielnymi jednokierunkowymi liniami. Sygnał zegara nie
jest ciągły, nadawany jest jedynie w czasie trwania transmisji. Umożliwia to odbiór poszczególnych
bitów danych bez konieczności testowania bitów startu i stopu, charakterystycznego dla transmisji
asynchronicznej. Kiedy układ nadrzędny nadaje dane na linii MOSI do układu podrzędnego, to
układ podrzędny odpowiada, wysyłając do układu nadrzędnego dane na linii MISO. Implikuje to
172
dwukierunkową transmisję z jednoczesnym wysyłaniem i odbieraniem danych, synchronizowanym
tym samym sygnałem zegarowym, przez oba układy. Zatem bajt transmitowany jest od razu
zastępowany bajtem odbieranym. Dzięki temu nie ma „pustych” transmisji: raz aby wysłać bajt,
drugi aby go odebrać. Do wysłania bajtu i jego odebrania wystarczy osiem impulsów zegarowych na
linii SCK. W interfejsie tym dane są wpisywane (odbierane) do rejestru szeregowego jednym
zboczem zegarowym, a przesuwane (wyprowadzane na zewnątrz – nadawane) drugim. Zwiększa to
czas podtrzymania danych odbiornika do ½TCLK - td, gdzie TCLK - okres zegara, td - opóźnienie
magistrali. Zatem wypełnienie sygnału zegarowego wynosi około ½. Najczęściej szybkość
transmisji nie przekracza 1-2 Mbit/s. Wymiana danych za pomocą interfejsu SPI mk pracującego w
trybie master pomiędzy mk, a zewnętrznym urządzeniem peryferyjnym generalnie przebiega według
następującej procedury:
− najpierw należy odpowiednio skonfigurować interfejs SPI mk: tryb master, poprawnie
skonfigurowane piny interfejsu (pin SCK ma być wyjściem), ustawić częstotliwość sygnału
zegarowego, urządzenie peryferyjne musi być uaktywnione (przygotowane na odbiór danych) –
najczęściej służy do tego dodatkowa linia mk podłączona do wejścia CS (ang. Chip Select )
urządzenia peryferyjnego,
− aby rozpocząć transmisję ustawia się odpowiedni bit w rejestrze sterującym SPI lub wpisuje się
daną do rejestru przesuwnego,
− po czym czeka się na zakończenie transmisji, testując flagę informującą o zakończeniu
transmisji lub czeka się na przerwanie od układu SPI, o ile jest odblokowane,
− na zakończenie z rejestru przesuwnego można odczytać daną odebraną.
Interfejs SPI mk można skonfigurować do pracy w trybie slave. W tym przypadku procedura
postępowania jest następująca:
− najpierw należy odpowiednio skonfigurować interfejs SPI mk: tryb slave, poprawnie
skonfigurowane piny interfejsu (pin SCK ma być wejściem),
− następnie wpisuje się daną, którą chcemy wysłać do rejestru przesuwnego,
− ustawia się odpowiedni bit w rejestrze sterującym SPI uruchamiającym interfejs,
− urządzenie peryferyjne musi być aktywne i pracować w trybie master,
− po czym czeka się na zakończenie transmisji, które wywołuje przerwanie, o ile jest
odblokowane,
− na zakończenie z rejestru przesuwnego można odczytać daną odebraną.
W trybie slave metoda odpytywania flagi zakończenia transmisji jest nieefektywna, ponieważ
transmisja z układu peryferyjnego może nastąpić w dowolnej chwili nieznanej mk. Zatem musi on
w pętli głównej programu ciągle odpytywać tę flagę, co niepotrzebnie zajmuje czas procesora. Stąd
wiele układów SPI posiada dodatkowy sygnał wejściowy (pin SS), który pozwala na wymuszenie
trybu slave interfejsu SPI mk przez urządzenie peryferyjne.
Podsumowując, właściwości układu SPI z punktu widzenia interfejsu mogą być opisane przy
pomocy 3 funkcji interfejsowych:
− Talker (nadajnik) – wprowadzenie danej do rejestru szeregowego, przesuwanie i wysyłanie
danej z rejestru szeregowego.
− Listener (odbiornik) - wczytanie danej odbieranej z rejestru szeregowego po zebraniu całego
słowa
− Repeater (pośredniczenie w transmisji) - dane wejściowe są wpisywane do rejestru szeregowego
z linii wejściowej, przesuwane i od razu wysyłane na linię wyjściową.
− Maksymalna konfiguracja zawiera z reguły wszystkie trzy wymienione funkcje, ale w praktyce
spotyka się najczęściej dwie pierwsze. Aby transmisja pomiędzy mk, a urządzeniem
peryferyjnym przebiegała prawidłowo muszą być spełnione następujące warunki:
− zachowanie jednakowej długość danej (najczęściej 8 bitów lub wielokrotność tej liczby),
− taka sama kolejność wysyłania bitów (najczęściej od MSB do LSB, niektóre mk mają
173
− możliwość programowej zmiany tej kolejności),
− zgodna polaryzacja i faza sygnału zegarowego.
Częstotliwość sygnału zegarowego nie jest istotna, ponieważ dane są synchronizowane tym
sygnałem i są aktywowane (wpisywane lub wyprowadzane z rejestru szeregowego) wyłącznie przez
zbocza tego sygnału. Zatem prędkość transmisji możemy zmienić nawet w trakcie przesyłania
danych. Można również wstrzymać transmisję w dowolnej chwili, aby następnie ją dalej
kontynuować. Właściwość ta jest szczególnie przydatna, w przypadku przesyłania danych 8nbitowych, gdzie n – liczna naturalna, za pomocą interfejsu SPI mk, który wyłącznie może przesyłać
dane 8-bitowe. Po wysłaniu 8 bitów następuje przerwa – zatrzymanie transmisji, w czasie której do
interfejsu jest wprowadzana/czytana kolejna dana 8-bitowa, po tej przerwie ponownie uruchamia się
interfejs, itd.
Polaryzacja i faza sygnału zegarowego muszą być zgodne zarówno dla układu master, jak i układów
slave, aby transmisja pomiędzy nimi przebiegała prawidłowo. Polaryzacja sygnału zegarowego jest
określona przez wartość logiczną sygnału zegara w stanie spoczynkowym (poza czasem transmisji):
− CPOL=0 – sygnał zegara w stanie spoczynku jest w stanie niskim „Lo”,
− CPOL=1 – sygnał zegara w stanie spoczynku jest w stanie wysokim „Hi”.
Faza sygnału zegarowego definiuje zależność pomiędzy zboczami sygnału zegarowego, a
momentami próbkowania danych wejściowych; przesuwania zawartości rejestru (wysłania danych
wyjściowych):
− CPHA=0 – pierwsze zbocze sygnału zegarowego próbkuje dane wejściowe, drugie zbocze
przesuwa dane w rejestrze – wyprowadza je z rejestru (dane są próbkowane, a następnie
przesuwane i wysyłane),
− CPHA=1 – pierwsze zbocze sygnału zegarowego przesuwa dane w rejestrze – wyprowadza je z
rejestru, drugie zbocze próbkuje dane wejściowe (dane są przesuwane i wysyłane, a następnie
próbkowane i wpisywane do rejestru).
Stąd można wyróżnić cztery warianty pracy interfejsu SPI (strobowania/przesuwania informacji):
(1): CPHA=0 i CPOL=0, (2): CPHA=0 i CPOL=1, (3): CPHA=1 i CPOL=0, (4): CPHA=1 i
CPOL=1. Najczęściej spotyka się pierwszy wariant, lecz pozostałe również są stosowane, dlatego
we współczesnych mk istnieje możliwość programowego ustawienia polaryzacji i fazy sygnału
zegarowego.
Na rys. 6.40 przedstawiono (1) i (2) wariant pracy interfejsu SPI, dla sygnału zegarowego o fazie
CPHA=0, natomiast na rys.6.41 warianty (3) i (4) dla sygnału zegarowego o fazie CPHA=1. Jako
przykład interfejsu SPI wybrano układ z mk ST72215G, którego schemat blokowy pokazano na rys.
6.42.
Rysunek 6.40. Przebiegi czasowe interfejsu SPI dla sygnału zegarowego o CPHA = 0
174
Rysunek 6.41. Przebiegi czasowe interfejsu SPI dla sygnału zegarowego o CPHA = 1
Rysunek 6.42. Schemat blokowy układu interfejsu SPI mk ST72215G
Z tym układem stowarzyszone są trzy rejestry:
− rejestr kontrolny, rej. CR,
− rejestr statusu, rej. SR,
− rejestr danych, rej. DR.
Rejestr danych DR służy do wpisywania danej, która ma zostać wysłana i do odczytu odebranej
danej. Rejestr statusu SR zawiera trzy flagi:
SPIF – informacja o zakończeniu transferu danej z rej. DR,
WCOL – bit kolizji ustawiany, gdy w trakcie wysyłania danej, wprowadzono nową daną do
rej. DR,
MODF – jest ustawiany sprzętowo, gdy na linii SS pojawi się stan niski w trakcie pracy
układu jako master. Bity te są zerowane programowo.
Pierwsza i trzecia flaga mogą wywołać przerwanie, jeśli bit SPIE w rej. CR jest ustawiony. Rejestr
sterujący CR służy do konfigurowania interfejsu i sterowania jego pracą. Znaczenie bitów jest
następujące:
SPIE – maska przerwania od interfejsu SPI,
175
SPE – podłączenie urządzenia do pinów portu równoległego, zerowany przez niski poziom
sygnału na linii SS w trybie master,
SPR2, SPR1, SPR0 – określają częstotliwość sygnału taktującego interfejs w trybie master,
MSTR – ustawienie tego bitu wybiera tryb master (w przeciwnym przypadku układ jest w
trybie slave), zerowany przez niski poziom sygnału na linii SS,
CPOL – wybór polaryzacji sygnału zegarowego, CPOL=0 lub CPOL=1,
CPHA – wybór fazy próbkowania, CPHA=0 lub CPHA=1.
Aby skonfigurować interfejs w trybie master należy wykonać następujące kroki:
− ustawić bity SPR1,SPR0 w rej. CR w celu wyboru prędkości transmisji,
− ustawić CPOL i CPHA w rej. CR aby wybrać właściwy wariant strobowania danych,
− na linii SS musimy zapewnić stan wysoki w czasie całej transmisji,
− bity MSTR i SPE muszą być ustawione.
Transmisja zaczyna się, gdy wpiszemy bajt do rej. DR. Jest on równolegle ładowany do rejestru
szeregowego i następnie szeregowo wyprowadzany począwszy od najstarszego bitu. Gdy transfer
jest kompletny, bit SPIF jest ustawiany sprzętowo i jeśli bit SPIE w rej. CR jest ustawiony oraz bit I
w rejestrze kontrolnym przerwań CCR został wyzerowany, to następuje generacja przerwania.
Kiedy ustawiany jest bit SPIF, to następuje jednoczesne przepisanie zawartości rejestru
szeregowego do bufora. Bit ten jest zerowany poprzez odczyt/zapis rej. SR lub odczyt z rej. DR. Do
rej. DR można wprowadzić kolejną daną wyłącznie w przypadku, gdy bit SPIF=0.
Dla trybu slave konieczne są następujące czynności:
− urządzenie peryferyjne musi być w tym samym trybie co mk (właściwie ustawiona CPOLi
CPHA),
− na linii SS musimy zapewnić stan niski w czasie całej transmisji,
− należy wyzerować bit MSTR i ustawić bit SPE.
Transmisja zaczyna się, gdy urządzenie peryferyjne zaczyna generować sygnał zegarowy. Układ
slave (mk) w takt tych impulsów wysyła z rejestru szeregowego bajt od MSB do LSB i jednocześnie
kompletuje daną odbieraną. Dalej procedura przebiega według uprzedniej procedury.
Generalnie za pomocą interfejsu SPI można utworzyć dwie konfiguracje magistralowe:
− system z pojedynczym układem master (ang. single master system),
− system z wieloma układami master (ang. multimaster system).
Najczęściej spotykanym i najprostszym w konfiguracji jest pierwszy system, którego przykładową
konfigurację pokazano na rys. 6.43.
Rysunek 6.43. System z pojedynczym układem master oparty na interfejsie SPI
Układ master wybiera poszczególny układ slave korzystając z czterech linii portu równoległego.
Dane urządzenie slave jest wybrane, gdy na jego wejściu SS pojawi się stan niski. W czasie
transmisji, w celu uniknięcia kolizji na liniach interfejsu, tylko jeden układ slave może być
aktywny.
176
6.4.3. Interfejs I2C
Standard ten został opracowany przez firmę Philips. Jest stosowany w urządzeniach powszechnego
użytku, zwłaszcza audio-video, telekomunikacji i systemach elektroniki przemysłowej. Transmisja
danych odbywa się szeregowo, w dwóch kierunkach, przy użyciu dwóch linii. Jedną z nich SCL
(serial clock line) przesyła się impulsy zegarowe synchronizujące transmisję, natomiast drugą SDA
(serial data line) transmituje się w dwóch kierunkach dane. W transmisji interfejsem I2C
uczestniczy układ nadrzędny (master) oraz jeden lub więcej układów podrzędnych (slave).
Transmisja bloku danych jest inicjowana wówczas, gdy stan linii SDA zmieni się z wysokiego na
niski, podczas gdy linia zegarowa SCL znajduje się w stanie wysokim. Sytuacja taka jest nazywana
warunkiem startowym (Start). Koniec transmisji ma miejsce wtedy, gdy linia SDA zmieni stan z
niskiego na wysoki, podczas gdy linia zegara jest w stanie wysokim. Jest to warunek nazywany
Stop. Stan linii danych może być zmieniany wówczas, gdy linia zegarowa znajduje się w stanie
niskim. Od chwili wystąpienia warunku Start do chwili odległej o określony odstęp czasu od
wystąpienia
warunku Stop szyna jest zajęta. Informacje są przesyłane bajtami, w postaci szeregowej, przy czym
jako pierwszy wysyłany jest najbardziej znaczący bit. Po przesłaniu danych wysyłany jest sygnał
potwierdzenia oznaczony symbolem A lub ACK (acknowledge). Dziewiąty impuls zegara
towarzyszący potwierdzeniu jest generowany przez układ master. Na ten sygnał urządzenie nadające
musi zwolnić linię SDA, wprowadzając swoje wyjście SDA w stan wysoki lub w stan wysokiej
impedancji, natomiast odbiornik potwierdza odbiór sygnałem SDA=0. Liczba bajtów przesłanych w
jednej sesji, to jest między stanem Start i Stop, jest nieograniczona. Wysłanie bitu potwierdzenia
przez odbiornik po odebraniu każdego bajtu danych jest obligatoryjne. Jeśli potwierdzenie nie
zostaje wysłane, linia SDA musi znaleźć się w stanie wysokim lub w stanie wysokiej impedancji, by
umożliwić układowi master wygenerowanie warunku Stop i zakończenie transmisji. Brak
potwierdzenia może nastąpić na przykład wtedy, gdy odbiornik pracuje w czasie rzeczywistym i jest
zajęty obsługa jakiegoś pilnego zadania.
Jeśli odbiornikiem jest układ master, to po odebraniu ostatniego bajtu w sekwencji nie wysyła
sygnału potwierdzenia NA (not acknowledge). Układ slave musi wtedy zwolnić linię SDA, by
umożliwić układowi master wygenerowanie warunku Stop kończącego transmisję.
Na rys. 6.44 przedstawiono kompletny cykl transmisji w formacie standardu I2C. Po
wygenerowaniu warunku Start układ master wysyła na szynę adres układu slave, z którym chce
współpracować. Adres składa się z siedmiu bitów, po którym następuje ósmy bit R/W określający
kierunek transmisji. Jeśli R/W=0, dane będą przesyłane z układu master do układu slave, natomiast
gdy R/W=1, kierunek transmisji będzie odwrotny.
Rysunek 6.44. Protokół transmisji szeregowej standardu I2C
177
Początkowa sekwencja bitów przesyłanych w trakcie każdej sesji, złożona z bitu Startu, adresu
urządzenia slave i bitu kierunku jest nazywana blokiem Start. Dalsza część transmisji polega na
przesyłaniu kolejnych bajtów danych, zgodnie z protokołem pokazanym na rys. 6.44. Ostatnią fazą
sesji jest wysłanie przez układ master warunku Stop. Pełna sesja składa się zatem z bloku Start,
przynajmniej jednego cyklu przesłania bajtu danych i bitu Stop. Jeśli układ master zamierza w
jednej sesji wysyłać informacje w kilku blokach do tego samego lub do różnych urządzeń, może nie
kończyć sesji warunkiem Stop, lecz po przesłaniu bloku danych powtórzyć warunek Start z tym
samym lub nowym adresem urządzenia slave. Przemysłowa norma magistrali I2C zakłada
możliwość taktowania transmisji sygnałem zegarowym SCL o częstotliwości od 0 do 100kHz.
Wymaga się przy tym, by stan niski impulsów zegarowych trwał przynajmniej 4,7µs, natomiast stan
wysoki był nie krótszy niż 4 µs. W razie potrzeby układ slave może spowolnić transmisję,
utrzymując linię zegara SCL w stanie niskim po odebraniu bajtu danych od mk. Stan taki jest
nazywany stanem oczekiwania i oznaczany symbolem WAIT. Realizacja stanów oczekiwania na
magistrali wymaga, by układ master przed wysłaniem kolejnego bajtu przełączył linię SCL w stan
wysoki lub w stan wysokiej impedancji, po czym odczytał stan na SCL. Układy współpracujące z
magistralą I2C muszą być wyposażone w wyjścia z otwartym drenem dla linii SCL i SDA. Każda z
tych linii jest połączona ze źródłem napięcia zasilającego UCC przez rezystor 10kΩ.
Do jednego układu master można przyłączyć dowolną liczbę układów slave, jednak pod
warunkiem, że pojemność połączeń nie przekroczy maksymalnej wartości równej 400pF. Schemat
połączeń przedstawiono na rys. 6.45.
Rysunek 6.45. Połączenie urządzeń z magistralą I2C
Jako przykład układu interfejsu I2C przytoczono układ MSSP (Master Synchronous Serial Port) mk
PIC16F873, który może pracować jako interfejs SPI oraz interfejs I2C. Układ ten w pełni
implementuje wszystkie funkcje master i slave interfejsu I2C. Zapewnia on sprzętową realizację
przerwań na pojawienie się sekwencji Start i Stop. Umożliwia adresowanie 7-mio i 10-bitowe oraz
może pracować przy dwóch prędkościach 100kHz i 400kHz.
Do obsługi interfejsu wykorzystuje się sześć rejestrów:
− rejestr sterujący SSPCON (SSP Contorl Register),
− rejestr sterujący drugi SSPCON2 (SSP Contorl Register2),
− rejestr statusowy SSPSTAT (SSP Status Register),
− bufor odbioru/wysyłania danej SSPBUF (Serial Receive/Transmit Buffer),
− rejestr przesuwny SSPSR (SSP Shift Register) –bezpośrednio nie dostępny,
− rejestr adresu SSPADD (SSP Address Register).
Rej. SSPCON służy do kontroli pracy interfejsu. Pozwala na wybór jednego z czterech
trybów pracy interfejsu:
− tryb slave (adres 7-bitowy),
− tryb slave (adres 10-bitowy),
178
− tryb master, prędkość transmisji jest równa fOSC/(4 * (adres SSPADD+1)),
− tryby firmware (aby zapewnić kompatybilność z innymi produktami średniej klasy).
Przed podłączeniem interfejsu I2C do portu mk, właściwe piny muszą być skonfigurowane jako
wejścia. Linii SCL i SDA muszą być poprzez zewnętrzne rezystory podwieszone do napięcia
zasilania. Schemat blokowy układu MSSP pracującego jako interfejs I2C w trybie slave pokazano
na rys. 6.46, a w trybie master na rys. 6.47.
Rysunek 6.46. Schemat blokowy układu MSSP pracującego jako interfejs I2C
Rysunek 6.47. Schemat blokowy układu MSSP pracującego jako interfejs I2C w trybie master
Przedstawione układy w sposób sprzętowy w pełni realizują protokół interfejsu I2C zarówno dla
trybu slave, jak i trybu master.
179
6.4.4. Interfejs CAN
Interfejs CAN stosuje się głównie w motoryzacji, w lotnictwie, a także w sterownikach
przemysłowych. Założenia projektowe CAN koncentrują się na trzech właściwościach systemu
transmisyjnego:
− szybkości przesyłania danych łączem szeregowym,
− odporności transmisji na zakłócenia elektromagnetyczne,
− możliwości dzielenia wspólnych danych przez rozproszone mk realizujące cząstkowe funkcje
sterowania.
Szyna CAN jest asynchroniczną szyną transmisji szeregowej z tylko jedną linią transmisyjną. Ma
strukturę otwartą, tzn. może być rozszerzana o nowe węzły (odbiorniki/nadajniki), oraz liniową,
czyli nie zawiera pętli. Minimalna konfiguracja CAN składa się z dwóch węzłów. Liczba węzłów w
trakcie pracy szyny może się zmieniać bez wpływu na działanie szyny. Właściwość ta oznacza
możliwość dynamicznego konfigurowania węzłów, na przykład wyłączenia węzłów, które w
wyniku działania procedur diagnostycznych zostały uznane za niesprawne. Poszczególne węzły są
przyłączone do szyny na zasadzie funkcji „zwarty iloczyn” (ang. wired- AND). Przy braku
sterowania szyna znajduje się w stanie nazywanym recesywnym R (ang. recessive), któremu
odpowiada stan logiczny „1”. Stan ten może być zmieniony na stan logiczny „0”, jeśli choć jeden
węzeł wymusi na szynie poziom dominujący D (dominant). Najpopularniejszy sposób sprzętowej
realizacji szyny jest użycie pary skręconych przewodów oznaczonych symbolami CAN_H i
CAN_L. Linie te przyłącza się do węzłów bezpośrednio lub za pośrednictwem
buforów/nadajników/odbiorników. Po obu stronach linii dołącza się rezystory. Maksymalna
szybkość transmisji szyną CAN wynosi 1Mbps przy długości linii nie przekraczającej 40m. Im
dłuższa linia tym prędkość transmisji mniejsza, np. dla długości przewodów 1km prędkość
transmisji wynosi już 40kbps. Dane przesyłane szyną są transmitowane metodą NRZ (ang. Non
Return to Zero). Adresy odbiorników (identyfikatory) są przesyłane jako integralna część przekazu.
Ponieważ interfejs składa się wyłącznie z jednej linii konieczny jest arbitraż szyny.
Wykonuje się go metodą CSMA/CD z opcją NDA (ang. carrier sense multiple access / collision
detection with nondestructive arbitration). Specyfika standardu CAN przewiduje 11-bitowe
identyfikatory, czyli umożliwia współpracę 2048 węzłów. Najnowsza specyfikacja 2.0B (extended
CAN) posiada identyfikator 29-bitowy, co daję teoretycznie możliwość adresowania 536 milionów
współpracujących ze sobą urządzeń.
6.4.5. Interfejs USB
Interfejs ten został opracowany jako uniwersalny interfejs szeregowy wbudowany w architekturę
komputerów PC. Jego przeznaczeniem jest współpraca komputerów z urządzeniami:
przemysłowymi, urządzeniami powszechnego użytku oraz integracja z sieciami
telekomunikacyjnymi. Prędkość transferu danych wynosi 1,5 lub 12 Mbit/s dla standardu USB 1.1,
natomiast dla standardu USB 2.0 jest ona równa 480 Mbit/s. Przyjęto następującą topologię systemu
z interfejsem USB, jeden host (komputer zarządzający) połączony z pierwszym Hubem, do którego
można podłączyć na zasadzie drzewa kolejne Huby lub urządzenia. Taka topologia zapewnia
możliwość współpracy różnych urządzeń poprzez wyspecjalizowane Huby, które z kolei
współpracują ze sobą tworząc jednolity system, wygodny do użycia przez końcowego użytkownika
dzięki :
− prostemu i znormalizowanemu okablowaniu,
− izolacji elektrycznej,
− samoidentyfikacji urządzeń,
− automatycznej konfiguracji ich sterowników,
− automatycznej rejestracji w systemie,
− niskich kosztów sprzętu i okablowania.
180
Podstawowym elementem systemu są Huby. Hub posiada port do połączenia z hostem (Upstream
Port) oraz do siedmiu portów do podłączenia urządzeń lub innych Hubów (Downstream Port), z
których każdy może być indywidualnie konfigurowany i kontrolowany poprzez komputer host.
Huby składają się z dwóch części:
− Hub Controller,
− Hub Repeater.
Hub Repeater jest protokołem kontrolującym połączenie pomiędzy Upsteam Port i Downstream
Port. Dostarcza on rejestr służący do komunikacji z hostem.
Wszystkie elementy systemu połączone są magistralą składającą się z czterech linii:
− Vbus, przewód zasilania +5[V]
− D+, przewód symetrycznej skrętki sygnałowej
− D-, przewód symetrycznej skrętki sygnałowej
− GND, przewód masy zasilania.
Typowym kablem sygnałowym jest skrętka ekranowana o impedancji charakterystycznej 90+-15[%]
i maksymalnej długości 5m. Maksymalne opóźnienie sygnału między punktami końcowymi, tzn.
hostem i urządzeniem musi być mniejsze od 70ns. Do transmisji danych interfejsem USB
wykorzystuje się kodowanie danych NRZI (ang. Non- Return to Zero Invert on ones). Kodowanie to
polega na braku zmiany poziomu dla jedynki logicznej i zmianie poziomu dla zera logicznego.
Komunikacja między urządzeniami przebiega w następujący sposób: urządzenie fizyczne zostaje
zidentyfikowane przez oprogramowanie typu klient, zai4nstalowane na komputerze (host).
Następnie zostaje zainicjowane połączenie pomiędzy urządzeniem a hostem, umożliwiające
przesyłanie komunikatów i danych. Dane odebrane z urządzenia zostają sformatowane zgodnie z
wymaganiami protokołu USB i przekazane do hosta dzięki współpracy oprogramowania systemu
USB, oprogramowania hosta oraz współpracującego sprzętu. Przykładem mk wyposażonego w
interfejs USB może być mk CY7C68013 firmy Cypress, którego schemat blokowy przedstawiono
na rys. 6.48.
Rysunek 6.48. Schemat blokowy mk CY7C68013 firmy Cypress z interfejsem USB 2.0
Mk ten zbudowany jest na bazie dwóch rdzeni 8051. Pierwszy stanowi jednostkę centralną całego
mk, drugi został użyty do obsługi interfejsu USB. Dodatkowo mk posiada interfejs I2C oraz układy
do współpracy ze standardowymi magistralami równoległymi.
181
7. Współpraca z układami zewnętrznymi
Urządzenia zewnętrzne w tym przede wszystkim pamięć zewnętrzną stosuje się w dwóch
podstawowych przypadkach:
- kiedy pojemność pamięci wewnętrznej danych i/lub programu jest niewystarczająca i
- gdy w fazie badań prototypu urządzenia wygodniej jest korzystać z programów i danych
zapisanych w wymiennych pamięciach RAM/EPROM/EEPROM.
- kiedy mikrokontroler nie dysponuje wystarczającą liczbą lub odpowiednim rodzajem
układu peruferyjnego (np. sterownikiem wyświetlacza LCD)
Przy projektowaniu układu interfejsu pamięci lub innych układów zewnętrznych, podstawowe
znaczenie dla poprawnej ich pracy ma przebieg cyklu szyny adresów, danych i sygnałów sterujących,
pokazujący relacje między tymi sygnałami. Większość mikrokontrolerów realizuje kilka wariantów cyklu
szyny. W układzie 8xC196 (Intel), który posłuży nam dalej do ilustracji zagadnień dotyczących
współpracy z pamięciami zewnętrznymi, podstawowym rodzajem cyklu szyny jest cykl z
multipleksowaniem adresów i danych, przy czym adresy są 16-bitowe. W innych trybach adresy mogą
być j przesyłane w dwóch 8-bitowych porcjach lub w dynamicznie zmienianym trybie 8- i 16-bitowym.
Dodatkowo, w każdym z tych trybów możliwe jest stosowanie różnych rodzajów
synchronizacji zapisu i odczytu pamięci. W standardowym trybie pracy zewnętrzna pamięć jest
adresowana pełnym, w tym przypadku 16-bitowym adresem przesyłanym liniami AD[15 : 0]. Dane
są transmitowane i samymi liniami, niezbędne jest zatem multipleksowanie szyn. Zazwyczaj do
przesyłania adresów i danych wykorzystuje się wydzielone porty wejścia/wyjścia, które w
systemach pozbawionych zewnętrznych układów pamięci służą do komunikacji z otoczeniem.
Na rysunku 7.1 przedstawiono wyidealizowany przebieg cyklu szyny. Sygnał ALE powoduje
zatrzaśnięcie adresów w przyłączanym z zewnątrz zatrzaskowym (na przykład typu 74AC373). By
uniknąć nieporozumień i nie mylić adresów na szynie z adresem wpisanym do rejestru, zatrzaśnięty
adres będzie oznaczony symbolem MD[15 : 0]. Przy odczycie dane wyprowadzone z pamięci muszą
ustabilizować przed pojawieniem się aktywnego, dodatniego zbocza sygnału odczytu RD . Przy
zapisie natomiast dane muszą być na wyjściach MD odpowiednio wcześniej przed pojawieniem się
aktywnego, dodatniego zbocza sygnału zapisu WR . Przy transmisjach 16-bitowych wykorzystuje
się dodatkowo sygnał sterujący BHE (bus high enable) , który uaktywnia pamięć przechowującą
bardziej znaczące bajty danych.
Rysunek 7.1. Poglądowa ilustracja cyklu szyny
Jeśli MAO = 0, to aktywna jest pamięć przechowująca mniej znaczące bajty danych. W ten sposób
mikrokontroler może wykonywać transmisje 16-bitowych słów umieszczonych w komórkach
pamięci o parzystych adresach (MAO = 0, BHE = l), tylko bardziej znaczących bajtów
182
zlokalizowanych pod adresami nieparzystymi (MAO = l, i = 0) lub oddzielnie mniej i bardziej
znaczących bajtów (MAO = 0, BHE = 0). Jeśli pracujemy z pamięcią tylko do odczytu, wtedy
dekodowanie stanów BHE i MAO nie jest potrzebne. Jeśli zajdzie taka potrzeba, mikrokontroler
sam odrzuci niepotrzebną część odczytanych danych. Sygnały biorące udział w transmisji są
generowane synchronicznie z impulsami wewnętrznego zegara, a dokładniej z przebiegiem na
wyprowadzeniu CLKOUT, który jest ściśle związany z przebiegiem na wyprowadzeniu oscylatora
XT ALI. Cykl szyny nie zawierający dodatkowych opóźnień, nazywanych stanami oczekiwania
(ang. wait states) trwa w omawianym procesorze dwa okresy zegara. Pierwsze ujemne zbocze
CLKOUT generuje sygnał ALE i wyprowadza na szynę adres. Następujące po nim zbocze dodatnie
likwiduje sygnał ALE. Kolejne ujemne zbocze CLKOUT powoduje pojawienie się sygnału RD lub
WR. Ostatnie w cyklu ujemne zbocze zegara przy odczycie zatrzaskuje dane z szyny w
wewnętrznym rejestrze danych mikrokontrolera, natomiast przy zapisie oznacza, że na szynie są
ważne dane.
Przedstawiony powyżej cykl szyny odnosi się do współpracy z dostatecznie szybkimi
pamięciami zewnętrznymi (lub innymi urządzeniami), które są w stanie spełnić wymagane relacje
czasowe między sygnałami. Jeśli pamięć jest zbyt wolna, do cyklu szyny wstawiane są stany
oczekiwania. Każdy taki stan trwa przez dwa okresy zegara. W mikrokontrolerach, które są
zbudowane jako układy statyczne, liczba wprowadzanych stanów oczekiwania może być dowolnie
duża, natomiast w mikrokontrolerach zawierających układy dynamiczne liczba ta jest ograniczona.
Żądanie dodania! do cyklu szyny stanów oczekiwania układy współpracujące z mikrokontrolerem
sygnalizują podając sygnał READY.
Różnorodność trybów pracy szyny wymaga wprowadzenia mechanizmu, dzięki któremu
mikrokontroler mógłby jednoznacznie określić konfigurację zewnętrznego podsystemu pamięci. W
przypadku mikrokontrolera 8xC196 służy do tego rejestr konfiguracji CCR (ang. chip configuration
register), umieszczony w komórce o adresie 2018H w wewnętrznej lub zewnętrznej pamięci, w
zależności od stanu na wejściu EA (rysunek 7.2). Dwa bardziej znaczące bity LOCO i LOC1
określają rodzaj protekcji pamięci.
Może ona oznaczać na przykład zakaz zapisu (EPROM) lub zakaz odczytu (ROM/EPROM) przez
nieupoważnione programy. Stan LOCO = LOC1 = 1 oznacza, że pamięć nie jest objęta protekcją.
Kolejne dwa bity IRCO i IRC l oznaczają górny limit liczby stanów oczekiwania.
Rysunek 7.2. Rejestr konfiguracji pamięci w systemie z mikroprocesorem 8xC196
Kombinacja dwóch zer oznacza, że dozwolony jest maksymalnie jeden stan oczekiwania, natomiast
dwie jedynki pozwalają wprowadzić dowolną liczbę stanów oczekiwania. Następne trzy bity
definiują sposób sterowania szyną, który dokładniej zostanie opisany w dalszej części rozdziału.
183
Ostatni, najmniej znaczący bit określa, czy pamięć może być wyłączana (zezwolenie lub blokada
trybu power-down). Zawartość rejestru jest pierwszym bajtem pobieranym z pamięci po sygnale
RESET i nie może być zmieniana w trakcie pracy systemu.
7.1. Sterowanie szynami
W zależności od ustawienia rejestru CCR procesor może generować kilka różnych rodzajów
sygnałów sterujących szynami, przy czym wyprowadzenia ALE, WR i BHE spełniają podwójne
funkcje. Dzięki temu mikrokontroler jest przystosowany do współpracy z podsystemami pamięci o
różnych konfiguracjach bez potrzeby używania dodatkowych układów zewnętrznych do
wypracowania sygnałów sterujących.
Na rysunku 7.3a,b przedstawiono uproszczony diagram przebiegu sygnałów w czasie
standardowego cyklu szyny. Sygnał ALE pojawia się wraz z adresami i opada po ich
ustabilizowaniu wyznaczając moment zatrzaśnięcia adresów w rejestrze zatrzaskowym, Operacja
zapisu następuje po pojawieniu się na szynie danych, w chwili określonej przez sygnał WR. Jeśli
stosuje się transmisję 16-bitową dodatkowo wykorzystywany jest sygnał BHE. Za jego pomocą
można również uzyskać sygnały WRH i WRL do sterowania zapisem odpowiednio tylko bardziej
lub mniej znaczących bajtów. . Sposób generowania sygnałów WRH i WRL przedstawiono na
rysunku 7.3c.
Rysunek 7.3. Standardowy cykl szyny: a) w konfiguracji 16-bitowej, b) w konfiguracji 8-bitowej oraz
sposób generowania sygnałów WRH i WRL
Stosowanie zewnętrznych układów do generowania sygnałów WRH i WRL może nie być potrzebne
dzięki trybowi pracy ze strobowanym zapisem (ang. write strobe mode). Tryb ten jest wybierany,
jeśli bit 2 rejestru CCR jest wyzerowany. Przy transmisjach 16-bitowych sygnały WRL i WRH są
generowane wówczas na wyprowadzeniach WR i BHE, przy czym gnał WRL pojawia się przy
zapisach bajtów do komórek o adresach parzystych oraz przy zapisach słów 16-bitowych. Sygnał
WRH jest generowany przy zapisach bajtów do komórek o adresach nieparzystych i przy zapisach
słów 16-bitowych. Postać cyklu szyny w tym trybie pracy mikrokontrolera przedstawiono na
rysunku 7.4.
184
Rysunek 7.4. Cykl szyny w trybie zapisu ze strobem: a) transmisje 16-bitowe, b) transmisje 8-bitowe
Jeśli bit 3 w rejestrze CCR jest wyzerowany, mikrokontroler pracuje w trybie ze strobowaniem
ważnego adresu (ang. address valid strobe mode). Przebiegi sygnałów w czasie cyklu szyny
wykonywanego w tym trybie przedstawiono na rysunku 7.5. Sygnał ADV, który pojawia się po
ustabilizowaniu adresów zastępuje używany wcześniej sygnał ALE. Aktywny stan ADV trwa aż do
końca cyklu szyny, dzięki czemu sygnał ten można wykorzystać do sterowania wejściami wyboru
pamięci CS (ang. chip select).
Rysunek 7.5. Cykl szyny w trybie ze strobem ważnego adresu: a) transmisje 16-bitowe, b)transmisje 8bitowe
Możliwa jest również kombinacja obu tych trybów, czyli praca ze strobem ważnego adresu i
strobem zapisu. Postać cyklu szyny dla transmisji 16- i 8-bitowych w tym trybie przedstawiono na
rysunku 7.6.
Rysunek 7.6. Cykl szyny z oddzielnym sygnałem strobu ważnych adresów i strobem zapisu: a) transmisje
16-bitowe, b) transmisje 8-bitowe
185
Jak wynika z przedstawionego dotąd opisu cyklu szyny w omawianym mikrokontrolerze, może on
pracować z dwoma szerokościami szyny danych: 16-bitową i 8-bitową. Konfiguracja szerokości
szyny może odbywać się w trakcie pracy mikrokontrolera i być zmieniana. Tryb 16-bitowy oznacza
przesyłanie 16-bitowych adresów i 16-bitowych danych ze wspólną, multipleksowaną szynę,
natomiast tryb 8-bitowy oznacza przesyłanie 6-bitowych adresów i 8-bitowych danych, przy czym
multipleksowane jest mniej znaczące 8 bitów szyny adresowej. Tryb 8-bitowy jest zatem identyczny
jak w prostych 8-bitowych mikrokontrolerach, na przykład należących do rodziny x51.
Podczas cykli 16-bitowych porty 3 i 4 przesyłają dane i adresy, przy czym sygnał ALE jest używany
do zatrzaskiwania adresów. W trybie 8-bitowym multipleksowane jest tylko 8 mniej znaczących
bitów adresu, natomiast 8 bardziej znaczących bitów ma ważne wartości w czasie trwania całego
cyklu szyny.
Rysunek 7.7. Dwa warianty konfiguracji szyny mikrokontrolera: a) szyna 16-bitowa z
multipleksowaniem adresów i danych i b) szyna 8-bitowa z multipleksowaniem mniej znaczącego bajtu
Szerokość szyny może być zmieniana co cykl szyny, jeśli tylko bit l w rejestrze CCR zostanie
ustawiony podczas operacji RESET. W czasie pracy szerokość szyny jest zmieniana dynamicznie
przy użyciu sygnału doprowadzonego do wejścia BUSWIDTH. Jeśli na wejściu jest stan wysoki,
szyna ma szerokość 16-bitów, natomiast w przeciwnym przypadku szyna pracuje w trybie 8bitowym. Jeśli w rejestrze CCR bit l jest wyzerowany, sygnał BUSWIDTH nie je wykorzystywany.
System dynamicznych zmian szerokości szyny daje pożyteczne w praktyce możliwości. Na
przykład instrukcje mogą być pobierane z pamięci programu w trybie 16-bitowym, natomiast dane w trybie 8-bitowym. Dzięki temu nie trzeba stosować danych dwóch 8-bitowych pamięci RAM,
jeżeli pojemność jednej pamięci jest wystarczająca. Konfigurację tego typu uzyskuje się przez
połączenie wejścia BUSWIDTH mikrokontrolera z wejściem CS pamięci i sterowanie ich
wspólnym sygnałem.
Korzystając z trybu 8-bitowego do pobierania kodów instrukcji z pamięci programu należy
pamiętać, że mikrokontroler nie jest wówczas w stanie pracować z pełną wydajnością. W
szczególności, kolejka instrukcji w potoku może być w pewnych okolicznościach nie wypełniana.
7.2. Wstrzymanie dostępu do szyny
W rozbudowanych systemach cyfrowych, w których wspólna szyna łączy większą liczbę
rozproszonych mikrokontrolerów lub innych urządzeń wyposażonych we własne sterowniki szyny,
często zachodzi potrzeba blokowania dostępu mikrokontrolera do szyny po to, by inne urządzenie
mogło przejąć sterowanie i wykonać transmisję. Do tego celu służy mechanizm wstrzymywania
dostępu do szyny (ang. hold).
Do obsługi wstrzymań w omawianym mikrokontrolerze 8xC 196 (Intel) używa się trzech
sygnałów: HOLD, HLDA i BREQ. Urządzenie, które chce przejąć kontrolę szyną, wysyła żądanie
dostępu do szyny. Sygnał ten, podany na wejście HOLD mikrokontrolera wywołuje sekwencję
czynności przedstawionych na diagramie z rysunku 7.8.
186
Rysunek 7.8. Przebiegi sygnałów na szynie po zewnętrznym zgłoszeniu żądania wstrzymania dostępu do
szyny przez mikrokontroler
W odpowiedzi na sygnał HOLD mikrokontroler wysyła potwierdzenie zwolnienia szyny w postaci
sygnału HLDA (ang. hold acknowledge). Po wykorzystaniu szyny przez urządzenie zgłaszające
żądanie dostępu sygnał HOLD zostaje zdjęty. Mikrokontroler zdejmuje wówczas sygnał HLDA i
przejmuje z powrotem kontrolę nad szyną. W czasie wstrzymania dostępu do szyny mikrokontroler
może realizować program, nie może jednak korzystać z szyny zewnętrznej. Jeśli powstanie taka
potrzeba, mikrokontroler generuje sygnał BREQ, który wskazuje urządzeniom zewnętrznym, by
niepotrzebnie nie przetrzymywały dostępu do szyny. Sygnał BREQ jest zdejmowany razem z
sygnałem HLDA. W czasie trwania wstrzymania wyjścia danych, adresów, RD, WR, BHE i 1NST i
nieokreślone stany, natomiast wyjście ALU znajduje się w stanie niskim, przy czym możliwa jest
realizacja funkcji „zwartego lub" i połączenia linii ALE z różnych sterowników szyny. W
niektórych mikrokontrolerach wyprowadzenia sygnałów HOLD, HLDA i BREQ są niezależne, w
innych natomiast sygnały te są przekazywane przez wybrane linie portów wejścia/wyjścia i
wykorzystywane tylko w razie potrzeby. Na rysunku 7.9 przedstawiono dwa warianty reakcji
mikrokontrolera na sygnał wstrzymania. Efektywne przekazywanie dostępu do szyny przez różne
urządzenia wymaga by maksymalny czas między zgłoszeniem HOLD a potwierdzeniem
udostępnienia szyny HLDA był krótki. Czas ten jest nazywany opóźnieniem reakcji na wstrzymanie
(ang. hold lattency), a jego wielkość zależy od rodzaju cyklu szyny wykonywanego przez
mikrokontroler podczas nadejścia zgłoszenia HOLD.
187
Rysunek 7.9. Obsługa asynchronicznego sygnału wstrzymania HOLD: a) zgłoszonego z wyprzedzeniem
w stosunku do dodatniego zbocza zegara, b) zgłoszonego asynchronicznie
Badanie stanu wejścia HOLD jest przeprowadzane przy najbliższym dodatnim zboczu zegara,
jeśli tylko zgłoszenie wstrzymania wyprzedza to zbocze o minimalny odstęp czasu oznaczany
symbole THVCH Jeśli czas wyprzedzenia HOLD nie jest zachowany, zgłoszenie zostanie rozpoznane
dopiero przy następnym zboczu zegara (rysunek 7.9b). To samo dotyczy wyjścia ze stanu wstrzymania:
jeśli sygnał HOLD zostanie zdjęty z odpowiednim wyprzedzeniem w stosunku do najbliższego
dodatniego zbocza zegara, wyjście ze stanu wstrzymania i nastąpi razem z tym zboczem, a ściślej
biorąc po upływie niewielkiego odstępu czasu THVCH .
Większość mikrokontrolerów ma możliwość blokowania żądań wstrzymań. Opcja ta jest potrzebna na
przykład wtedy, gdy mikrokontroler musi wykonać serię odwołań do pamięci zewnętrznej w czasie
rzeczywistym, bez opóźnień wywołanych wstrzymaniami. Bit zezwolenia na wstrzymania HLDEN
(ang. hold enable) umieszczony w jednym z rejestrów specjalnych SFR mikrokontrolera może być
ustawiany i zerowany podczas wykonywania programu. Jeśli jednostka centralna zablokuje
wstrzymania (HLDEN = 0), a mikrokontroler znajduje się właśnie w stanie wstrzymania,
przywrócenie dostępu do szyny nastąpi dopiero po zakończeniu bieżącego cyklu wstrzymania.
7.3. Przyłączenie zewnętrznych pamięci RAM/ROM/EPROM
Zewnętrzne pamięci RAM / ROM / EPROM mogą być przyłączane do mikrokontrolerów na wiele
różnych sposobów. Na rysunku 7.10 pokazano najprostszą konfigurację, w której mikrokontroler
współpracuje z jednym zewnętrznym układem ROM / EPROM w trybie 8-bitowym.
188
Rysunek 7.10. Połączenie mikrokontrolera z jednym układem zewnętrznej pamięci ROM/EPROM w
trybie przesłań 8-bitowych
Do sterowania wejściem wyboru układu pamięci CS wykorzystano sygnał ADV. W rejestrze
konfiguracji pamięci CCR bit numer l jest wyzerowany, co powoduje, że system pracuje w trybie
przesłań 8-bitowych. Do zatrzaskiwania mniej znaczącego bajtu. użyto rejestru typu 373,
strobowanego sygnałem ADV. W przypadku nowoczesnych pamięci ROM / EPROM jest on
najczęściej niepotrzebny, ponieważ pamięć ma wbudowany rejestr zatrzaskowy adresu.
Jeśli w systemie potrzebne są dwie pamięci, jedna typu RAM, a druga nieulotna, można zastosować
konfigurację przedstawioną na rysunku 7.11. W układzie tym pamięć ROM/EPROM jest umieszczona w
dolnej połowie przestrzeni adresowej, natomiast pamięć RAM w górnej połowie. Jeszcze inaczej można
zorganizować pamięć w trybie 16-bitowym, z pamięcią stałą. Konfigurację połączeń pokazano na
rysunku 7.12.
Rysunek 7.11. Połączenie mikrokontrolera z pamięcią ROM/EPROM i pamięcią RAM
189
Rysunek 7.12. Połączenie mikrokontrolera z dwoma pamięciami w trybie 16-bitowym
Najbardziej pełna konfiguracja podsystemu zewnętrznej pamięci jest przedstawiona na rysunku 7.13, na
którym pokazano wariant z dynamicznie zmienianą szerokością szyny. Pamięci stałe przechowują kod
programu, natomiast dane są umieszczone w pamięci RAM. Należy zwrócić uwagę, że sygnał CS
wyboru pamięci RAM jest jednocześnie używany do sterowania wejściem BUSWIDTH i wymuszenia 8bitowego trybu pracy na szynie.
Rysunek 7.13. Połączenie pamięci w konfiguracji z dynamicznym wyborem szerokości szyny
Przedstawione powyżej proste warianty realizacji połączeń mikrokontrolera z pamięciami
zewnętrznymi wykorzystują bezpośrednie sterowanie sygnałami wyboru układów pamięci CS z
wyjścia ADV lub najbardziej znaczącym bitem adresu. W praktyce, zwłaszcza gdy w systemie
znajduje się wiele układów pamięci, takie rozwiązanie jest niewystarczające, nie pozwala bowiem
lokować pamięci o różnych pojemnościach w wybranych miejscach przestrzeni adresowej.
Znacznie wygodniejsze w użyciu są wówczas mikrokontrolery wyposażone we wbudowany dekoder
adresów i wyprowadzenia kilku lub nawet kilkunastu zdekodowanych sygnałów CS. Oprócz tego
niektóre mikrokontrolery mają dodatkowe wyjście wyboru pamięci, w której zapisano
oprogramowanie inicjujące pracę systemu (CSBOOT).
Stosując na przykład mikrokontroler 68HC16 można zewnętrzne pamięci przyłączyć w sposób
przedstawiony na rysunku 7.14.
190
Rysunek 7.14. Sterowanie pamięciami przez mikrokontroler wyposażony w wyjścia selekcji CS
Pamięć RAM została przyłączona do linii ośmiu bardziej znaczących bitów szyny danych. Przy
zapisie dane pojawiają się również na mniej znaczących bitach, ale nie ma to wpływu na pracę
pamięci ROM, która jest wówczas nieaktywna. Warto zauważyć, że 16-bitowa pamięć ROM jest
sterowana adresami ADDR[16 : l], to znaczy bit ADDR1 szyny jest połączony z wejściem adresowym
ADDR0 pamięci. Zapewnia to prawidłową pracę przy odczycie słowami 16-bitowymi. Pamięć RAM
jest wybierana sygnałem CSO mikrokontrolera, natomiast pamięć stała uaktywnia się po wystąpieniu
sygnału CSBOOT.
Na rysunku 7.15 przedstawiono natomiast sposób połączenia dwóch 8-bitowych pamięci
pracujących wspólnie jako układ 16-bitowy. Dodatkowo pokazano połączenie z pamięcią 16-bitową
typu ROM. Wyborem układów RAM sterują sygnały CSO i CS1, przy czym CSO wybiera pamięć
przechowującą bardziej znaczące bajty danych, natomiast CS1 wybiera pamięć zawierającą mniej
znaczące bajty. Wejścia strobu odczytu i zapisu obydwu układów są połączone z wyjściem R / W
mikrokontrolera. Zaletą przedstawionego rozwiązania jest brak jakichkolwiek zewnętrznych układów.
Nie jest potrzebne stosowanie ani rejestrów zatrzaskowych, ani najprostszych nawet dekoderów
adresów. Uproszczenia te wynikają po części stąd, że przykładowy mikrokontroler użyty do ilustracji
struktur bloków pamięci na rysunkach 7.14 i 7.15 ma rozdzielone szyny adresów i danych, a po części
z wykorzystania sygnałów wyboru układów (CS).
191
Rysunek 7.15. Konfiguracja 16-bitowej pamięci złożonej z dwóch układów 8-bitowych
Odmianą konfiguracji z rysunku 7.15 jest wariant połączeń przedstawiony na rysunku 7.16. Tu
również dwie 8-bitowe pamięci RAM tworzą razem jeden blok pamięci 16-bitowej, ale zastosowano
układy z oddzielnymi wejściami strobu odczytu OE i zapisu WE. Są one uzyskiwane z odpowiednich
wyjść CS mikrokontrolera. Wejścia wyboru układów RAM są połączone z masą, toteż obydwa układy
są zawsze gotowe do pracy.
Rysunek 7.16. Blok 16-bitowej pamięci RAM złożonej z dwóch układów 8-bitowych sterowanych
oddzielnymi sygnałami zapisu i odczytu
Przytoczone przykłady połączeń mikrokontrolerów z pamięciami zewnętrznymi nie wyczerpują
bogactwa możliwych wariantów budowy podsystemu pamięci RAM/ROM/EPROM. W
szczególności, jeśli w systemie wykorzystywane są zewnętrzne dynamiczne pamięci RAM (DRAM),
niezbędne jest zapewnienie odświeżania ich zawartości. Pamięci tego typu są wyposażone w wejścia
RAS (ang. rów address strobe) l i CAS (ang. column address strobe). Odświeżanie polega na
okresowym odczycie komórek pamięci przy odpowiednim wysterowaniu wejść RAS i CAS. Okres, w
którym pamięć musi być odświeżana, jest rzędu milisekundy. Zadanie to realizuje się dwoma
sposobami:
- z wykorzystaniem układów sterowania odświeżaniem wbudowanych do mikrokontrolera (np.
H8 Hitachi, i960 Intel, Y8000 NEC),
- przy użyciu zewnętrznego kontrolera pamięci DRAM.
Użycie wbudowanego kontrolera pamięci DRAM jest wygodniejsze, jednak tylko nieliczne
mikrokontrolery 8- i 16-bitowe są wyposażone w taki układ (por. p. 2.4).
W rozbudowanych systemach ze skomplikowaną mapą pamięci często zachodzi też potrzeba użycia
zewnętrznych dekoderów adresowych. Dotyczy to zwłaszcza systemów z mikrokontrolerami, które nie
mają wyjść CS. Dekodery adresowe buduje się z prostych układów kombinacyjnych, na przykład ze
scalonych dekoderów z wyjściem w kodzie ,.1 z 8" - uklad 74HCT138, albo przy użyciu
programowanych układów PLD.
7.4. Współpraca z pamięciami EEPROM i błyskowymi
Pamięci nieulotne EEPROM i błyskowe są coraz częściej stosowane w systemach
mikroprocesorowych ze względu na możliwość programowania ich zawartości w układzie, pracują
(ang. in-circuit programming). Jeśli pamięci te są zaprogramowane poza systemem i używane
wyłącznie jako ROM, mogą współpracować z mikrokontrolerami w taki sam sposób jak pamięci
ROM/EPROM. W szczególności, można je przyłączać do mikrokontrolera zgodnie z zasadami
192
podanymi w p.7.3, w konfiguracjach opisanych na rysunkach 7.10-7.16. Inaczej wygląda współpraca
mikrokontrolera z pamięciami błyskowymi i EEPROM w następujących przypadkach:
1) gdy pamięć błyskowa lub EEPROM ma być nie tylko odczytywana, ale również
programowana w układzie, w którym pracuje,
2) gdy pamięć jest wyposażona w szeregowe wejście i wyjście danych.
Analizę tych przypadków rozpoczniemy od omówienia współpracy mikrokontrolerów: tanimi
pamięciami EEPROM o niewielkich pojemnościach wyposażonych w szeregowe wejścia i wyjścia.
7.5. Przyłączanie pamięci EEPROM z dostępem szeregowym
Pamięci EEPROM z szeregowym wejściem i wyjściem danych są stosowane w miniaturowych
kontrolerach, w których ważny jest koszt wykonania układu, jego gabaryty, masa pobór mocy.
Pojemności pamięci tego typu nie przekraczają zwykle kilku kilobajtów, nadają się zatem do
wykorzystania w systemach z niezbyt skomplikowanym oprogramowaniem. Ich zaletą, oprócz niskiej
ceny i małych rozmiarów obudowy, jest standardowe cię zasilania równe zwykle +5V. Produkowane są
również pamięci zasilane napięciem +3V. Podobnie jak pamięci EEPROM z wejściami i wyjściami
równoległymi, układy pracujące w trybie szeregowym mają zwykle wbudowaną przetwornicę napięcia i
nie wymagają do programowania i kasowania zewnętrznego napięcia programującego.
W praktyce spotyka się dwie podstawowe odmiany pamięci EEPROM z szeregowym wejściem i
wyjściem danych:
- układy pracujące z niestandardowym protokołem wymiany danych,
- układy I2C EEPROM, w których zastosowano protokół komunikacji szeregowej opracowany
przez firmę Philips.
Przykładem pamięci EEPROM z dostępem szeregowym jest rodzina układów 93x6 produkowana
między innymi przez takie firmy, jak National, Catalyst, SGS Thomson rochip. Protokół wymiany
informacji nie jest zgodny z żadnym międzynarodowym standardem, wszystkie pamięci tej rodziny
wykorzystuj ą jednak identyczny zbiór poleceń dwójkowych potrzebnych do kasowania, programowania
i odczytu ich zawartości. Są dostępne w odmianach o pojemności l kb (128 x 8), 2 kb (256 x 8) oraz 4 kb
(512 x 8). Zasadniczą wadą tych układów, jak również innych rodzajów pamięci EEPROM, jest długi
czas zapisu informacji, wynoszący w przypadku układów z. serii 93x6 około 4 ms.
Do sterowania pamięci EEPROM z szeregowym dostępem stosuje się powszechnie dwie różne
metody:
− sterowanie przy użyciu linii portów wejścia/wyjścia mikrokontrolera oraz
− sterowanie przez interfejs komunikacji szeregowej.
Na rysunku 7.17 pokazano przykładową konfigurację połączenia pamięci EEPRCto typu 93C56 z
prostym mikrokontrolerem 8-bitowym typu 68HC705 (Motorola).
193
Rysunek 7.17. Przykładowe połączenie pamięci EEPROM z szeregowym dostępem do mikrokontrolera
przy użyciu linii portu wejścia/wyjścia mikrokontrolera
Pamięć jest połączona z mikrokontrolerem przez 4 linie portu PA. Spełniają one następując funkcje:
PAO - CS (ang. chip select), linia wyboru układu pamięci,
PA1 - SK (ang. serial clock), sygnał szeregowo przesyłanych impulsów synchronizujących
(zegarowych),
PA2 - DI (ang. serial data input), szeregowe wejście danych, PAS - DO (ang. serial data
output), szeregowe wyjście danych.
Procesor steruje pamięcią wysyłając do niej polecenia złożone z 3 bitów kodu polecenia, 8 bitów
adresu i ewentualnie 16 bitów danych. Formaty i znaczenie poszczególnych poleceń podano w tablicy
7. l.
Tablica 7.1. Formaty i funkcje poleceń sterowania pamięcią EEPROM
W układzie z rysunku 7.17 operacje zapisu, odczytu i kasowania pamięci EEPROM są wykonywane
przez odpowiednie procedury programowe. Tryb taki bywa nazywany obsługą przez programowe
przeglądanie (ang. polling). Przykładowy algorytm odczytu danych z pamięci w opisanej wcześniej
konfiguracji przedstawiono na rysunku 7.18. Założono przy tym dodatkowo, że pamięć może
przesyłać dane w trybie 16-bitowym, tak jak określa to tablica 7.1, oraz w trybie 8-bitowym. Wybór
trybu odbywa się przez odpowiednie ustawienie dodatkowego wejścia ORG/NC (nie pokazanego na
rysunku 7.17). Jeśli wejście to jest połączone z masą układu, pamięć pracuje w trybie 8-bitowym,
natomiast jeśli na wejściu jest stan wysoki - przesłania odbywają się słowami 16-bitowymi.
Po odpowiednim skonfigurowaniu portów mikrokontrolera polegającym w tym przypadku na
zdefiniowaniu kierunku transmisji w porcie PA, program wysyła polecenie WDS zabezpieczające
pamięć przed przypadkowym skasowaniem. Następnie w pętli odczytywane są kolejne słowa (lub
bajty dla trybu 8-bitowego).
194
Rysunek 7.18 Algorytm odczytu z pamięci EEPROM o dostępie szeregowym
Licznik przesłań N jest ustawiony przed wywołaniem procedury i zawiera liczbę słów (bajtów), które
procedura ma odczytać z pamięci oraz adres bufora w wewnętrznej pamięci mikrokontrolera, w której
zapisywane są odczytane dane. Przy każdym obiegu pętli wartość licznika jest zmniejszana o 1.
Jednocześnie inkrementowany jest adres pamięci.
Wygodniejszą metodą współpracy z pamięciami EEPROM o dostępie szeregowym jest wykorzystanie
portu transmisji szeregowej mikrokontrolera (UART, USART, SP itp.). Przykład połączenia
mikrokontrolera z pamięcią EEPROM przez port SPI pokazano na rysunku 7.19.
195
Rysunek 7.19. Współpraca mikrokontrolera z pamięcią EEPROM o dostępie szeregowym przez port
transmisji szeregowej SPI (Motorola)
Port szeregowy, jak jest to wyjaśnione szczegółowo w dalszej części rozdziału, może pracować w dwóch
podstawowych trybach: z zablokowanymi przerwaniami oraz z włączonym systemem przerwań. W
pierwszym przypadku program przegląda stan rejestrów portu i kolejno wysyła lub odczytuje dane. Tryb
ten jest zatem podobny do opisanego wcześniej wariantu z wykorzystaniem portu wejścia/wyjścia.
Korzyścią z zastosowania portu jest to, że konwersja równoległo-szeregowa i szeregowo-równoległa
danych odbywa się teraz nie programowo, ale sprzętowo. W trybie z przerwaniami program może
realizować inne zadania, podczas gdy trwa transmisja. Jednostka centralna jest angażowana tylko po
skompletowaniu danych w buforze portu szeregowym przy odbiorze po opróżnieniu bufora przy
wysyłaniu danych. Powiadomienie CPU o zakończeniu transmisji bajtu odbywa się za pomocą
mechanizmu przerwań. Źródłem przerwań jest w tym przypadku wewnętrzny układ portu szeregowego
mikrokontrolera. Oczywiście przed rozpoczęciem transmisji należy odpowiednio skonfigurować port
szeregowy. Sposób konfiguracji oraz funkcje poszczególnych linii portu SPI (SCK, MOSI, MISO)
omówione w jednym z następnych punktów.
7.6. Współpraca z pamięciami błyskowymi
Jeśli pominąć wejście zezwolenia na zapis (ang. write-enable), pamięci błyskowe można traktować
tak jak zwykłą pamięć EPROM. Z funkcjonalnego punktu widzenia rzeczywista różnica między
oboma rodzajami pamięci polega zatem wyłącznie na tym, że pamięć błyskową można kasować i
programować w sposób elektryczny. Jeśli chcemy korzystać z zaprogramowanej wcześniej pamięci
FLASH i tylko odczytywać jej zawartość, można posłużyć się konfiguracjami z rysunków 7.10 7.16. Zastosowane tam pamięci ROM/EPROM o pojemności 32 kB można zastąpić na przykład
pamięcią błyskową 28F256 o identycznej organizacji wewnętrznej. Pamięci błyskowe, podobnie jak
omówione wcześniej proste pamięci ERPROM z dostępem szeregowym przyjmują oprócz danych
polecenia, które umożliwiają realizację różnych rodzajów operacji. Przykład poleceń dla popularnej
pamięci typu 29F010 ced Micro Devices) o organizacji 128 k x 8 podano w tablicy 7.2.
196
Tablica 7.2. Formaty poleceń sterowania pamięcią błyskową 29F010 (AMD)
Znaczenie symboli użytych w tablicy 7.2 jest następujące:
RA - adres komórki pamięci do odczytu,
PA- adres komórki pamięci do zaprogramowania, określony w chwili wystąpienia opadającego
zbocza na wejściu WE pamięci,
SA. - adres sektora do skasowania,
RD - zawartość komórki pamięci o adresie RA,
PD - zawartość komórki pamięci o adresie PA.
Pamięć typu 29F010 jest podzielona na sektory, przy czym kasowanie można przeprowadzać tylko dla
wybranego sektora albo dla całej pamięci. Polecenie Read/R oznacza wprowadzenie pamięci w tryb
Read/Reset i umożliwia odczyt danych. Polecenie AUTO odczytuje typ układu i kod producenta
zapisany w pamięci, rozkaz Byte zapisuje dane do pamięci, natomiast polecenia Erase i Sector kasują
odpowiednio całą pamięć lub sektor (fragment pamięci o wielkości zależnej od jej wewnętrznej
organizacji).
Różne warianty połączeń pamięci błyskowej z mikrokontrolerem zostaną prześledzone na przykładzie
mikrokontrolera 80C51XA G3 (Philips). Procesor ten jest wytwarzany w kilku odmianach z różnymi
rodzajami wbudowanej pamięci RAM/ROM/0l Ma 20-bitową szynę zewnętrznych adresów i może
współpracować z pamięciami o pojemności do l MB.
Na rysunku 7.20 przedstawiono najprostszą konfigurację połączeń z pamięcią błyskową przy założeniu,
że nie jest potrzebna dodatkowa, zewnętrzna pamięć W konfiguracji tej oprogramowanie do ładowania
programu z pamięci błyskowej jest zapisane w wewnętrznej pamięci EPROM/OTP mikrokontrolera.
Również inicjację systemu wykonuje program w wewnętrznej pamięci stałej procesora (ang. bootfrom
ROM). Wymuszenie startu programu z wewnętrznej pamięci następuje przez podanie stanu wysokiego
na wejście EA (ang. external access). Po uruchomieniu wewnętrznego programu następuje odwołanie do
zewnętrznej pamięci błyskowej.
Rysunek 7.20. Połączenie pamięci błyskowej typu 29F010(AMD) o organizacji 128k x8 z mk80C51 XA
(Philips)
197
Zanim to jednak nastąpi, procesor musi zablokować wejście WAIT przez wpis odpowiedniego bitu do
rejestru BCR (ang. bus configuration register). W wyniku tego CPU nie będzie otrzymywać sygnałów
żądania wstawienia do cyklu szyny stanów oczekiwania. W tym przypadku stany oczekiwania nie są
potrzebne, ponieważ program jest przed wykonaniem przepisywany do wewnętrznej pamięci
mikrokontrolera. Program ładujący (ang. loader) jest zapisany również wewnątrz mikrokontrolera.
Inicjacja ładowania może nastąpić na sygnał z zewnątrz, doprowadzony na przykład przez UART. Zaletą
przedstawionej konfiguracji jest jej prostota i brak potrzeby stosowania dodatkowych układów
zewnętrznych. Ma ona jednak także wady. Najważniejszą jest to, że adresy procedur obsługi przerwań
(wektor przerwań) w procesorze XA są przechowywane w obszarze adresów 0-120H wewnętrznej
pamięci ROM, nie mogą być więc zmieniane. Programy zapisane w pamięci błyskowej muszą być
dopasowane do tych adresów, to znaczy muszą zawierać procedury obsługi w odpowiednich miejscach.
Ponadto początkowy adres startu aplikacji jest sztywno określony.
Inną wadą jest marnowanie początkowego obszaru 32 kB w pamięci FLASH, jeśli jest ona
umieszczona w mapie adresowej począwszy od adresu 0000H, ponieważ w obszarze tym znajduje się
wewnętrzna pamięć ROM mikrokontrolera. Wadą jest też wyższa cena mikrokontrolera XA z
wbudowaną pamięcią OTP w porównaniu z wersją bez pamięci stałej (ang. ROM-less) oraz
kłopotliwa emulacja programów, ponieważ nie są one umieszczone począwszy od 0000H. Sygnał
PSEN (ang. program store enable) jest strobem odczytu zewnętrznej pamięci programu.
Na rysunku 7.21 przedstawiono inny wariant połączenia mikrokontrolera 80C51 z zewnętrzną
pamięcią błyskową. Zastosowano mikrokontroler bez wewnętrznej pamięci ROM. Program inicjujący
pracę systemu (ang. boot program) jest umieszczony w zewnętrznej pamięci stałej o pojemności 4 kB.
W pamięci błyskowej przechowywany jest program aplikacji sterującej pracą systemu. Program
aplikacji jest umieszczony w obszarze adresowym zaczynającym się od adresu 0000H.
Rysunek 7.21. Połączenie mk 80XC51 XA z pamięcią błyskową i zewnętrzną pamięcią ROM
zawierającą program inicjujący
Program ładujący zapisano w zewnętrznej pamięci ROM ulokowanej w obszarze położonym
powyżej obszaru FLASH, od adresu 20000H. Po wystąpieniu sygnału RESET, lub po włączeniu
zasilania, system ładuje program aplikacji z pamięci błyskowej, ponieważ wejście EA jest
utrzymywane w stanie niskim.
Jeśli mikrokontroler otrzyma polecenie ponownego załadowania aplikacji z pamięci FLASH, na
przykład sygnałem z konsoli operatorskiej przyłączonej przez port UART, wykonywana aplikacja
generuje skok do programu ładującego w zewnętrznej pamięci ROM. Po załadowaniu nowej
198
aplikacji niezbędne jest wydanie programowego sygnału RESET w celu wznowienia pracy
aplikacji.
Zamiast układu ROM typu 82HS321 wykorzystanego w systemie z rysunku 7.21. możliwe jest,
oczywiście, użycie innej pamięci, na przykład EPROM typu 27Cxx. Jeśli w systemie potrzebna jest
większa pamięć FLASH, zamiast pojedynczej pamięci 29F010 stosuje się kilka takich układów lub
jeden układ o większej pojemności. Wejście zezwolenia CE pamięci należy wówczas połączyć nie z
linią A17, jak pokazano na rysi 7.21, ale z linią A19.
Organizacja mapy pamięci omawianego przykładowego systemu wymaga, by zapis do komórek
pamięci FLASH w obszarze adresów od 0000H do 01FFH w przypadku mikrokontrolera XA G3 i
w obszarze adresów od 0000H do 03FFH w przypadku mikrokontrolera XA S3 był wykonywany
przy użyciu instrukcji odwołań do pamięci zewnętrznej. Na liście instrukcji omawianego
mikrokontrolera, instrukcja ta ma oznaczenie mnę mnemoniczne MOVX. Jeśli zamiast instrukcji
MOVX w programie zostanie użyta instrukcja MOV stosowana przy przesłaniach wewnętrznych,
program odwoła się do wewnętrznej pamięci mikrokontrolera.
Konfiguracja połączeń mikrokontrolera XA z zewnętrzną pamięcią błyskową pokazana na rysunku
7.21 ma ważne zalety:
- system jest elastyczny; można stosować dodatkowe pamięci i swobodnie organizować mapę
pamięci,
- wektor przerwań jest zapisany w pamięci błyskowej i może być łatwo modyfikowany;
pozwala to na dopasowanie adresów przerwań do programu aplikacji w pamięci, a nie
odwrotnie, jak wymagała tego konfiguracja z rysunku 7.20,
- mikrokontroler XA bez wewnętrznej pamięci ROM jest tańszy niż wersja z pamięcią
ROM/OTP,
- ładowanie aplikacji zaczyna się zawsze od adresu 0000H,
- możliwa jest prosta emulacja w trakcie wykonywania aplikacji zapisanych w pamięci
błyskowej.
Do wad przedstawionej powyżej konfiguracji należy natomiast zaliczyć konieczność stosowania
zewnętrznej pamięci stałej (ROM/EPROM), kłopotliwe pierwsze uruchomienie systemu z pustą
pamięcią błyskową oraz większe gabaryty i pobór mocy systemu. W opisanych dwóch wariantach
połączeń mikrokontrolera z zewnętrzną pamięcią błyskową założono, że w systemie nie jest
potrzebna zewnętrzna pamięć RAM. Jeśli zachodzi konieczność użycia takiej pamięci, należy
zastosować połączenie mikrokontrolera z pamięciami według schematu z rysunku 7.22. Z zewnątrz
dołączona jest pamięć danych SRAM o pojemności 8 kB, którą w razie potrzeby można
powiększyć. Wewnętrzna pamięć EPROM/OTP w mikrokontrolerze jest w tej konfiguracji
zbyteczna, wykorzystuje się więc tanią wersję mikrokontrolera (ROM-less).
Po sygnale RESET lub po włączeniu zasilania uruchamiany jest program inicjujący, zapisany w pamięci
błyskowej, ponieważ wejście EA znajduje się w stanie niskim. W pamięci tej umieszczony jest również
program ładujący. Pamięć RAM jest „widziana" przez mikrokontroler podwójnie, zarówno w obszarze
pamięci programu i danych, i jest umieszczona począwszy od adresu 20000H.
Jeśli potrzebna jest zmiana (przeładowanie) zawartości pamięci błyskowej, program ładujący jest
kopiowany do pamięci RAM i wykonywany. Po zmianie programu zapisanego w pamięci błyskowej
należy, tak jak poprzednio, ponownie uruchomić program inicjujący (ang. re-boot), ale odbywa się to
teraz z wykorzystaniem kodu nowego programu aplikacji i polega po prostu na wykonaniu instrukcji
RESET (programowy sygnał RESET).
Podobnie jak we wcześniej omawianej konfiguracji, jeśli potrzebne jest zastosowanie pamięci błyskowej
lub SRAM o większej pojemności, można łatwo dodać kolejne układy, a wejścia wyboru układów CE
sterować sygnałem A19 zamiast A17.
199
Rysunek 7.22. Współpraca mk 80C51 XA z zewnętrzną pamięcią błyskową i zewnętrzną pamięcią RAM
Obszar pamięci RAM zostaje wówczas przesunięty do obszaru zaczynającego się od adresu 80000H.
Tak samo jak w poprzednio omawianej konfiguracji, zapis do komórek pamięci błyskowej o adresach z
przedziału OOOOH - 01FFH (XA G3) lub OOOOH - 03FFH (XAS3) jest możliwy tylko przy użyciu
instrukcji MOVX.
Zaletą metody współpracy z rysunku 7.22 jest prostota układu, niski koszt (mikrokontroler bez pamięci
ROM), łatwość modyfikacji wektora przerwań w pamięci FLASH, ładowanie programów od adresu
0000H i prosta emulacja aplikacji. Wadą jest natomiast to, że pamięć RAM nie jest umieszczona od
adresu 0000H, dlatego nie nadaje się do organizacji stosu.
Podobnie jak we wcześniej omawianym wariancie kłopotliwe jest też pierwsze uruchomienie systemu
Dostęp do pamięci FLASH przyłączonej do mikrokontrolera na jeden z wymienionych wyżej sposobów
realizuje się łatwo przy użyciu odpowiednich procedur zapisanych w języku asemblera lub C. Do zapisu
bajtu pod wskazany adres służy funkcja o następującej postaci (Philips):
200
Funkcja ZAPIS realizuje cykl zapisu zgodnie z formatem polecenia Byte w tablicy 7.2. Składa się z trzech
cykli WR, cyklu zapisu danej do pamięci oraz sprawdzenia poprawności zapisu. Po wykonaniu
procedury zwracana jest wartość 0, gdy programowanie zostało wykonane poprawnie, i wartość l, gdy
wystąpił błąd. Kasowanie zawartości całej pamięci realizuje natomiast następująca procedura:
201
Z powyższych przykładów widać, że o ile kasowanie pamięci błyskowej przebiega sprawnie i wymaga
jednego wywołania podanej wyżej procedury, o tyle programowanie jest bardziej czasochłonne,
ponieważ po zapisie każdej danej należy wykonać sprawdzenie prawności zapisu. W przypadku
kasowania sprawdzenie to jest wykonywane tylko raz po zakończeniu procedury kasowania całej
pamięci. Mimo tej komplikacji oraz często bardziej złożonego połączenia pamięci błyskowych z
mikrokontrolerem niż w przy-pamięci ROM/EPROM, pamięci błyskowe są coraz szerzej stosowane w
systemach zawierających mikrokontrolery. Największą łatwość konfigurowania systemów z
zewnętrznymi pamięciami, w tym również typu FLASH, zapewniają mikrokontrolery wyposażone w
wyjścia wyboru układów współpracujących (CS).
Na rysunku 7.23 przedstawiono przykład systemu z zewnętrzną pamięcią błyskową o organizacji 64k x
16 oraz z dwiema pamięciami SRAM o organizacji 32 k x 8. W systemie pracuje mikrokontroler z
rodziny 60HC16 wyposażony w wyjście CSBOOT do aktywacji pamięci zawierającej program
inicjujący oraz wyjścia CS do współpracy z pamięciami.
Rysunek 7.23. Konfiguracja połączeń zewnętrznych pamięci SRAM i FLASH z mk 68HC16
wyposażonym w wyjścia wyboru CS
W pamięci błyskowej umieszczony jest program inicjujący oraz dane. Odczyt i zapis przebiega słowami
16-bitowymi (wejście A0 pamięci jest połączone z linią adresową ADDR1). Dwie pamięci SRAM
przechowują odpowiednio bardziej i mniej znaczącej bajty danych. Pierwsza z nich współpracuje z
liniami danych DANE[15 : 8], a druga] z liniami DANE[7 : 0]. Wyborem obu pamięci sterują linie CS1 i
CS2. Konfiguracja taka jest znacznie bardziej przejrzysta i prostsza przy programowaniu niż podane
wcześniej konfiguracje połączeń dla mikrokontrolera XA. Wynika to przede wszystkim z możliwości
użycia linii wyboru układów.
7.7. Bezpośredni dostęp do pamięci
Bezpośredni dostęp do pamięci - DMA (ang. direct memory access) polega na wymianie informacji
między pamięciami i urządzeniami zewnętrznymi bez udziału jednostki centralnej. Do realizacji trybu
przesłań DMA wykorzystuje się mechanizm wstrzymań. Transmisja DMA jest obsługiwana przez
specjalizowane zespoły funkcjonalne nazywane kontrolerami DMA lub w skrócie - DMAC (ang. DMA
controller). Bloki DMAC mogą być wbudowane do mikrokontrolerów lub przyłączane z zewnątrz.
202
8. Mikrokontrolery DSP
W układach mikroprocesorowych stosowanych obecnie szczególną rolę zajęły procesory
sygnałowe DSP (ang. Digital Signal Processor).
Są to układy zaprojektowane do obróbki w czasie rzeczywistym sygnałów cyfrowych.
Najczęściej używaną funkcją procesorów DSP jest umiejętność wykonywania operacji mnożenia w
jednym cyklu rozkazowym, jest to możliwe dzięki zastosowaniu sprzętowego układu mnożącego.
Kolejną cechą procesorów DSP jest umiejętność kilkukrotnego dostępu do pamięci w jednym
cyklu rozkazowym. Umożliwia to procesorowi ładowanie instrukcji równolegle z pobieraniem
argumentów i/lub składowaniem w pamięci wyników poprzednich operacji.
Trzecią funkcją używaną dla przyspieszenia operacji arytmetycznych w procesorach DSP jest
specjalny układ generujący adresy. W chwili gdy zostaną odpowiednio skonfigurowane jego
rejestry, rozpoczyna on pracę „w tle” (bez używania głównej magistrali), przygotowując adres
wymagany do pobrania parametrów równolegle z wykonywaniem operacji arytmetycznej.
Ponieważ wiele algorytmów DSP wykorzystuje wielokrotne, powtarzające się obliczenia,
większość procesorów DSP umożliwia specjalne, efektywniejsze wykonywanie pętli. Pozwala to
programiście na zaimplementowanie następnej pętli bez wykonywania dodatkowych cykli
rozkazowych dla sprawdzenia i zmiany stanu licznika pętli lub utworzenia rozgałęzienia do
początku istniejącej pętli.
Tak wyposażone procesory, charakteryzują się ogromną szybkością działania i dużą mocą
obliczeniową.
8.1. Stałoprzecinkowe DSP na przykładzie ADSP 2181
ADSP-2181 jest mikrokomputerem jednoukładowym ukierunkowanym na przetwarzanie
sygnałów cyfrowych, czyli procesorem DSP od angielskiego skrótu "Digital Signal Procesor".
Wyprodukowany został w technologii CMOS 0.5 um. Wykorzystując zegar 33MHz wykonuje
każdą instrukcję w pojedynczym cyklu procesora, tj. w czasie 30ns. Jest produkowany jest w
obudowach TQFP i PQFP 128-pinowych. (W module EZ-Kit Lite zastosowano procesor z obudowę
PQFP.)Struktura blokowa procesora została pokazana na rysunku 8.1.
DATA ADDRESS
GENERATORS
Generatory Adresu
Danych
DAG1
DAG2
PROGRAM
SEQUENCER
POWERDOWN
CONTROL
PROGRAMOWALNE
WE/WY
WEWNĘTRZNA PAMIĘĆ
FLAGI
PAMOIĘĆ
PAMOIĘĆ
PROGRAMU DANYCH
BYTE DMA
CONTROLLER
ZEWNĘTRZNA
SZYNA
ADRESÓW
SZYNA ADRESÓW PAMIĘCI PROGRAMU
SZYNA ADRESÓW PAMIĘCI DANYCH
ZEWNĘTRZNA
SZYNA
DANYCH
SZYNA DANYCH PAMIĘCI PROGRAMU
SZYNA DANYCH PAMIĘCI DANYCH
JEDNOSTKI ARYTMETYCZNE
ALU
MAC
SHIFTER
PORTY SZEREGOWE
SPORT0
SPORT1
TIMER
WEWNĘTRZNY
PORT
DMA
SZYNA
DMA
Rdzeń budowy rodziny ADSP-2100
Rysunek 8.1. Budowa wewnętrzna procesora ADSP-2181
ADSP-2181 łączy bazową architekturę rodziny ADSP-21xx, na którą składają się:
203
- trzy jednostki obliczeniowe
- dwa generatory adresu danych
- generator adresu programu (program sequencer)
z dodatkowymi układami peryferyjnymi:
- dwoma portami szeregowymi
- 16-to bitowym wewnętrznym portem DMA
- bajtowym portem DMA
- programowalnym timerem
- portami wejścia-wyjścia
- kontrolerem przerwań oraz
- układem sterowania poborem mocy (Power Down)
- wewnętrzną pamięcią programu i pamięcią danych
Wymienione elementy spełniają w procesorze ADSP2181 następujące funkcje:
- trzy jednostki obliczeniowe - jednostki te przetwarzają bezpośrednio 16-to bitowe dane:
- ALU - odpowiada za wykonywanie standardowych operacji arytmetycznych i
logicznych
- MAC multiplier/accumulator - wykonuje w jednym cyklu procesora operacje:
mnożenia, mnożenia/dodawania, mnożenia/odejmowania. Wynik obliczeń tych
operacji może być nawet 40-to bitowy
- SHIFTER - wykonuje logiczne oraz arytmetyczne przesunięcie, normalizację,
denormali-zację oraz wyprowadza wykładnik potęgi. Shifter może być użyty do
sprawnego implementowania obliczeń zmiennoprzecinkowych
- dwa generatory adresu danych - elementy te o nazwach DAG1 i DAG2, dostarczają adresy
dla równoczesnego pobrania argumentu z pamięci danych oraz z pamięci programu. Każdy
układ utrzymuje oraz aktualizuje cztery wskaźniki adresu
- generator adresu programu (program sequencer) - układ przy pomocy generatorów adresu
danych zapewnia sprawne dostarczenie argumentów operacji do jednostek obliczeniowych.
Poza tym inicjuje skoki warunkowe, wywołania podprogramów, oraz powroty z
podprogramów w pojedynczym cyklu rozkazowym. Dzięki niemu procesor ADSP-2181
wykonuje np. kod pętli warunkowej bez żadnych sprecyzowanych instrukcji skoku
- dwa porty szeregowe - o nazwach SPORT0 i SPORT1 służą do komunikacji z innymi
urządzeniami. Umożliwiają uruchomienie mechanizmu buforowania transmisji szeregowej.
- 16-to bitowy wewnętrzny port DMA - o nazwie IDMA służy do połączenia procesora DSP z
zewnętrznym systemem mikroprocesorowym. Skład się on z 16 sygnałów danych/adresów
oraz 5 sygnałów sterujących
- bajtowy port DMA (BDMA) - jest dwukierunkowym portem umożliwiającym adresowanie
pamięci zewnętrznej RAM oraz ROM do wielkości 4MB. Pozwala to na przechowywanie
bardzo dużych bloków danych
- programowalny timer - jest układem licznikowym umożliwiającym odliczanie czasu oraz
generację przerwań
- porty wejścia wyjścia - składa się na nie osiem programowalnych pinów wejścia/wyjścia,
trzy piny wyjściowe oraz dwa dodatkowe sygnały dostępne przy alternatywnej konfiguracja
SPORT1
- kontroler przerwań - jest układem umożliwiającym sprawowanie nadzoru oraz podjęcie
właściwej reakcji na 11 różnych przerwań
- układ sterowania poborem mocy (Power Down) - służy do obniżenia poboru mocy procesora
w przypadku np. aplikacji o zasilaniu bateryjnym
- wewnętrzna pamięć programu i danych. - ten 80 kbajtowy obszar pamięci wewnętrznej (onchip) skonfigurowanej jako 48kB pamięci RAM programu oraz 32kB pamięci RAM danych
umożliwia sprawne wykonywanie programu oraz obliczeń.
204
Elastyczna struktura oraz obszerny zestaw instrukcji pozwala procesorowi na wykonanie wielu
operacji równolegle. W jednym cyklu procesor może w związku z tym np.:
- generować nowe adresy programu
- pobierać nowe instrukcje
- wykonać jedno lub dwa przesłania danych
- modyfikować jeden lub dwa wskaźniki adresów danych
- wykonać operację obliczeniową.
Wykonanie powyższych operacje nie koliduje z pracą innymi czynnościami procesora, który może
równocześnie:
- otrzymywać oraz transmitować dane poprzez dwa porty szeregowe
- otrzymywać i/lub transmitować dane poprzez wewnętrzny port DMA
- otrzymywać i/lub transmitować dane poprzez port bajtowy DMA
- zmniejszać wartość timera.
Rysunek 8.2.pokazuje budowę procesora ADSP-2181 w sposób bardziej szczegółowy, pozwalający
na opisanie mechanizmów wymiany danych między jego elementami.
POWER
DOWN
CONTROL
LOGIC
INSTRUCTION
REGISTER
DAG1
Data
Address
Generator
#1
PROGRAM
SRAM
16K x 24
DAG1
Data
Address
Generator
#1
DATA
SRAM
16K x 24
BYTE
DMA
CONTROLLER
PROGRAM
SEQENCER
2
PROGRAMMABLE
I/O
8
3
FLAGS
14
MUX
14
SZYNA PMA
14
ZEWNĘTRZNA
SZYNA
ADRESU
SZYNA DMA
24
24
SZYNA PMD
BUS
EXCHANGE
16
MUX
ZEWNĘTRZNA
SZYNA
DANYCH
SZYNA DMD
COMPANDING
CIRCUITRY
INPUT REGS
INPUT REGS
INPUT REGS
ALU
MAC
SHIFTER
OUTPUT REGS
OUTPUT REGS
OUTPUT REGS
TRANSMIT REG
TRANSMIT REG
RECEIVE REG
RECEIVE REG
SERIAL
PORT0
SERIAL
PORT1
TIMER
16
INTERNAL
DMA
PORT
16
4
5
5
INTERRUPTS
SZYNA R
Rysunek 8.2. Budowa wewnętrzna procesora ADSP-2181
Jak widać wewnętrzna szyna wyniku (R) łączy jednostki obliczeniowe w taki sposób, że wyjście
dowolnej jednostki może być wejściem innej dowolnej jednostki w kolejnym cyklu.
Dwa generatory adresów danych DAG1 i DAG2 dostarczają adresy niezbędne do równoczesnego
pobrania argumentu z pamięci danych oraz z pamięci programu. Każdy układ DAG utrzymuje oraz
aktualizuje cztery wskaźniki adresu. Pojedynczy generator adresu danych (DAG) posiada trzy
rejestry:
- (M) Modify
- (I) Index
- (L) Length.
Każdy z nich zawiera po cztery rejestry 14-to bitowe, które mogą być bezpośrednio czytane bądź
zapisywane na szynę DMD. Rejestr I (I0-I3 w generatorze DAG1, I4-I7 w generatorze DAG2)
205
zawiera aktualne adresy pamięci. Rejestr L (L0-L3 w generatorze DAG1, L4-L7 w generatorze
DAG2) zawiera długości buforów. Rejestr M (M0-M3 w generatorze DAG1, M4-M7 w generatorze
DAG2) zawiera wartość modyfikacji adresu. Generatory adresu umożliwiają dwa typy adresowania:
adresowanie liniowe i kołowe. Wartość rejestru L korespondująca z rejestrem I (np. L0 może
korespondować z I0) decyduje, który schemat adresowania zostanie użyty. Przy adresowaniu
liniowym należy wyłączyć logikę modułu poprzez ustawienie rejestru korespondującego L na
wartość „0”. Przy adresowaniu buforu kołowego rejestr L jest ustawiony na długość bufora różną od
zera.
Sprawny transfer danych uzyskuje się, dzięki użyciu pięciu wewnętrznych szyn:
- szyny PMA Program Memory Address
- szyny PMD Program Memory Data
- szyny DMA Data Memory Address
- szyny DMD Data Memory Data
- szyny R Result.
Dwie szyny adresów PMA i DMA tworzą pojedynczą, multipleksowaną, zewnętrzna szynę
adresową. Dwie szyny danych PMD i DMD w podobny sposób tworzą pojedyncza,
multipleksowaną, zew. szynę danych.
Pamięć programu może przechowywać zarówno instrukcje jak i dane, pozwalając procesorowi
ADSP-2181 na pobranie dwu argumentów w pojedynczym cyklu: jeden z pamięci programu oraz
jeden z pamięci danych. ADSP-2181 może pobierać z pamięci programu w tym samym cyklu
argument oraz następną instrukcję. Pamięć programu stanowi przestrzeń o szerokości 24-bitów
(trzech bajtów). ADSP-2181 ma możliwość adresowania 16K słów wewnętrznej pamięci programu
RAM, co pozwala na dysponowanie pamięcią o wielkości 48Kbajty (3bajty • 16K=48Kbajty).
Pamięć danych jest przestrzenią o szeroką 16 bitów, użytą do magazynowania danych oraz
rejestrów kontrolnych. ADSP-2181 ma możliwość adresowania 16k słów wewnętrznej pamięci
danych lecz dla użytkownika dostępnych jest 16352 słów, ponieważ ponieważ resztę pamięci
zajmują 32 zmapowane rejestry.
ADSP-2181 posiada 16-to bitowy port (IDMA) łączący szynę PMD z szyną DMD. Jest on
wykorzystywany do podłączania układów zewnętrznych. Port IDMA składa się z 16 pinów
danych/adresów oraz 5 kontrolnych pinów. Port IDMA umożliwia bezpośredni dostęp do pamięci
programu oraz danych RAM.
Sygnały pochodzące z nieużywanego portu IDMA są dostępne na złączu P3 modułu EZ-KIT.
Dwukierunkowy Port BDMA może bezpośrednio adresować do 4MB zewnętrznej pamięci RAM
oraz ROM wykorzystywanej do podręcznego przechowywania programu lub danych.
ADSP-2181 zawiera dwa szeregowe porty (SPORT0 i SPORT1). Szeregowy port SPORT0 służy
do przesyłania danych i komunikacji z innymi urządzeniami mającymi łącza szeregowe
synchroniczne lub asynchroniczne. Port SPORT1 służy opcjonalnie do wymiany danych z głównym
komputerem, lub może być skonfigurowany jako wejście i wyjście dwustanowe.
ADSP-2181 może odpowiadać na 11 źródeł przerwań, sześć zewnętrznych (jedna wyzwalana
zboczem, dwie poziomem oraz trzy z możliwością konfigurowania) oraz pięć wewnętrznych
generowanych poprzez:
- timer
- porty szeregowe (SPORTs)
- port Byte DMA oraz
- układy sterowania poborem mocy
- sygnał RESET
ADSP-2181 zapewnia 13 uniwersalnych bitów wejścia/wyjścia - flag. Osiem z nich można
zaprogramować dowolnie jako wejścia lub wyjścia. Trzy flagi są na stałe skonfigurowane jako
206
wyjścia. Dwie ostatnie flagi, z których jedna jest wejściem a druga wyjściem, są przypisane do portu
SPORT1
W procesorze istnieje również programowalny timer generujący przerwania. Jest on zbudowany
w oparciu o 16-to bitowy rejestr zliczający (TCOUNT), którego wartość jest zmniejszana po
każdych n cyklach procesora, gdzie n jest wartością przechowywaną w 8 bitowym rejestrze
(TSCALE). Kiedy wartość rejestru licznika osiąga zero, generowana jest przerwanie, a do rejestru
zliczającego wpisywana jest powtórnie wartość z 16-to bitowego rejestru okresu (TPERIOD).
Na rysunku 8.3 pokazano wszystkie rejestry specjalne procesora ADSP-2181. Rejestry te mogą
mieć znaczenie bitowe lub mogą przechowywać wartości - liczby. Przykładowo: rejestr AX0
zawiera jeden z operandów jednostki arytmetyczno-logicznej ALU, rejestr I4 przechowuje wartość
adresu DAG2. Rejestry bitowe składają się z bitów kontrolnych, pól, lub flag stanu. Na przykład:
- rejestr ASTAT zawiera flagi stanu operacji arytmetycznych
- bity w rejestrze DWAIT określają opóźnienie cyklu odczytu lub zapisu danych, dla
różnych zakresów adresów mapy pamięci
- rejestry PMOVLAY i DMOVLAY określają wielkość przestrzeni adresowej dla pamięci
danych oraz programu. (Rejestry te mogą być użyte w instrukcjach przesyłania danych.)
Niektóre rejestry są dostępne w obszarze pamięci danych. Są to:
- System Control Register
- DWAIT
- timer
- port IDMA
- port IDMA
- SPORT
Rejestry te położone są pod adresami pokazanymi w poniższej tabeli.
Tablica 8.1. Położenie rejestrów procesora ADSP 2181
Nazwa rejestru
Adres
Nazwa rejestru
Sys_Crtl_Reg
0x3fff
Sport0_Ctrl_Reg
Dm_Wait_Reg
0x3ffe
Sport0_Sclkdiv
Tperiod_Reg
0x3ffd
Sport0_Rfsdiv
Tcount_Reg
0x3ffc
Sport0_Autobuf_Ctrl
Tscale_Reg
0x3ffb
Sport1_Ctrl_Reg
Sport0_Rx_Words1
0x3ffa
Sport1_Sclkdiv
Sport0_Rx_Words0
0x3ff9
Sport1_Rfsdiv
Sport0_Tx_Words1
0x3ff8
Sport1_Autobuf_Ctrl
Sport0_Tx_Words0
0x3ff7
Prog_Flag_Comp_Sel_Ctrl
Prog_Flag_Data
0x3fe5
BDMA_External_Address
BDMA_Word_Count
0x3fe4
BDMA_Internal_Address
BDMA_Control
0x3fe3
IDMA_Control
Pokazane wartości rejestrów są wartościami obowiązującymi po resecie procesora.
207
Adres
0x3ff6
0x3ff5
0x3ff4
0x3ff3
0x3ff2
0x3ff1
0x3ff0
0x3fef
0x3fe6
0x3fe2
0x3fe1
0x3fe0
Rysunek 8.3. Rejestry procesora ADSP-2181
208
8.2. Zmiennoprzecinkowe DSP na przykładzie ADSP-21061 SHARC
Procesor ADSP-21061 SHARC – Super Harvard Architecture Computer – jest nowoczesnym
32-bitowm mikrokomputerem jednoukładowym specjalizowanym do przetwarzania sygnałów
cyfrowych (Digital Signal Processor). Może być wykorzystywany do przetwarzania mowy,
dźwięku, grafiki czy obrazu. Został on zaprojektowany i wykonany w oparciu o nowoczesny rdzeń
zmiennoprzecinkowy i uzupełniony dwuportową pamięcią SRAM oraz obsługą zintegrowanej
magistrali I/O. Dzięki zawartej w strukturze procesora pamięci „cache” oraz specjalnej
architekturze, możliwe jest wykonywanie wszystkich instrukcji w pojedynczym cyklu.
Architektura Super Harvard jaką wykorzystano do budowy procesora ADSP-21061
charakteryzuje się rozdzieleniem pamięci programu i pamięci danych, co umożliwia równoczesne
pobieranie instrukcji i operandów, a w efekcie przyspiesza pracę procesora. Do poprawnej pracy
takiego układu wymagane są cztery niezależne magistrale: adresowa pamięci programu PMA Bus
(24-bit), danych pamięci programu PMD Bus (48-bit), adresowa pamięci danych DMA Bus (32-bit)
oraz danych pamięci danych DMD Bus (40-bit).
Procesor taktowany jest zewnętrznym sygnałem zegarowym o częstotliwości 40 MHz, co przy
zastosowaniu opisywanej wyżej architektury oraz umieszczonych w rdzeniu procesora trzech
niezależnych, pracujących równolegle jednostkach liczących, pozwala osiągnąć szybkość
przetwarzania 40 MIPS oraz szybkości obliczeń: średnio 80 MFLOPS i maksymalnie 120
MFLOPS. Czas wykonywania jednej instrukcji wynosi 25 ns.
Procesor posiada 1 Mbit wewnętrznej pamięci SRAM oraz 32Ksłów pamięci „cache”, dwa
porty szeregowe synchroniczne mogące przesyłać dane z prędkością 40 Mbit/s oraz zewnętrzną
szynę danych i szynę sterującą, pozwalające na równoległą pracę sześciu procesorów z dostępem do
zewnętrznej pamięci danych lub do wewnętrznej pamięci każdego ze współpracujących
procesorów.
Procesor oferuje dwa tryby pracy ograniczające pobór mocy: idle oraz idle16. W trybie idle
procesor oczekuje przez nieograniczony czas, ze zmniejszonym poborem mocy, na przyjście
niemaskowanego przerwania natomiast w trybie idle16 dodatkowo jest spowalniany wewnętrzny
zegar procesora do 1/16 częstotliwości podstawowej co jeszcze bardziej ogranicza pobór energii. W
trybie idle16 przerwania są obsługiwane 16 razy wolniej.
Budowa wewnętrzna procesora
Struktura wewnętrzna procesora zawiera:
- trzy niezależne jednostki obliczeniowe, pracujące równo-legle, wykonujące operacje
zmiennoprzecinkowe na danych 32-bitowych pojedynczej prec-yzji lub 40-bitowych
rozszerzo-nej precyzji, są to: ALU, multiplier i shifter;
- zbiór rejestrów wymiany danych (Data Register File);
- dwa generatory adresu (DAG1, DAG2);
- sekwenser programu z pamięcią podręczną (Program Sequencer) ;
- timer;
- dwuportową pamięć SRAM (Dual-Ported SRAM);
- dodatkowy port do komunikacji z zewnętrzną pamięcią i peryferiami (External Port);
- interfejs współpracy z innymi procesorami (Multiprocessor Interface);
- sterownik kanałów DMA (DMA Controller);
- dwa porty szeregowe (Serial Ports);
- port testujący (JTAG).
209
INSTRUCTION
TIMER
CACHE
32 x 48-Bit
BLOCK 0
BLOCK 1
Dual-Ported SRAM
AAAAA
Core Processor
AAAAAAA
JTAG
7
Test &
Emulation
DAG 1
8 x 4 x 32
PROCESSOR PORT
PROGRAM
DAG 2
8 x 4 x 24
SEQUENCER
I/O PORT
AAAAAAA
AA A
IOD
48
PM Address Bus (PMA) 24
External Port
IOA
17
PMA
32
EPA
DM Address Bus (DMA) 32
DMA
MULTIPROCESSOR
PM Data Bus (PMD)
Bus
INTERFACE
48
PMD
Connec t
DM Data Bus (DMD)
(PX)
48
EPD
DMD
32/40
HOST INTERFACE
A
BARREL
SHIFTER
IOA
16 x 40-Bit
EPA
DATA
REGISTER
FILE
IOD
EPD
DMD
PMD
A
AA
A
MULTIPLIER
DMA
4
CONTROLLER
IOP
REGISTERS
ALU
6
SERIAL PORTS
(2)
6
I/O Processor
Rysunek 8.4. Schemat blokowy procesora
Jednostka ALU (ang. Arithmetic/Logic Unit) jest odpowiedzialna za wykonywanie
standardowych operacji arytmetycznych i logicznych.
Multiplier wykonuje w jednym cyklu procesora operacje: mnożenia, mnożenia/dodawania,
mnożenia/odejmowania.
Shifter wykonuje arytmetyczne przesunięcie, normalizację, denormalizację, wyprowadzanie
wykładnika potęgi oraz operacje na bitach: ustawianie, zerowanie, zmianę stanu, testowanie.
Zbiór rejestrów wymiany danych jest zestawem rejestrów, przy pomocy których odbywa się
wymiana danych między jednostkami obliczeniowymi i szynami danych.
Generatory adresów dostarczają adresy niezbędne do równoczesnego pobrania instrukcji z
pamięci programu oraz argumentu z pamięci danych. Generatory adresu umożliwiają adresowanie
liniowe i kołowe.
Sekwenser programu przy pomocy generatora adresów zapewnia sprawne dostarczanie
argumentów operacji do jednostek obliczeniowych. Sekwenser inicjuje skoki warunkowe,
wywołanie podprogramów oraz powroty w pojedynczym cyklu. Dzięki niemu możliwe jest
wykonywanie pętli bez sprecyzowanych instrukcji skoku. Sekwenser jest wykorzystywany także w
czasie obsługi przerwań oraz trybu bezczynności (idle).
Pamięć podręczna “cache” ma rozmiar 32 Ksłów i sekwenser korzysta z niej w przypadku
operacji powtarzających się. Takie zachowanie powoduje, że układ nie musi pobierać kolejnych
instrukcji z pamięci programu lecz możne je pobrać z szybszej pamięci podręcznej.
Programowalny timer dostarcza cyklicznych przerwań, rejestr licznika jest automatycznie
przeładowywany po każdym zakończeniu liczenia.
210
Dwuportowa pamięć SRAM o pojemności 1Mbit jest skonfigurowana w dwa bloki po 0,5Mbit
z możliwością niezależnego dostępu przez rdzeń procesora, sterownik I/O lub sterownik DMA.
Dwuportowa organizacja pamięci i oddzielne magistrale wewnętrzne pozwalają na dwa transfery
danych z rdzenia oraz jeden z układu I/O w jednym cyklu procesora.
Zastosowanie w procesorze dodatkowego portu do komunikacji z pamięcią zewnętrzną i
peryferiami umożliwia zaadresowanie do 4-giga słów pamięci zewnętrznej. Port ten integruje
wewnętrzne magistrale adresowe i danych w jedną 32-bitową magistralę adresową oraz jedną 48bitową magistralę danych.
Interfejs współpracy z innymi procesorami umożliwia połączenie ze sobą do sześciu
procesorów mogących równolegle wykonywać operacje (możliwość ta może być wykorzystana przy
skomplikowanych algorytmach). Wszystkie połączone ze sobą jednostki mają możliwość dostępu
do jednej wspólnej pamięci zewnętrznej oraz swoich pamięci wewnętrznych. Wymiana danych
między procesorami może odbywać się z prędkością do 240 Mbit/s.
Sterownik DMA umożliwia bezpośredni transfer danych bez zaangażowania procesora.
Sterownik pracuje niezależnie i niewidocznie dla rdzenia procesora gdy ten w tym czasie wykonuje
program. Kanały DMA pośredniczą w transferze między pamięcią wewnętrzną i zewnętrzną oraz
peryferiami, a także między pamięcią wewnętrzną i portami szeregowymi.
Do komunikacji z innymi układami procesor może wykorzystywać dwa synchroniczne porty
szeregowe. Taktowanie procesora z pełną prędkością pozwala na przesyłanie danych przez porty
szeregowe z szybkością do 40 Mbit/s. Niezależne funkcje odbioru i wysyłania pozwalają na bardzo
elastyczne użytkowanie portów szeregowych. Mogą one również automatycznie przesyłać dane do i
z- pamięci zewnętrznej przez kanał DMA. Możliwe jest synchronizowanie portów za pomocą
sygnałów generowanych przez procesor lub sygnały zewnętrznie.
211
9. Programowanie mikrokontrolerów
W odróżnieniu od programowania komputerów do zadań związanych z przetwarzaniem i archiwizacją
danych (obliczenia numeryczne, bazy danych, edycja tekstów itp.), programowanie sterowników z
wbudowanymi mikrokontrolerami jest znacznie ściślej związane z architekturą samego procesora i
jego sprzętowego otoczenia. W ostatnich latach nastąpił w tej dziedzinie znaczny postęp. Język
asemblera, aczkolwiek wciąż niezbędny w wielu zastosowaniach, jest stopniowo wypierany przez języki
C/C++. Do programowania mikrokontrolerów zaczęto też używać języka Java opracowanego przez Sun
ticrosystems do tworzenia przenośnych aplikacji.
Dużym ułatwieniem dla programistów mikrokontrolerów jest popularyzacja językówów C i C++.
Kompilatory tych języków są dziś dostępne dla praktycznie wszystkich produkowanych typów
mikrokontrolerów. Mimo znacznego postępu w zakresie optymalizacji kodu programu produkowanego
przez kompilatory C/C++, języki te wciąż są mniej efektywne od asemblerów. Jeśli zatem warunki
pracy systemu w czasie rzeczywistym narzucają szczególnie krytyczne wymagania wobec szybkości
działania programu, język asemblera jest niezastąpiony. Połączenie zalet programowania w języku
asemblera z korzyściami, jakie daje język wysokiego poziomu jest możliwe przy zastosowaniu
mieszanych technik programowania, w których newralgiczne fragmenty programu projektuje się w
języku asemblera, a pozostałą część programu w języku C/C++. W niniejszym rozdziale przedstawiono
zarys problemów związanych z wykorzystaniem obu tych języków, przy czym założono, że Czytelnik
zna podstawy programowania w języku C/C++. Ponieważ, jak powiedziano wcześniej, o
programowaniu mikrokontrolerów nie można mówić w oderwaniu od ich architektury, w podanych dalej
przykładach posłużono się głównie architekturą popularnej rodziny układów x51.
9.1. Programowanie w języku asemblera
Programowanie w języku asemblera stosuje się w trzech przypadkach:
1) gdy tworzona aplikacja jest bardzo prosta i zapis w języku asemblera nie sprawia kłopotu,
2) gdy nie dysponujemy kompilatorem C/C++ lub jego koszt byłby niewspółmierny do skali
projektu i
3) gdy wymagania wobec szybkości działania programu i minimalizacji zajmowanej pamięci są
szczególnie ostre.
Do zalet programowania w języku asemblera należy zaliczyć:
1) możliwość pełnego panowania nad zasobami systemu; programista ma nieograniczony
dostęp do wszystkich bloków na poziomie rejestrów i pojedynczych bitów; żadna z funkcji
systemu nie jest ukryta; w szczególności możliwe jest dowolne, nawet nietypowe
oddziaływanie na obszar stosu i mechanizm przerwań,
2) swobodne dysponowanie obszarem pamięci,
3) efektywny program wynikowy; szybszy i zajmujący na ogół znacznie mniej pamięci niż
równoważny program zapisany w języku wysokiego poziomu,
4) możliwość swobodnego wyboru formatu danych i precyzji obliczeń; programista może
samodzielnie definiować wielobajtowe struktury danych do obliczeń o praktycznie dowolnej
dokładności,
5) możliwość dopasowania algorytmu do indywidualnych cech architektury mik kontrolera
oraz optymalizacji programu wynikowego.
Niestety, zastosowanie asemblera ma też i wady. Programowanie jest żmudne i zajmuje więcej
czasu niż przy użyciu języków wysokiego poziomu. Program jest zatem droższy, trudniejszy do
modyfikowania, bardziej podatny na błędy i mniej czytelny, nawet jeśli zastosowano obszerne
komentarze.
Projektowanie oprogramowania w języku asemblera przebiega według schematu przedstawionego na
rysunku 9.1.
212
Rysunek 9.1. Cykl projektowania oprogramowania w języku asemblera
W większości przypadków wykorzystuje się w tym celu komputer PC. Programy edytora, asemblera,
program łącząco-ładujący (ang. linking-\-loader) i śledzący (debuger) są instalowane w PC albo jako
oddzielne aplikacje DOS, lub Unix, albo też jako zintegrowane środowisko projektowe IDE (ang. inte\grated development emironment).
Do edycji programów źródłowych zapisanych w plikach tekstowych ASCII można użyć dowolnego,
prostego edytora dostarczanego na przykład wraz z systemami operacyjnymi.
Otrzymany w wyniku edycji program źródłowy jest poddawany tłumaczeniu (czyli translacji lub
asemblacji). W rezultacie powstają dwa nowe pliki dyskowe:
1) Program wynikowy (ang. objęci code), który jest zapisany w postaci dwójkowej, nie nadaje
się jednak jeszcze do załadowania do pamięci mikrokontrolera i wykonania. Program
wynikowy zapisany w pliku OBJ jest przemieszczalny (relokowalny - ang. relocatable
code), to znaczy może być przypisany do ustalonego później obszaru adresowego pamięci.
2) Plik tekstowy z raportem translacji i wydrukiem programu źródłowego z towarzyszącym
mu kodem wynikowym (zazwyczaj w postaci szesnastkowej). Raport z translacji (ang.
listing fiie) podaje ponadto numery i adresy kolejnych linii (instrukcji) programu, adresy
zadeklarowanych zmiennych, zestawienie użytych nazw symbolicznych oraz ewentualnie
komunikaty o błędach.
Pliki źródłowy, wynikowy i listing mogą mieć dowolne nazwy i rozszerzenia, najczęściej jednak
nadaje się im tę samą nazwę (np. PROJEKT1) i standardowe rozszerzenia:
ASM plik z tekstem programu źródłowego,
OBJ
plik z programem wynikowym,
LST
plik zawierający raport z translacji wraz z wydrukiem programu.
213
Po uzyskaniu programu wynikowego wolnego od błędów translacji następuje faza łączenia
programu (konsolidacji). W fazie tej wykonuje się połączenie modułów wynikowych (jeśli program
został zapisany w kilku plikach OBJ), dołączenie modułów bibliotecznych (jeśli zostały użyte w
programie) oraz uzgodnienie adresów modułów. •W rezultacie na dysku komputera PC powstaje
zapis nie przemieszczalnego programu dwójkowego (ang. non-relocatable code), który można
załadować do pamięci systemu [mikroprocesorowego i uruchomić. Format dyskowego pliku z
programem ładowalnym zależy od typu procesora i użytego środowiska IDE.
Jednym z najszerzej rozpowszechnionych formatów jest format HEX opracowany przez firmę Intel.
Plik z rozszerzeniem |HEX przechowuje kody instrukcji i dane (stałe) w postaci ciągu rekordów
zapisanych |w kodzie ASCII. Każdy z rekordów ma stały format:
:llaaaatt[dd....]cc
przy czym znaczenie użytych symboli jest następujące:
: znak dwukropka, identyfikator początku każdego nowego rekordu,
ll długość pola danych (dd. . . .) wyrażona w bajtach,
aaaa
16-bitowy adres miejsca pamięci, do którego mają być załadowane dane
zapisane w rekordzie,
tt kod typu rekordu: 00 oznacza rekord danych, 01 oznacza rekord terminalny
(kończący plik HEX),
dd ciąg bajtów danych,
cc suma kontrolna obliczana jako różnica: OOH - (suma wszystkich bajtów rekordu)
mod 256.
W asemblerach firmy Motorola stosuje się jednocześnie z formatem HEX własny firmowy format S
(ang. S-record file). Budowa rekordu S jest podobna do budowy kodu HEX, jednak kolejność pól
jest nieco inna. Najpierw podawany jest dwuznakowy typ rekordu złożony ze znaku S i cyfry 0-9,
potem dwuznakowa liczba oznaczająca liczbę par bajtów w całym rekordzie z wyłączeniem pola
typu i długości, dalej 4-, 6- li 8-znakowy adres pamięci, w-znakowe pole danych lub kodu programu
i wreszcie dv znakowa suma kontrolna. Rekord typu SO jest nagłówkiem zaczynającym plik S. Po
stawowym typem rekordu danych lub programu jest typ Sl, natomiast rekord typu S9 kończy plik
rekordów.
Podczas ładowania programu z pliku HEX (lub S) do pamięci systemu wykonywane jest
rozpakowanie kolejnych rekordów, sprawdzenie sumy kontrolnej oraz przesłanie pola danych pod
wskazany adres. Po załadowaniu program jest gotowy do uruchomienia, Testowanie programu jest
wykonywane pod nadzorem programu śledzącego.
W początkowej fazie korzysta się przy tym z trybu pracy krokowej lub z systemu pułapek (punktów
zatrzymań) ulokowanych w zadanych miejscach programu. Śledzenie pracy programu polega na
sprawdzaniu zawartości rejestrów i wybranych komórek pamięci w kolejnych fazach wykonywania
programu. Jeśli zawartości te zmieniają się zgodnie z założeniami projektowymi, a przyłączone do
systemu urządzenia peryferyjne pracują również zgodnie z oczekiwaniami, uruchamianie programu
jest zakończone. Ważnymi aspektem etapu testowania aplikacji jest określenie zbioru warunków
testowych (danych wejściowych i sygnałów z urządzeń zewnętrznych), które wyczerpują przestrzeń
stanów sterowania systemu.
9.1.1. Asemblery i makroasemblery
Wyróżnia się dwa rodzaje programów tłumaczących programy źródłowe zapisane w języku
asemblera: proste asemblery oraz makroasemblery. Obydwa rodzaje programów łumaczących mają
wspólne cechy w zakresie podstawowych funkcji związanych z translacją: generują kod programu
wynikowego i produkują raport z przebiegu translacji. Sterowanie przebiegiem translacji w przypadku
prostych asemblerów pracujących w środowisku DOS odbywa się przez podanie parametrów
(przełączników). W ten sposób określa się na przykład czy ma być generowany raport (L), czy też nie
214
(-L). W przypadku asemblerów pracujących w graficznym środowisku IDE parametry te ustala siej w
zbiorze opcji asemblera, stosując system list dialogowych Windows.
Oprócz znakowego zapisu kolejnych instrukcji programu, plik źródłowy zawiera komentarze oraz
dyrektywy asemblera, które same nie zostają przetłumaczone na kod wynikowy, ale mają wpływ na
proces tłumaczenia. Poniżej podano podstawowe dyrektywy stosowane w większości asemblerów
oraz przykłady ich użycia:
PARAMETR1
EQU 23H
Dyrektywa equ (ang. equate) definiuje stałą o zadanej nazwie (w powyższym przykładzie parametr1) i
nadaje jej wyspecyfikowaną wartość (23H). Należy wyraźnie zaznaczyć, że definicja stałej nie
oznacza rezerwacji pamięci, zatem obiekt zdefiniowany dyrektywą EQU istnieje tylko podczas
translacji i znika po jej zakończeniu. Stała zdefiniowana dyrektywą EQU może być używana bez
ograniczeń, poczynając od miejsca, w którym została zdefiniowana. Jeśli na przykład w programie
zostanie zapisana instrukcja:
MOV A,#PARAMETR1
to asembler przetłumaczy ją jako MOV A,#23H, czyli zastąpi symboliczną nazwę PARAMETR1
przez nadaną jej wcześniej wartość 23H.
Podobnie, definicja stałej o postaci:
Adres_bazowy_PIO
EQU 50FFH
spowoduje, że po napotkaniu instrukcji ładowania rejestru
MOV DPTR,#Adres_bazowy_PIO
asembler wygeneruje kod odpowiadający instrukcji:
MOV DPTR,#50FFH.
Stałe mogą być definiowane, przy użyciu wszystkich zapisów liczbowych dopuszczanych przez
asembler, a więc zwykle w postaci dziesiętnej, szesnastkowej i dwójkowej. Ponadto większość
asemblerów dopuszcza w definicji stałej użycie prostych wyrażeń. Dla przykładu zapis:
Rejestr_CTRL EQU Adres_bazowy_PIO+3
poprzedzony podaną wcześniej definicją stałej o nazwie Adres bazowy PIO spowoduje
zdefiniowanie stałej o nazwie Rejestr_CTRL i nadanie jej wartości 5102H.
Używanie stałych symbolicznych zamiast stałych liczbowych jest zalecane jako • jedna z
podstawowych reguł programowania w języku asemblera. Odpowiednio dobrane nazwy radykalnie
poprawiają czytelność programu, a ponadto w razie konieczności zmiany stałej wystarczy
zmodyfikować jedną linię programu (i oczywiście powtórnie wykonać asemblację), zamiast
modyfikować wszystkie instrukcje, w których użyto stałej liczbowej.
Do deklarowania zmiennych używa się dyrektyw DB (ang. defme bytes) oraz DW (ang. defme
words). Niefortunne użycie słowa defme w terminologii angielskiej nie powinno wywołać mylnego
przekonania, że chodzi tu o podobną definicję, jak w przypadku stałych. Dyrektywy DB i DW
faktycznie rezerwują miejsce w pamięci danych, powstają zatem obiekty, które będą istniały w
czasie wykonywania programu. Deklaracje zmiennych mogą być użyte tylko do rezerwacji miejsca
w pamięci dla zmiennych o podanych nazwach symbolicznych albo jednocześnie do nadania im
określonych wartości początkowych.
Przykładowy zapis:
X1: DB
3FH,21,0FH
Y1: DW 3FFFH
rezerwuje trzybajtową zmienną xi i nadaje kolejnym bajtom wartości dziesiętne 63, 21 i 15 oraz
zmienną Y o rozmiarze słowa i wartości początkowej 3FFFH. Większość asemblerów dopuszcza
ponadto deklarowanie łańcuchów znakowych. Na przykład deklaracja
NAPIS DB "to jest napis" deklaruje łańcuch o nazwie NAPIS i treści TO JEST NAPIS.
Jednym z zadań programisty piszącego program w języku asemblera jest zaplanowanie
rozmieszczenia poszczególnych fragmentów programu w pamięci. W zależności od rodzaju
asemblera służą do tego różne dyrektywy. Najczęściej spotykana jest dyrektywą ORG (ang.
215
originate), która wskazuje asemblerowi, że następujące po niej instrukcje programu (lub dane
zadeklarowane dyrektywami DB bądź DW) mają być umieszczone w kolejnych komórkach pamięci
od wskazanego adresu. Przykładowy zapis:
ORG
200H
START: CLR A
spowoduje, że kod instrukcji CLR A opatrzonej etykietą START zostanie umieszczony\ w komórce o adresie 2000H,
natomiast sekwencja:
ORG
0EFH
DB
1AH
zainicjuje komórkę (rejestr) o adresie EFH, wpisując do niej wartość 1AH. Większość asemblerów
dopuszcza ponadto inne sposoby definiowania obszarów adresowych danych i programu. Dla
przykładu zapis CSEG AT 1OOOH oznacza, że program (ang. code segment) następujący po tej
dyrektywie będzie lokowany począwszy od adresu 1000H, natomiast zapis TABLICA DATA 3000H
deklaruje wektor o nazwie TABLICA umieszczony począwszy od adresu 3000H.
Możliwe jest też definiowanie segmentów danych w pamięci wewnętrznej (DSEG) i zewnętrznej
(XSEG), obszarów adresowanych bitowo (BSEG) i obszarów relokowalnych (RSEG).
Jeśli program jest zapisany modularnie, w kilku plikach OBJ, udostępnianiem procedur sterują
dyrektywy:
PUBLIC
EXTERN.
Ostatnią linią programu źródłowego powinna być dyrektywa END.
Operatory, wyrażenia, stałe
W zapisie programu źródłowego dozwolone jest używanie prostych operatorów, wyrażeń i stałych.
Zbiór operatorów i symbole używane do ich oznaczania są różne dla różnych asemblerów.
Przykładem typowej symboliki operatorów jest notacja stosowana w asemblerach firmy Motorola,
w których dopuszcza się użycie następujących operacji:
*
mnożenie
/
dzielenie
+
dodawanie
odejmowanie
<
przesunięcie w lewo
>
przesunięcie w prawo
%
reszta z dzielenia
&
iloczyn logiczny
|
suma logiczna
^
suma modulo 2
Korzystanie z operatorów jest dozwolone przy zapisie dowolnych argumentów, zarówno danych,
jak i adresów.
Dla przykładu instrukcje:
JMP PROC1+5
MOV A,#Dana S. ICH
spowodują odpowiednio skok do adresu PROC1+3 oraz załadowanie do akumulatora liczby będącej
iloczynem logicznym stałej „Dana” oraz stałej ICH.
Specjalnym przypadkiem operatorów jest symbol „$" (oraz w niektórych asemblerach
równoważny mu symbol gwiazdki „*"), który oznacza aktualną zawartość licznika programu.
Instrukcje o postaci:
JMP $
JMP $-5
oznaczają zatem odpowiednio: „skocz na siebie" (w tym przypadku jest to nieskończona pętla) oraz
„skocz o 5 bajtów wstecz".
216
Każdy z asemblerów wykorzystuje domyślną podstawę zapisu stałych. W przypadku asemblerów
firmy Motorola i niektórych asemblerów firmy Intel (np. dla procesorów x86) jako domyślny jest
przyjmowany zapis szesnastkowy, dlatego liczba 15 bez żadnych dodatkowych symboli oznacza
wartość 15H, czyli 21 w kodzie dziesiętnym. W innych asemblerach, na przykład x51, domyślny
jest zapis dziesiętny. Zmianę domyślnej pod stawy zapisu stałych umożliwia system przedrostków
(ang. prefix) oraz przyrostków i (ang. suffix). Pisanie programów w językach różnych asemblerów
utrudnia to, że stosuje się w nich różne symbole przedrostków i przyrostków. W notacji firmy Intel
przyrostki dla liczb dwójkowych, ósemkowych, dziesiętnych i szesnastkowych mają odpowiednio 1
symbole B, O (lub Q), D oraz H, natomiast w notacji firmy Motorola są oznaczane symbolami Q,
O, T i H.
Asemblacja warunkowa i procesor makrodefinicji
Opisane wcześniej dyrektywy są słowami zarezerwowanymi i nic muszą być poprzedzone w
programie żadnym znakiem specjalnym pełniącym rolę wyróżnika dyrektywy. Pozostałe dyrektywy
wyróżnia się natomiast znakiem „S". Wśród dyrektyw tego typu znajdują się między innymi
dyrektywy sterujące postacią raportu z translacji oraz warunkowym tłumaczeniem fragmentów
programu. Warunkowe tłumaczenie programu polega na możliwości zdefiniowania sekcji programu
źródłowego, które będą tłumaczone na kod wynikowy tylko wtedy, gdy jest spełniony określony
warunek zadany w postaci wyrażenia boolowskiego. Sekcja taka ma postać:
Dzięki translacji warunkowej można tworzyć uniwersalne programy źródłowe, które w
zależności od sposobu zdefiniowania zmiennych sterujących warunkami będą miały różną postać
wynikową.
Do zapisu warunków używa się meta-zmiennych, operatorów i stałych. Meta-zmienne są
definiowane przy użyciu dyrektywy SET. Dla przykładu zapis:!
$ SET (VAR1, VAR2 = 3, VAR3)
definiuje zmienne o nazwach VAR1, VAR2 i VAR3. Początkowa wartość zmiennej VAR2 jest
równa 3, natomiast zmienne VAR1 i VAR3 przyjmą domyślne wartości OFFFFH. Dyrektywa RESET
zeruje zmienne. Na przykład zapis:
$ RESET (VARl, VAR2)
spowoduje wyzerowanie zmiennych VAR1 i VAR2. Wyrażenie boolowskie złożone z metazmiennych, operatorów i stałych jest spełnione (prawdziwe), jeśli jego wartość jest różna od zera.
W przeciwnym przypadku wyrażenie jest fałszywe.
Zasadniczą cechą, która wyróżnia makroasemblery od prostych asemblerów jest
wbudowany preprocesor makrodefinicji i makrowywołań. Początek makrodefinicji oznacza
dyrektywa MACRO, natomiast koniec - dyrektywa ENDM. Dla przykładu, sekwencja o postaci:
DODAJ MACRO PAR1, PAR2
MOV A,#PAR1
217
ADD A,#PAR2
ENDM
jest makrodefinicją o nazwie DODAJ, która dodaje do siebie parametry PAR1 i PAR2, przy czym
wynik jest umieszczony w akumulatorze.
Jeśli po powyższej makrodefinicji w pro gramie nastąpi makrowywołanie, na przykład w postaci
linii:
DODAJ 20H, 7
to preprocesor makro zastąpi ją tekstem źródłowym:
MOV A,#20H
ADD A,#7
Należy zwrócić uwagę, że obsługa makrowywołań przez preprocesor odbywa się na poziomie kodu
programu źródłowego. Zatem mimo pewnego podobieństwa mechanizmu makrowywołań do
mechanizmu wywołań podprogramów (procedur) efekt obu tych technik programowania jest inny.
Podprogram rezyduje w programie wynikowym tylko w jednym egzemplarzu, a każde jego wywołanie
powoduje zapamiętanie adresu powrotu na stosie, skok do podprogramu, wykonanie jego treści i powrót
do zapamiętanego adresu. W przypadku każdego makrowywołania w programie wynikowym pojawia się
nowa kopia przetłumaczonej na kod wynikowy makrodefinicji, z uwzględnieniem aktualnych
parametrów makrowywołania. Skok i zapamiętanie adresu powrotu nie jest więc konieczne, dzięki
czemu makrowywołanie wykonuje się szybciej od równoważnego podprogramu. Wadą makrowywołań
jest natomiast większa zajętość pamięci, ponieważ każde makrowywołanie generuje w programie
wynikowym kopię kodu makrodefinicji.
Używanie makrodefinicji i makrowywołań jest zalecane, ponieważ poprawia czytelność
programu. Należy je stosować przede wszystkim w przypadku krótkich sekwencji instrukcji,
powtarzanych w programie z różnymi argumentami oraz w sytuacjach, gdy szybkość działania
programu jest istotna. W przypadku długich, często wywoływanych procedur lepiej stosować jest
podprogramy, zwłaszcza gdy system ma niewielką pamięć.
Szczególnym przykładem akcji preprocesora makro, jest obsługa dyrektywy REPT, która ; służy do
powielania ciągu instrukcji.
Przykładowy zapis:
REPT 3 INC
DPTR ENDM
spowoduje, że w programie źródłowym preprocesor wstawi trzykrotnie powieloną instrukcję
inkrementacji rejestru wskaźnika danych DPTR:
INC DPTR
INC DPTR
INC DPTR
W praktycznie implementowanych preprocesorach makro spotyka się ponadto dodatkowe
funkcje, umożliwiające między innymi zagnieżdżanie się makrodefinicji oraz bardziej wszechstronne
sposoby przekazywania parametrów.
9.1.2. Przykłady Makroasemblerów
Większość dostępnych asemblerów i makroasemblerów wykonuje tłumaczenie programu źródłowego w
dwóch przebiegach (ang. two-pass assembly), co oznacza że program jest analizowany dwukrotnie.
W pierwszym przebiegu tłumaczone są instrukcje, które nie zawierają argumentów symbolicznych
(stałych i zmiennych symbolicznych oraz etykiet).
Równocześnie ascmblcr buduje tablicę symboli (ang. symbol table), w której notuje s wszystkie
napotkane definicje symboli i ich wartości. Po zakończeniu pierwszego przebiegu następuje drugi
przebieg, polegający na uzupełnieniu wartości argumentów symbolicznych w programie wynikowym.
W podanym poniżej przykładzie przedstawiono wydruk raportu translacji uzyskany w wyniku
tłumaczenia prostego programu testującego. Wydruk raportu z translacji popularnego
makroasemblera A51 (Keil), przeznaczonego dla mikrokontrolerów rodziny x51 pokazuje rys. 9.2.
218
Rysunek 9.2. Wydruk raportu makroasemblera A51
W podanym niżej przykładzie program o nazwie TRANS wysyła ciąg znaków ASCII przez port
szeregowy UART. Ciąg jest zdefiniowany przy użyciu dyrektywy DB i oznaczony symboliczną
nazwą KOM. Koniec łańcucha znaków tworzącego tekst określa znak terminalny, którym w
podanym przykładzie jest znak EOT (04H). W celu zilustrowania działania dyrektyw PUBLIC i
EXTRN założono, że procedura SEND realizująca wysyłanie pojedynczego bajtu przez port UART jest
zdefiniowana w innym module wynikowym programu. Wydruk raportu translacji omawianego
programu ma następującą postać:
Treść pliku źródłowego zawierającego procedurę transmisji zaczyna się od dyrektywy NAME, która
nadaje modułowi wynikowemu nazwę TRANS wykorzystywaną później w procesie łączenia modułów. Stała
RATĘ oznacza szybkość transmisji w porcie UARTJ i jest określona na podstawie częstotliwości zegara,
zgodnie z danymi katalogowymi mikrokontrolera x51. Kolejna dyrektywa EXTRN wskazuje
makroasemblerowi, że procedura SEND wywoływana w treści modułu jest zdefiniowana w innym module i
należy ją dołączyć później. Adres początkowy START modułu TRANS jest udostępniany na zewnątrz j przy
użyciu dyrektywy PUBLIC, zatem z procedury transmisji mogą korzystać inne moduły wynikowe,
oczywiście pod warunkiem,
że zawierają odpowiednią dyrektywę EXTRN. Program jest
przetłumaczony jako moduł relokowalny, ponieważ zastosowano dyrektywę RS EG.
Właściwy program zaczyna się od ustawienia trybu pracy portu UART i uruchomienia licznika T1
użytego do taktowania transmisji. Następnie pobierane są kolejne bajty komunikatu tekstowego z pola
danych o nazwie KOM i wysyłane przez port UART przy użyciu zewnętrznej procedury SEND. Po wysłaniu
każdego znaku następuje sprawdzenie, czy wysłany znak jest znakiem terminalnym. Jeśli tak, procedura
kończy się (RET), natomiast w przeciwnym przypadku następuje skok do etykiety NEXT i wysłanie
kolejnego znaku.
Należy zwrócić uwagę, że pobieranie kolejnych znaków jest wykonywane przy użyciu rozkazu
MOVC, który w mikrokontrolerach x51 umożliwia dostęp do pamięci programu.
Adres bajtu jest obliczany jako suma zawartości akumulatora (w podanym przykładzie zawsze zero)
oraz rejestru wskaźnika DPTR, który po wysłaniu każdego znaku jest inkrementowany rozkazem INC .
219
Aby program działał poprawnie, zewnętrzna procedura SEND nic może zmieniać zawartości akumulatora i
rejestru DPTR.
W liniach, w których występują odwołania do procedury SEND (linia 14) i pola danych KOM (linia 17),
asembler podał dodatkowy symbol F, oznaczający, że część adresowa instrukcji jest wyrażeniem
relokowalnym i musi być uzupełniona w fazie łączenia modułów. Tymczasowo część adresowa tych
instrukcji jest wypełniona zerami.
9.1.3. Przykłady programów asemblera
Weźmy pod uwagę układ sterowania wyświetlaczami 7-segmentowymi, którego uproszczony schemat
przedstawiono na rysunku 9.3. Zastosowano w nim mikrokontroler x51 sprzężony z programowanym
układem wejścia /wyjścia PIO oraz, sześć identycznych wyświetlaczy. Załóżmy, że dekoder adresowy
narysowany w postaci zamkniętego bloku generuje sygnał CS wybierający układ PIO, jeśli na szynie
adresowej mikrokontrolera pojawi się adres 800xH. Rejestr PA układu 8255 ma wówczas adres
8000H, rejestr PI3 – adres 8001H, rejestr PC - adres 8002H, natomiast rejestr kontrolny - adres
8003H. System sterowania zastosowany w układzie z rysunku 9.3 jest systemem dynamicznym,
ponieważ w danej chwili aktywny jest tylko jeden wyświetlacz.
Wyświetlanie informacji na kilku wyświetlaczach wymaga więc ich okresowego pobudzania
przez mikrokontroler. Dane dla wyświetlaczy są przesyłane przez port PB ustawiony jako
wyjście.
Rysunek 9.3. Uproszczony schemat układu sterowania wyświetlaczami 7-segmentowymi
Port A nie jest wykorzystywany, natomiast bardziej znaczące cztery bity portu PC służą do wyboru
wyświetlacza, na którym ma się pojawić informacja wysłana przez port PB. Porty PCH i PB powinny
być zatem ustawione jako wyjścia pracujące w trybie 0, natomiast konfiguracja portów PA i PCL jest
nieistotna. Cykl wyświetlania informacji przebiega w następujący sposób:
1) Mikrokontroler wysyła 7-segmentowy kod cyfry do portu PB. Przyporządkowanie poszczególnych
segmentów pozycjom bitów kodu pokazano na rysunku 9.3. Dla przykładu, aby wyświetlić cyfrę
„4" należy wysłać kod 0110011 OB -= 66H. Wysłany kod pojawia się na wejściach informacyjnych
220
wszystkich wyświetlaczy, jednak na razie żaden z nich nie zapala się, gdyż żaden z kluczy
prądowych nie jest otwarty.
2) Na linie PC4-6 należy podać kombinację zer i jedynek odpowiadającą numerowi wyświetlacza,
na którym ma się pojawić cyfra. Linia PC7 powinna być w stanie wysokim. Dla przykładu, by
wybrać wyświetlacz drugi z lewej, do portu PCH należy wysłać kombinację 1001B.
Wyświetlacz nadal nie jest zapalony, ale dekoder l 74LS145 jest już wstępnie zaadresowany.
Na wszystkich sześciu wykorzystywanych wyjściach dekodera jest stan wysoki, ponieważ
wejście D znajduje się w stanie wysokim.
3) Należy spowodować wyzwolenie układu monostabilnego 74LS123 przez podanie na wejście A
stanu niskiego z wyjścia PC8. Układ monostabilny wyprodukuje wówczas ujemny impuls na
wyjściu zanegowanym, który włączy wybrany wyświetlacz. W podanym przypadku, aby
spowodować wyzwolenie układu monostabilnego, do portu PCH należy wpisać kombinację
0001B. Czas trwania impulsu, czyli czas włączenia wyświetlacza jest określony przez stałą
czasową obwodu RC przyłączonego do układu 74LS123. Po upływie tego czasu cyfra na
wybranym wyświetlaczu zgaśnie i mikrokontroler powinien powtórzyć sekwencję czynności
1) - 3).
Jeśli chcemy wyświetlać cyfry na kilku wyświetlaczach, powyższa sekwencja powinna być
powtórzona kolejno dla wszystkich używanych wyświetlaczy. Wadą przedstawionego tu
dynamicznego sposobu wyświetlania jest konieczność stałego zaangażowania CPU, natomiast
zaletą - możliwość programowego regulowania jaskrawości świecenia poszczególnych
wyświetlaczy. Jasność ta zależy od częstotliwości pobudzania wyświetlaczy w pętli programowej.
Program, który wyświetla cyfrę „4" na drugim od lewej strony wyświetlaczu z rysunku 9.3, ma
następującą postać:
Odblokowanie przerwań z portu UART jest w powyższym przykładzie potrzebne po to, by system
mógł mieć kontakt z systemem uruchomieniowym opartym na komputerze PC, połączonym z
221
mikrokontrolerem przez interfejs RS-232C. Oczywiście, zamiast programowego opóźnienia
wprowadzanego przez procedurę CZEKAJ można zastosować wbudowany licznik. Jeśli obsługa
przepełnienia licznika będzie się odbywać w trybie przerwań, jednostka centralna między kolejnymi
pobudzeniami wyświetlacza może realizować inne zadania.
Rozważmy teraz blok prostego programowanego generatora przebiegów analogowych z
mikrokontrolerem x51 i 8-bitowym przetwornikiem cyfrowo-analogowym przedstawiony na
rysunku 9.4.
Rysunek 9.4. Uproszczony schemat programowanego generatora przebiegów elektrycznych
Na rysunku pominięto źródła napięć odniesienia przetwornika C/A oraz bufory sygnałów
wyjściowych mikrokontrolera. Przetwornik ma wewnętrzny rejestr danych, który jest zapisywany,
jeśli wejście CS jest w stanie niskim, a na linii WR pojawi się strob zapisu. Wpis liczby OOH do
rejestru przetwornika powoduje, że na jego wyjściu UX pojawia się napięcie o wartości 0V,
natomiast wpis liczby FFH generuje napięcie +5V. Napięcie wyjściowe UX jest podawane na
wejście X analogowego multipleksera MUX z ośmioma wyjściami ponumerowanymi od O do 7.
Wyborem wyjścia multipleksera steruje 3-bitowa liczba wpisana z szyny danych do wewnętrznego
rejestru multipleksera. Wpis liczby OOH wybiera wyjście numer O, natomiast wpis liczby 07H
wybiera wyjście nr 7.
Załóżmy, że zadanie projektowe polega na napisaniu programu dla generatora fali prostokątnej o
zadanych wartościach napięć w stanie wysokim i niskim oraz o zadanych czasach trwania stanu
wysokiego i niskiego. Dla ustalenia uwagi przyjmijmy, że napięcie w stanie wysokim UH ma
wynosić 4V, natomiast napięcie w stanie niskim UL ma być równe 2V. Załóżmy też, że stan niski
ma trwać dwa razy krócej niż stan wysoki, a czas trwania stanu wysokiego ma być zdefiniowany
jako parametr projektowanej procedury. Niech ponadto sygnał CS1 z dekodera odpowiada adresowi
800CH, natomiast sygnał CS2 - adresowi 800DH. Generowane napięcie ma się pojawić na wyjściu
numer 5. Program, który realizuje powyższe zadanie ma postać:
222
Podobnie jak we wcześniejszym przykładzie, zamiast opóźnień programowych można wykorzystać
przerwania z licznika. Należy zauważyć, że użycie opóźnień programowych może prowadzić do
znacznych błędów określenia czasów trwania stanu niskiego i wysokiego na wyjściu, ponieważ do
opóźnień wnoszonych przez procedurę delay dodają się opóźnienia związane z wywołaniem
procedury i powrotem z niej oraz opóźnienia związane z wykonaniem instrukcji przygotowujących
każdy kolejny cykl w sekcji start. Dokonując prostych modyfikacji podanego wyżej programu
można uzyskać generację przebiegów o innym kształcie, na przykład trójkątnym, trapezowym itp.
9.2. Programowanie w języku C
Tworzenie programu w języku C przebiega według tego samego schematu, co cykl projektowy
programu w języku asemblera przedstawiony na rysunku 9.1. Pliki źródłowe programu (oznaczone
zwykle rozszerzeniem C) są tłumaczone na postać wynikową przez translatory nazywane
kompilatorami (ang. compilers).
9.2.1. Kompilatory języka C
Większość dostępnych kompilatorów języka C dla mikrokontrolerów jest opracowywana przez
specjalistyczne firmy zajmujące się oprogramowaniem wspomagającym projektowanie systemów z
mikrokontroleraini. Do najbardziej znanych firm działających w tej dziedzinie należą: Archimedes,
Tasking, Ceibo, Hi-Tech, Frankłin, Keil, Ashling i IAR. Kompilatory języka C opracowywane
przez wymienione wyżej firmy są zwykle niezgodne ze sobą, co wynika także z wciąż
niedostatecznej standaryzacji samego języka C. Najczęściej stosowanym standardem jest standard
ANSI C, jednak w praktyce kod źródłowy akceptowany przez kompilator określonej firmy może
wymagać modyfikacji przed skompilowaniem przy użyciu kompilatora ANSI C innej firmy.
Kompilatory C dla mikrokontrolerów są przeważnie dostarczane jako kompilatory skrośne (ang.
223
cross-compilers). Oznacza to, że kompilator pracuje na innej platformie (zwykle PC) i produkuje
kod wynikowy dla mikrokontrolera określonego typu.
Typowe kompilatory języka C dla mikrokontrolerów mają następujące cechy:
- implementacja wszystkich typów ANSI C: unsigned, short, long, char, inl,floal, double
oraz pointer, a także typów związanych z architekturą mikrokontrolerów: bit, sbit,sfr,
- implementacja struktur, unii oraz typów tablicowych i wyliczeniowych,
- deklaracje funkcji współużywalnych, rekurencyjnych i funkcji przerwań,
- implementacja różnych modeli pamięci (liny, smali, compact, medium, large, banked) z
podziałem na obszary danych (data), programu (code), obszaru pierwszych 256 bajtów
pamięci (idata) oraz obszaru pamięci zewnętrznej (xdata),
- dostęp do obszarów adresowanych bitowo, rejestrów SFR i rejestrów ogólnego
przeznaczenia,
- implementacja wskaźników o długości zależnej od typu pamięci (np. l-bajtowe w obszarze
data i 2-bajtowe w obszarze xdata),
- funkcje optymalizacji kodu wynikowego przez optymalizację skoków, eliminację
zdublowanych fragmentów kodu i niepotrzebnych rozgałęzień, optymalizację operacji
zmiennoprzecinkowych itp.
Niektóre z wymienionych cech powodują, że programowanie mikrokontrolerów w języku C
wymaga specjalistycznych umiejętności i przebiega w odmienny sposób niż w przypadku
programowania komputerów.
Najważniejsze różnice można streścić w postaci następujących spostrzeżeń:
1) Zapisanie algorytmu pracy mikrokontrolera w języku C wymaga tak samo dobrej znajomości
architektury mikrokontrolera, jak przy posługiwaniu się językiem asemblera (chyba że
przedmiotem projektu jest fragment programu nie związany ze sprzętem, a tylko z
przetwarzaniem danych). Większość autorytatywnych publikacji z tej dziedziny postuluje
opanowanie asemblera jako niezbędną umiejętność przed przystąpieniem do pisania
programów w języku C.
2) Programy dla mikrokontrolerów zapisane w języku C „wyglądają" nieco inaczej niż typowe
programy komputerowe. W mniejszym stopniu korzysta się ze skomplikowanych konstrukcji
strukturalnych, a w większym z prostych operacji przypisań. Dotyczy to zwłaszcza programów
intensywnie współpracujących ze sprzętem na j poziomie rejestrów i poszczególnych bitów.
Uwaga 2) pociąga za sobą w konsekwencji to, że program źródłowy w języku C ma często
prawie tak samo dużo linii, jak program źródłowy w języku asemblera. Kod wynikowy
wyprodukowany przez dobry kompilator jest natomiast zwykle od kilku do kilkunastu razy dłuższy
od kodu wynikowego asemblera. W tym świetle o popularności języka C w programowaniu
mikrokontrolerów decyduje głównie sprawa kosztów. Duży program zapisany w języku C może być
nawet kilkukrotnie tańszy niż program w języku asemblera, a czas jego projektowania, testowania i
dokumentowania jest znacznie krótszy niż cykl projektowania programu w języku asemblera.
9.2.2. Przykłady programów w języku C – przykład 1
Obsługa wyświetlaczy 7-SEGMENTOWYCH
Rozważmy program sterowania wyświetlaczem 7-segmentowym w układzie z rysunku 9.3,
realizujący to samo zadanie co program podany w p. 9. l .3:
224
Powyższy program różni się nieco od programu z p. 9.1.3, gdyż funkcja czekaj wykorzystuje licznik
T0 mikrokontrolera x51. Na początku programu dołączono biblioteczny nagłówek reg51.h z
definicjami rejestrów i bitów kontrolno-sterujących mikrokontrolera. Program zajmuje 29 linii,
natomiast program w języku asemblera z p. 6.1.3 nieco więcej, bo 33 linie (razem z komentarzami).
Jeśliby w programie zapisanym w języku C zrezygnować z obsługi licznika i wykorzystać
opóźnienie programowe, liczba i linii programu źródłowego wyniosłaby 16. Pogram byłby zatem o
połowę krótszy niż wersja zapisana w asemblerze. Porównanie wielkości kodu wynikowego wypada
natomiast zdecydowanie na korzyść asemblera. Program wynikowy zajmuje bowiem odpowiednio
40 bajtów (asembler) i 116 bajtów (C).
W przedstawionym powyżej programie założono, że mikrokontroler pracuje z oscylatorem
o częstotliwości 11,0592 MHz, typowej dla tych układów, jeśli chce się łatwo uzyskać standardowe
szybkości transmisji w porcie UART. Wewnętrzna częstotliwość sygnału zegara doprowadzonego
do licznika jest wówczas równa 11,0592 MHz/ /12 - 921,6 kHz, a okres zegara wynosi 1,085 p.s.
Aby uzyskać opóźnienie 20 ms trzeba zatem zliczyć 20000 / 1,085 = 18433 impulsów zegara.
Ponieważ licznik liczy od zaprogramowanej wartości
x
do chwili
przepełnienia, czyli
osiągnięcia stanu FFFFH = I = 65535D, zatem wartość x programująca licznik powinna być równa
65535 - 18433 = = 47102 - B7FDII. W programie przyjęto przybliżoną wartość równą B800H.
9.2.3. Przykłady programów w języku C – przykład 2
Programowany generator funkcyjny z przetwornikiem C/A
Rozważmy teraz program generacji przebiegu prostokątnego o zadanych parametrach, równoważny
programowi z p. 9. l .3. W języku C ma on następującą postać:
225
W powyższym przykładzie, podobnie jak w poprzednim, do odmierzania czasu wykorzystano
licznik T0, pracujący w konfiguracji 16-bitowej. Program generuje falę prostokątną o napięciu UH
= 4 V i UL = 2 V, przy czym czas trwania stanu wysokiego wynosi 80ms, natomiast czas trwania
stanu niskiego równa się 40ms.
Mimo bardziej elastycznej procedury odmierzania czasu program źródłowy w języku C jest krótszy
od programu w języku asemblera. Kod wynikowy jest jednak blisko 3-krotnie dłuższy (asembler 38 bajtów, C - 112 bajtów). Podany wyżej program można łatwo zmodyfikować w celu realizacji
programowanego generatora funkcyjnego o dowolnym przebiegu. Dla przykładu, program
generatora przebiegu piłokształtnego z dobieranym czasem trwania kroku narastania impulsów oraz
z ustalaną programowo wartością napięcia maksymalnego może mieć następującą postać:
226
Przebieg piłokształtny jest generowany na wyjściu WY0 układu z rysunku 9.3. W rzeczywistości
narastające zbocze przebiegu jest krzywą schodkową, przy czym czas trwania każdej kolejnej
wartości napięcia wynosi 10 ms (TLH), natomiast skok napięcia wynosi 5V/256 = 19,5 mV.
Zastosowanie pętli for przy generowaniu kolejnych napięć powoduje, że napięcie o wartości 0V
pojawia się na czas krótszy niż l ms. Można to łatwo zmienić, zastępując pętlę for pętlą while z
inkrementacją zmiennej licz na końcu pętli.
9.2.4. Przykłady programów w języku C – przykład 3
Obsługa klawiatury matrycowej
Najprostszym zespołem wykorzystywanym w systemach mikrokontrolerów do wprowadzania
danych i poleceń sterujących są klawiatury zorganizowane w postaci matryc (macierzy) przycisków.
Na rysunku 9.5 przedstawiono prostą klawiaturę złożoną z 28 przycisków ułożonych w matrycy z
siedmioma kolumnami i czterema wierszami. Pominięto dodatkowe bufory i rezystory, które są
zwykle stosowane w celu zapewnienia odpowiednich parametrów elektrycznych sygnałów przy
współpracy z układem P1O.
Rysunek 9.5. Uproszczony schemat klawiatury matrycowej 7x4 z mikrokontrolerem x51 przez
programowany układ PIO
Obsługa klawiatury z rysunku 9.5 jest wykonywana w sposób programowy, to znaczy sprawdzanie,
czy został wciśnięty jakiś przycisk oraz dekodowanie jego współrzędnych w matrycy (numeru
wiersza i kolumny) odbywa się przy użyciu algorytmu skanowania (przeglądania) klawiatury. W
bardziej skomplikowanych zespołach klawiatur alternatywnie stosuje się sygnalizację wciśnięcia
przycisku przez linie przerwań oraz sprzętowe dekodowanie wciśniętego przycisku.
227
W układzie przedstawionym na rysunku 9.5 dekodowanie stanu klawiatury przebiega według
następującego schematu:
1) Mikrokontroler ustawia stan „O" na linii kolumny numer O, sterowanej z wyjścia PBO układu
PIO. Wcześniej należy, oczywiście, odpowiednio skonfigurować układ PIO, to znaczy zdefiniować
odpowiednie kierunki transmisji w portach.
2) Program odczytuje port PCL i sprawdza, czy na jednym z wejść jest stan „O". Jeśli tak jest, to
wykryto wciśnięcie przycisku na skrzyżowaniu kolumny O i wiersza, na którym odczytane zostało
„O".
3) Mikrokontroler generuje stan „O" na kolejnej linii kolumn i wykonuje sprawdzenie stanu linii
wierszy. Procedura powtarza się, aż sprawdzona zostanie cała klawiatura albo nastąpi wykrycie
stanu wciśnięcia jakiegokolwiek przycisku.
4) Po zdekodowaniu klawiatury program przystępuje do obsługi przez wywołanie procedury
przypisanej do danego klawisza.
Przedstawiony poniżej program obsługi klawiatury z rysunku 9.5 sprawdza całą macierz,
niezależnie od tego, czy w trakcie sprawdzania wykryto stan wciśnięcia któregoś z przycisków, czy
też nie. Sprawdzanie odbywa się od lewej kolumny do prawej i od dolnego wiersza do górnego.
Jeśli równocześnie wciśnięty został więcej niż jeden przycisk, program zwróci kod klawisza
położonego w kolumnie położonej bliżej prawej strony matrycy i w wierszu znajdującym się bliżej
jej dołu.
228
Funkcja dekoduj zwraca kod wciśniętego klawisza. Jeśli żaden klawisz nic został wciśnięty,
zwracana jest liczba 0xff, natomiast jeśli wciśnięto klawisz Kxy, wartość funkcji dekoduj na
czterech bardziej znaczących bitach podaje numer kolumny (0 - 6) w naturalnym kodzie
dwójkowym, a na mniej znaczących czterech bitach - numer wiersza w kodzie „l z 4". Wywołanie
funkcji obsługi klawiszy zrealizowano przy użyciu instrukcji switch. Ten fragment programu można
również zapisać, korzystając z tablicy wskaźników do funkcji obsługi.
Przedstawiony powyżej prosty program obsługi klawiatury matrycowej ma pewne niedoskonałości.
Mianowicie, klawiatury realizowane w postaci matryc z mechanicznymi stykami wytwarzają przy
zwieraniu zakłócenia impulsowe, w wyniku czego przez pewien niedługi czas stan linii wierszy
może być nieustalony.
W stosowanych w praktyce programach obsługi klawiatur tego typu nieprawidłowemu
zdekodowaniu klawiatury zapobiega się przez kilkakrotne (na przykład 3-krotne) odczytanie stanu
wiersza.
Jeśli przynajmniej dwa odczyty świadczą o wciśnięciu klawisza, program przystępuje do jego
obsługi, natomiast w przeciwnym przypadku stan klawisza uznaje się za nieokreślony. Drugą wadą
przedstawionego programu jest brak reakcji systemu na zwieranie klawiszy w czasie gdy
mikrokontroler jest zajęty obsługą poprzednio wciśniętego klawisza. Można temu zaradzić, stosując
dodatkową linię doprowadzającą do mikrokontrolera sygnał przerwania w przypadku wciśnięcia
któregokolwiek klawisza. Praca z przerwaniami ma dodatkowo tę zaletę, że przy braku zgłoszeń z
klawiatury procesor może realizować inne zadania zamiast bezproduktywnie skanować klawiaturę.
Przykład obsługi przerwań w programie zapisanym w języku C przedstawiono w następnym
punkcie.
9.2.5. Przykłady programów w języku C – przykład 4
Transmisja przez port szeregowy
229
W systemach z mikrokontrolerami stosuje się najczęściej transmisję asynchroniczną, ze
standardową szybkością określoną przez odpowiednio zaprogramowany licznik. Szybkość ta w
prostych mikrokontrolerach jest zazwyczaj niewielka, dlatego obsługa transmisji w trybie
programowym powodowałaby bardzo nieefektywne wykorzystanie czasu CPU. Dlatego zamiast
obsługi programowej w praktyce korzysta się z systemu przerwań, zgodnie z regułami podanymi w
p. 5.4.4.
W podanym niżej przykładzie mikrokontroler odbiera ciąg bajtów z portu szeregowego pracującego
jako 8-bitowy układ UART. Szybkość transmisji jest określona przez impulsy produkowane przez
licznik T1. Odebrane bajty są wysyłane w postaci równoległej do portu P1 w prosty sposób - bez
synchronizacji transmisji między mikrokontrolerem a odbiornikiem i z powiadamianiem odbiornika
o gotowości bajtu do odbioru przez wysłanie dodatniego impulsu na wyjściu P2.0.
Program realizujący tak zdefiniowane zadanie ma następujący zapis w języku C:
Zapis interrupt 4 w nagłówku definicji funkcji przekaz oznacza, że funkcja ta będzie wywoływana,
jeśli wystąpi przerwanie numer 4. W mikrokontrolerach rodziny x51 przerwanie to jest przypisane
portowi UART. Kompilator po natrafieniu na taki zapis spowoduje, że adres funkcji przekaz
zostanie zapisany pod adresem odpowiadającym wektorowi przerwań o numerze 4 (licząc od zera).
Zgodnie z ogólnymi zasadami obsługi przerwań opisanymi w p. 5.4.4 funkcja obsługi przerwań
powinna być napisana w taki sposób, by nie zmieniała wartości rejestrów używanych przez
program, którego wykonanie jest przerywane. Można to zrealizować przy użyciu stosu, ale w
mikrokontrolerach z rejestrami podzielonymi na banki prościej jest wykorzystać w funkcji obsługi
inny bank rejestrów niż ten, na którym operuje program główny. W podanym przykładzie zapis
using 2 oznacza, że funkcja przekaz będzie wykorzystywać bank rejestrów o numerze 2. Dla
ścisłości trzeba dodać, że w podanym wyżej programie przedstawiono tylko sam mechanizm
inicjacji portu UART i sposób programowania w systemie przerwań. Po wykonaniu inicjacji portu
UART program główny wchodzi w nieskończoną pętlę, toteż korzyść z pracy w systemie przerwań
nie jest widoczna. Jeśli jednak zamiast pętli while(1) w funkcji main zapisze się program
realizujący inne zadania, wtedy korzyść z zastosowania systemu przerwań stanic się oczywista.
230
9.3. Narzędzia wspomagające uruchamianie systemów mikroprocesorowych
Uruchamianie prototypowych systemów z mikrokontrolcrami jest na ogól trudniejsze od
uruchamiania konwencjonalnych systemów mikroprocesorowych, budowanych głównie do
przetwarzania danych. Wynika to z dwóch podstawowych przyczyn:
1)
Mikrokontrolery mają wiele wbudowanych bloków funkcjonalnych (pamięci i układów
peryferyjnych), do których dostęp w czasie pracy systemu jest utrudniony lub niemożliwy.
Traktowanie mikrokontrolera jako „czarnej skrzynki" nie wystarcza jednak do szczegółowego
przeanalizowania pracy systemu. Potrzebne są specjalistyczne narzędzia i metody do śledzenia
stanu mikrokontrolera i jego otoczenia, a w szczególności do badania stanu rejestrów SFR.
2)
Sterowniki z wbudowanymi mikrokontrolerami są przeznaczone do pracy w czasie
rzeczywistym. Testowanie systemu w czasie rzeczywistym, we współpracy z rzeczywistym
otoczeniem, bez naruszania relacji czasowych sygnałów, wymaga narzędzi diagnostycznych, które
nie zakłócają pracy systemu.
Mimo tych różnic, do uruchamiania systemów z mikroprocesorami i mikrokontrolerami stosuje
się podobne metody i narzędzia, opracowane i udoskonalane w ciągu blisko 30-letniej ewolucji
techniki mikroprocesorowej. Przedstawione powyżej trudności pokonuje się przy użyciu
ulepszonych metod śledzenia systemów w czasie rzeczywistym, z wykorzystaniem wbudowanych
do mikrokontrolerów bloków zapewniających pracę ze śledzeniem w tle (ang. background
debugging modę) oraz specjalizowanych interfejsów diagnostycznych (JTAG).
Narzędzia wspomagające projektowanie i uruchamianie dzieli się na kilka podstawowych kategorii:
- monitory programowe (ang. monitors),
- programy śledzące (ang. debuggers),
- symulatory (ang. simulators),
- analizatory stanów logicznych (ang. logie analyzers),
- emulatory sprzętowe (ICH, ang. in-circuit emulators),
- zintegrowane systemy projektowo-diagnostyczne (IDE, ang.
integrated deve-lopment
environment),
- analizatory szybkości pracy systemu (ang. performance analysis tools),
- programatory wbudowanych i zewnętrznych pamięci OTP / EPROM / EEPROM / FLASH (ang.
memory programmers).
Do narzędzi wspomagających projektowanie zalicza się też omówione wcześniej asemblery,
kompilatory i programy łącząco-ładujące. Systemy uruchomieniowe produkuje się albo jako
autonomiczne systemy z wbudowanym mikrokomputerem, albo w postaci kart, interfejsów,
przystawek i oprogramowania do instalacji w typowych komputerach PC.
9.3.1. Monitory i programy śledzące
Monitory i programy śledzące (debugery) są najprostszymi, najtańszymi i jednocześnie najszerzej
stosowanymi narzędziami wspomagającymi uruchamianie systemów z mikrokontrolerami.
Podstawowa różnica między monitorami i programami śledzącymi polega na tym, że monitory są
instalowane w pamięci nieulotnej (wewnętrznej lub zewnętrznej) systemu zawierającego
mikrokontroler, natomiast debugery pracują w przyłączonych do systemu komputerach (zwykle
klasy PC). Z tego powodu monitory nazywa się również rezydującymi debugerami (ang. resident
debuggers). Często stosuje się rozwiązanie mieszane, w którym część programu debugera rezyduje
w pamięci na płycie prototypowej (ang. evaluation board), a pozostała część programu jest
umieszczona w pamięci komputera PC. W takiej konfiguracji program rezydujący służy przede
wszystkim do realizacji komunikacji z komputerem PC (zwykle przez port UART - RS232) i
ładowania testowanych programów, natomiast komputer PC wykonuje właściwe funkcje związane
ze śledzeniem pracy programu (rysunek 9.6).
231
Rysunek 9.6. Prosty system uruchomieniowy z płytą prototypową i komputerem PC
Zestaw funkcji monitora-debugera zależy od jego typu, producenta i rodzaju zastosowanego
mikrokontrolera. Większość debugerów zapewnia realizację podstawowego zbioru operacji, przy
użyciu których można załadować program z pliku HEX lub S do pamięci, uruchomić go, śledzić w
kilku różnych trybach, obserwować i modyfikować zawartości pamięci i rejestrów (w tym SFR), a
także wykonywać proste zmiany w programie bez potrzeby ponownej asemblacji (lub rekompilacji).
Debugery pracujące w systemie DOS są sterowane przy użyciu poleceń podawanych przez
operatora, zwykle w postaci jednoliterowych symboli z opcjonalnymi parametrami. Programy
śledzące przeznaczone dla graficznego środowiska Windows są natomiast sterowane typową metodą
interaktywną (mysz, listy dialogowe, menu), a wyniki pojawiają się w odpowiednich oknach.
Poniżej podano zbiór typowych poleceń debugera. W nawiasach prostokątnych umieszczono
opcjonalne parametry sterujące.
D [adres] [, l bajtów] - (ang. display, dump) wyprowadza i wyświetla na konsoli zawartość n =
1_bajtów kolejnych komórek pamięci począwszy od adresu adres. Jeśli liczba bajtów nie jest
podana, wyświetlana jest zawartość domyślnej liczby komórek. Jeśli natomiast nie podano adresu,
wyświetlany jest obszar zaczynający się od aktualnej zawartości licznika adresów. Po uruchomieniu
debugera licznik wskazuje zwykle na początek pamięci (najczęściej 0). Poniższy przykładowy
wydruk ilustruje typowy format stosowany przy wyświetlaniu zawartości pamięci: w lewej kolumnie
podane są adresy, następnie w 16 kolumnach zawartości komórek pamięci w kodzie szesnastkowym
i w końcowych kolumnach równoważna informacja w kodzie ASCII. Kody, którym nie odpowiadają
dające się wydrukować znaki ASCII są reprezentowane przez znak kropki.
Rysunek.9.7. Fragment monitora Siemens x166 wyprowadzony w trybie HEX-dump
adres [, nowa_zawartość] - (ang. memory) wyświetla zawartość komórki pamięci o adresie adres
i ewentualnie wpisuje do niej nową zawartość.
R
[nazwa_rejestru] - (ang. register) wyświetla zawartość wskazanego rejestru lub wszystkich
rejestrów (jeśli nie podano nazwy konkretnego rejestru). Operator może podać nowe zawartości
rejestrów.
L [adres, ] nazwa-pliku - (ang. load) ładuje plik dwójkowy (np. w formacie HEX) do pamięci
systemu poczynając od adresu adres.
B [iista_adresów] - (ang. breakpoint) wstawia punkt zatrzymania przy adresie odpowiadającym
aktualnej zawartości licznika programu lub w punktach określonych przez listę adresów.
G [adres] - (ang. go) uruchamia program od aktualnego adresu w liczniku programu lub od adresu
wskazanego jako parametr. Jeśli nie zdefiniowano punktów zatrzymań, program wykonuje się w
całości.
M
232
S [liczba_instrukcji] - (ang. step) wykonuje pojedynczą instrukcję programu lub ciąg instrukcji o
zadanej długości.
Debugery są ponadto najczęściej wyposażone w prosty asembler (ang. in-line as-sembler) i
deasembler (ang. disassembler), które są wywoływane poleceniami A i u:
A [adres] - (ang. assemble) po podaniu tego polecenia operator może wpisywać z konsoli program
źródłowy. Kolejne instrukcje są tłumaczone na bieżąco i umieszczane w kolejnych komórkach
pamięci, zaczynając od aktualnej zawartości licznika programu lub od podanego adresu. W
najprostszych asemblerach typu in-line nie można używać nazw symbolicznych, a więc w
szczególności etykiet. Adresy skoków są podawane w postaci liczbowej, co znacznie utrudnia
pisanie większych fragmentów programu.
u [adres] [, liczba_instrukcji] - (ang. unassemble) deasembluje podaną lub domyślną liczbę
instrukcji zaczynając od adresu adres lub od aktualnej zawartości licznika programu. Adres
początkowy musi odpowiadać pierwszemu bajtowi instrukcji, w przeciwnym przypadku deasembler
zinterpretuje zawartość pamięci w nieprawidłowy sposób. Przykład takiej sytuacji ilustruje podane
niżej zestawienie prawidłowego i nieprawidłowego użycia polecenia u deasemblera x86:
Rysunek 9.8. Prawidłowe i nieprawidłowe użycie polecenia deasemblera x86
Wywołanie U 123 jest prawidłowe, ponieważ w bieżącym segmencie programu (CS = 1F6E)
komórka pamięci o adresie 0123H zawiera pierwszy bajt (kod operacji) instrukcji jnz. Wywołanie u
122 jest natomiast nieprawidłowe, ponieważ pod rym adresem znajduje się ostatni bajt (argument)
poprzedniej instrukcji. Deasembler próbuje zinterpretować go jako kod operacji xor, co prowadzi w
konsekwencji do błędnej interpretacji kolejnych instrukcji. Ponowna synchronizacja adresów
następuje dopiero przy rozkazie MOV DX,CX.
Zaletą prostych monitorów i debugerów jest łatwość obsługi i niska cena. Podstawową wadą
jest fakt, że narzędzia te nie pozwalają na prześledzenie pracy systemu w czasie rzeczywistym i w
warunkach identycznych jak te, które będą miały miejsce w gotowej aplikacji. Monitor
zainstalowany w systemie prototypowym zajmuje część jego zasobów (pamięć, port szeregowy i
linię przerwań), dlatego aplikacje korzystające z tych zasobów muszą być w fazie testowania
zmodyfikowane i śledzone w niepełnym zakresie realizowanych funkcji.
9.3.2. Symulatory
Symulator jest programem umożliwiającym prześledzenie programu dla mikrokontrolera przy
użyciu procesora innego typu (zwykle x86 na platformie Windows/PC). Program symulatora
naśladuje zachowanie się mikrokontrolera, pozwala śledzić stan rejestrów, zawartość pamięci, a
nawet symulować przerwania i proste układy peryferyjne. Zaletą takiego rozwiązania jest to, że
badania oprogramowania można zacząć zanim jeszcze powstanie prototyp sprzętowy. Wadą
symulatorów jest brak możliwości przetestowania współpracy mikrokontrolera z otoczeniem w
rzeczywistych warunkach. Mimo to symulatory są często stosowane we wstępnej fazie
projektowania oprogramowania, ponieważ pozwalają wykryć wiele błędów nie związanych ze
współpracą mikrokontrolera z otoczeniem sprzętowym. Na rysunku 9.9 przedstawiono okno
definiowania parametrów urządzeń zewnętrznych przykładowego symulatora mikrokontrolerów
x51, 251 i 8x93.
233
Rysunek 9.9. Okno do definiowania parametrów urządzeń zewnętrznych w symulatorze
Compass/251USB
Emulatory sprzętowe
Emulatory sprzętowe są najlepszymi i jednocześnie najdroższymi narzędziami do uruchamiania
systemów z mikroprocesorami lub mikrokontrolerami. Zasada ich pracy polega na zastąpieniu
mikrokontrolera w uruchamianym urządzeniu przez sondę zakończoną adapterem dopasowanym do
podstawki mikrokontrolera. Układy emulatora, częściowo wbudowane do samego adaptera, a
częściowo przyłączone przez sondę, pracują tak samo jak wyjęty z podstawki mikrokontroler, ale
oprócz tego zapewniają śledzenie pracy systemu w czasie rzeczywistym. Dobrze zaprojektowane
emulatory naśladują mikrokontrolery w najdrobniejszych szczegółach, z zachowaniem relacji
czasowych między wszystkimi sygnałami wejściowymi i wyjściowymi. Najczęściej emulator jest
połączony z zewnętrznym komputerem (np. klasy PC), który umożliwia wygodne śledzenie
badanego prototypu. Klasyczny emulator jest zbudowany w sposób przedstawiony na rysunku 9.10.
Rysunek 9.10. Poglądowy schemat budowy typowego emulatora sprzętowego
Emulator przypomina kompletny mikrokomputer, gdyż oprócz jednostki centralnej zawiera pamięci
i układy wejścia/wyjścia. Emulatory mają następujące cechy:
- mogą w trakcie pracy zamieniać między sobą zasoby testowanego systemu i
odpowiadające im zasoby emulatora; technikę tę nazywa się mapowaniem zasobów (ang.
mapping),
234
-
testowanie programu w czasie rzeczywistym jest możliwe nawet bez przyłączonego
systemu prototypowego,
- podobnie jak w przypadku debugerów, program jest wykonywany w trybie ciągłym,
krokowo lub ze zdefiniowanymi uprzednio punktami zatrzymań,
- zapewniona jest pełna obserwacja i możliwość modyfikacji zawartości rejestrów i pamięci,
często również w czasie rzeczywistym,
- śledzenie wykonywania programu ułatwiają wbudowane analizatory stanów logicznych
rejestrujące sekwencje stanów w wybranych punktach systemu.
Emulatory o zaawansowanej architekturze mają takie same możliwości, przy czym funkcje
śledzenia w czasie rzeczywistym są bardziej rozbudowane i dotyczą praktycznie wszystkich
parametrów testowanego systemu. Emulatory tego typu wykorzystują bloki pamięci RAM
wyposażone w podwójne sterowanie, a więc w dwie niezależne szyny adresów i danych (ang. dualport RAM). Dzięki temu procesor emulatora i przyłączona do niego stacja robocza mogą pracować
równocześnie, mając dostęp do wspólnych zasobów (rysunek 9.11). W emulatorze nie jest zatem
potrzebny monitor zapisany w pamięci ROM, gdyż komunikacja stacji z emulatorem odbywa się
bez udziału procesora wbudowanego do emulatora.
O ile w przypadku układu z rysunku 9.10 każde polecenie emulacyjne wysyłane z komputera
nadzorującego przerywało pracę procesora emulującego (NM1), o tyle w układzie z rysunku 9.11
przerwania są potrzebne tylko w przypadku niektórych operacji (na przykład wymuszenia przejścia
do określonego adresu w programie).
Rysunek 9.11. Budowa emulatora wyposażonego w blok pamięci RAM z podwójnym dostępem
Emulatory są zazwyczaj budowane z wykorzystaniem mikrokontrolera tego samego typu, jaki
zastosowano w systemie testowanym. Z zewnątrz przyłączane są dodatkowe, niekiedy bardzo
skomplikowane układy, umożliwiające rejestrację stanu mikrokontrolera w czasie rzeczywistym. W
przypadku mikrokontrolerów niektórych typów budowa emulatora jest ułatwiona, oprócz bowiem
wersji rynkowej układów producenci dostarczają także wersje przeznaczone specjalnie do emulacji
(ang. bond out version). Mają one obudowy z większą liczbą wyprowadzeń, przez które
wyprowadza się na zewnątrz sygnały z wewnętrznej szyny danych i adresów. W przypadku
mikrokontrolerów, które są trudne do emulacji, a nie mają wersji bond out, stosuje się niekiedy
funkcjonalnie równoważne mikrokontrolery zbudowane przy użyciu programowanych struktur
logicznych.
Metoda nie nadaje się jednak do użycia w przypadku najbardziej zaawansowanych
mikrokontrolerów o skomplikowanej budowie wewnętrznej.
Drugim pod względem trudności zadaniem przy projektowaniu emulatorów jest opracowanie
układów realizujących mapowanie zasobów. Technika mapowania zastosowana do pamięci
umożliwia elastyczne przełączanie zasobów testowanego systemu i emulatora lub komputera
sterującego. We wstępnej fazie projektu, programy mogą być dzięki temu uruchamiane w pamięci
komputera, a dopiero potem wraz z pojawieniem się prototypu projektowanego urządzenia są
przenoszone do jego własnej pamięci. W fazach pośrednich możliwe jest wykonywanie części
235
programu w pamięci komputera, a innych fragmentów oprogramowania - w pamięci badanego
systemu. Mapowaniem zasobów zarządza specjalizowany kontroler współpracujący z pamięcią
emulacyjną (rysunek 9.12). W zależności od sposobu zaprogramowania (skonfigurowania)
kontrolera system korzysta albo z zasobów komputera sterującego, albo z rzeczywistych zasobów
testowanego systemu.
Rysunek 9.12. Realizacja mapowania obszarów pamięci w emulatorze sprzętowym
Do emulatorów sprzętowych zalicza się również oddzielną grupę narzędzi nazywanych
emulatorami pamięci ROM (EPROM). Są one znacznie prostsze w budowie od emulatorów
mikrokontrolerów, choć pracują na podobnej zasadzie. Sonda z adapterem emulatora ROM
zastępuje pamięć stałą i naśladuje jej działanie. Dane odczytywane przez szynę pamięci ROM
pochodzą jednak z pamięci RAM emulatora, dlatego mogą być łatwo modyfikowane w fazie
testowania systemu, bez potrzeby programowania kolejnych układów ROM (FPROM). Dzięki temu
czas tworzenia projektu jest znacznie krótszy.
Wysoki koszt opracowania emulatorów dla coraz bardziej skomplikowanych mikrokontrolerów
spowodował, że coraz więcej czołowych producentów mikrokontrolerów wyposaża je w dodatkowe
bloki funkcjonalne ułatwiające śledzenie pracy w czasie rzeczywistym. Układy te mogą pracować w
trybie śledzenia w tle (HMD - ang. background modę debugging), a sygnały potrzebne do śledzenia
są przesyłane przy użyciu dodatkowych wyprowadzeń, nie wpływając na pracę mikrokontrolera.
Interfejs diagnostyczny mikrokontrolerów i mikroprocesorów jest najczęściej zgodny ze standardem
JTAG. W system BMD są wyposażone między innymi wszystkie nowe procesory firm Intel i
Motorola, poczynając od Pentium, PowerPC i ColdFire. Dla niektórych typów procesorów tryb
BMD lub równoważne mu tryby pracy testowej nie są dostępne. Dotyczy to zwłaszcza procesorów z
oprogramowaniem fabrycznym zapisanym w wewnętrznej pamięci ROM, które jest w ten sposób
chronione przed skopiowaniem lub rozkodowaniem. W rzeczywistości jednak nawet układy do
zastosowań specjalnych z zabezpieczonym odczytem wewnętrznej pamięci programu mogą
pracować w trybie diagnostycznym, jest to bowiem niezbędne w fazie testów fabrycznych. Sposób
uruchomienia trybu testowego w takich przypadkach jest otoczony tajemnicą firmową i nie jest
udostępniany nawet producentom narzędzi wspomagających projektowanie i testowanie systemów.
9.3.3. Zintegrowane programy wspomagające uruchamianie
Poszczególne programy narzędziowe do śledzenia, symulacji i emulacji są najczęściej dostarczane
w postaci pakietów tworzących kompletne środowisko programowe do projektowania i testowania
aplikacji mikrokontrolerów. Typowy pakiet tego typu (IDE) zawiera asembler, debuger, kompilator
języka C, program łącząco-ładujący, program zarządzania plikami projektów (ang. project manager,
librarian) oraz opcjonalnie symulator, program do emulacji i analizator szybkości pracy systemu.
Pakiety IDE są najczęściej implementowane w środowisku Windows/PC i sprzedawane w
rozmaitych opcjach. Ich cena zależy głównie od typu mikrokontrolera, jakości kompilatora języka C
oraz zestawu funkcji do testowania systemów prototypowych w czasie rzeczywistym.
236
Przykładem środowiska IDE dla popularnych mikrokontrolerów 8- i 16-bitowych firm Intel i
Motorola jest PathFinder, opracowany przez irlandzką firmę Ashling. PathFinder jest w znacznej
mierze systemem otwartym, może bowiem współpracować w szerokim zakresie z
oprogramowaniem i sprzętem innych firm produkujących narzędzia IDE. W szczególności można w
nim wykorzystać kompilatory C dostarczane przez IAR, Keil, Tasking/BSO, HiwarelArchimedes,
Hi-Tech, Cosmic, Byte Craft, Intel i Introl. Może też współpracować z emulatorami sprzętowymi i
programatorami pamięci.
Jeśli testowany system jest przyłączony do komputera nadzorującego przy użyciu złącza
szeregowego RS-232, pakiet PathFinder zapewnia szybkość transmisji równą 115 kbps, dlatego
ładowanie nawet dużych programów przebiega sprawnie. Zaletą systemu są też praktycznie
nieograniczone rozmiary tablic symboli dla uruchamianych programów. Jedna z dodatkowych
funkcji pozwala przeprowadzić analizę szybkości wykonywania poszczególnych rodzajów operacji
przez badany program (rysunek 9.13).
Rysunek 9.13. Raport z przebiegu analizy szybkości działania poszczególnych rodzajów operacji w
testowanym programie
Dla większości popularnych typów mikrokontrolerów dostępne są kompletne zestawy do prac
projektowo-uruchomieniowych (ang. development kits). W skład takich zestawów wchodzi płyta
prototypowa z mikrokontrolerem, zewnętrznymi pamięciami oraz z podstawowymi urządzeniami
peryferyjnymi, takimi jak klawiatury matrycowe, wyświetlacze i porty RS-232. W zestawie jest
również oprogramowanie (najczęściej IDF) oraz podstawowa dokumentacja techniczna. Jest to
wystarczająca podstawa do wstępnych prac projektowych lub do tworzenia niezbyt
skomplikowanych aplikacji. Dla biur projektowych zajmujących się profesjonalnie budową bardziej
złożonych
systemów
oferowane
są
o
wiele
droższe
zestawy
MDS
(ang.
microprocessorlmicrocontroller development system) wyposażone w emulator sprzętowy i
kompilator języka C wraz z obszernymi bibliotekami.
237
10. Literatura
1. TIETZE U., SCHENK CH.: Układy półprzewodnikowe,
Warszawa, WNT, 1996
2. Pełka R.: Mikrokontrolery architektura, programowanie, zastosowania,
Warszawa, WKŁ, 1999
3. GAŁKA P., GAŁKA P.: Podstawy programowania mikrokontrolerów 8051,
Warszawa, ZNI “MIKOM”, 1995
4. Z.Czaja: Materiały do wykładu Mikrokontrolery i mikrosystemy 2003,
Politechnika Gdańska, 2003
238
11. Dokumentacja sterownika DSM-51 wyk. w laboratorium
Rysunek 11.1. Schemat blokowy
239
Rysunek 11.2. Schemat jednostki centralnej
240
Rysunek 11.3. Schemat układu zasilania oraz resetu i wdog
241
Rysunek 11.4. Schemat układu łączy szeregowych RS232
242
Rysunek 11.5. Schemat układów przetwornika A/C i C/A
243
Rysunek 11.6. Schemat układu wyświetlacza 7-segmentowego i klawiatury sekwencyjnej
244
Rysunek 11.7. Schemat układu klawiatury matrycowej
245
Rysunek 11.8. Schemat układu buforów szyny danych, adresowej i sygnałów sterujących
246
Rysunek 11.9. Schemat układu łączówek sterownika
247

Podobne dokumenty