You are on page 1of 47

Technika mikroprocesorowa

Prowadzący: dr inż. Maciej Dzieniakowski


konsultacje: 306 GE
tel. wew.: 7880

Treść wykładów:
by Mirosław Szczepaniak

Wykład 1 2.10.2007
Przelicznik:

DATA IN DATA OUT


ALU

Procesor:
PROGRAM

DATA IN DATA OUT


ALU

DATA BUS 8b
pamięć
programowa

Układ
ADDRESS BUS 16b
sterowania

zegar
Podstawowy system mikroprocesorowy

DATA BUS

OUT DATA DATA

mikroprocesor

ROM RAM I/O

Cykl maszynowy:
Cykl maszynowy to cykl, podczas którego następuje wymiana danych między procesorem a
pamięcią lub układem wejścia wyjścia (odczyt albo zapis).

Fazy:

pobrania PC → ADDRESS BUS PC - Program Counter


PC → PC + 1 RR - Rejestr Rozkazu
RR → DATA BUS

rozpoznania rozpoznanie rozkazu, ustawianie sekwencji zdarzeń

wykonania wykonywanie czynności

Każdy cykl maszynowy trwa tyle samo!!!

1c = N · Tosc

c - cykl maszynowy
N = 1, 2, 3, 4 ....
Tosc - okres oscylatora
Wykład 2 9.10.2007

Podstawowe parametry ROM

1. Czas dostępu

tacc - czas dostępu - czas odpowiedzi pamięci od momentu żądania danych do momentu ich
otrzymania

2. Pojemność
2n+1

N
...
...
ADDRESS BUS ...

...
...
...
0
0000

POJ = 2n+1 · ORG [bit]


ORG - szerokość komórki [bit]

Pamięć stała:
1.
● ROM - programowane przez producenta pamięci w czasie produkcji, czasami określana jako
MROM (Mask programmable ROM).
● PROM (ang. Programmable ROM) - pamięć która może zostać zaprogramowana. Pierwsze
pamięci tego typu były programowane przez przepalenie cieniutkich drucików
wbudowanych w strukturę (tzw "przepalanie połączeń")
● EPROM (ang. Erasable Programmable ROM) - pamięć, do której zaprogramowania
potrzebne jest specjalne urządzenie, zwane programatorem PROM (PROM Programmer
albo PROM Burner) kasowana przez naświetlanie ultrafioletem
2
● E PROM (ang. Electrically Erasable Programmable ROM) - pamięć kasowalna i
programowalna elektrycznie.
2.
● FLASH - pamięć kasowalna i programowalna elektrycznie

Pamięć o dostępie swobodnym


RAM
● z podtrzymywaniem
○ wewnętrznym
○ zewnętrznym
● bez podtrzymywania

Podtrzymywanie pozwala na zachowanie danych w pamięci mimo odłączenia napięcia


zewnętrznego.

Mikrokontroler → mikroprocesor + urządzenia I/O

ASEMBLER

Asembler jest to:


● język programowania niskopoziomowego,
● przetwarzanie tekstu na dane wynikowe w programowaniu niskopoziomowym
(asemblacja - odpowiednik kompilacji w językach wysokiego poziomu)

Język asembler

mnemonic (lub mnemonik) - podstawowy rozkaz


zbiór mnemoników - język danego procesora
Liczba mnemoników jest ograniczona.

mnemonic + adresowanie → język asembler danego procesora

mnemonic
● instrukcje transferu
○ mov _,_ (w procesorach 51 po prawej stronie przecinka źródło, po lewej komórka
← docelowa),
○ movc _,_
○ movx _,_
○ push
○ pop
● instrukcje arytmetyczne
○ add _,_ (suma)
○ subb _,_ (różnica)
○ mul _,_ (iloczyn)
○ inc _ (inkrementacja)
● instrukcje logiczne
○ anl _,_ (iloczyn logiczny)
○ orl _,_ (suma logiczna)
○ RR _,_ (rotacja w prawo)
● instrukcje sterujące
○ bezwarunkowe
■ ljmp _ (long jump - skok do etykiety _)
■ RET
○ warunkowe
■ jb _,_ (jump if direct bit is set - skok warunkowy, jeśli docelowy bit jest 1)
● instrukcje bitowe
○ setb _ (ustaw dany bit na 1)
○ cpl _ (dopełnienie danego bitu, negacja)
(więcej instrukcji na końcu)

Adresowanie

Wyróżniamy dwie architektury procesorów:


● von Neumanna (najczęściej komputery RISC, choć nie wszystkie);
● harwardzka (najczęściej komputery CISC);

architektura von Neumana architektura harwardzka


● prostszy asembler (jedna ● trudniejszy asembler (wiele
przestrzeń adresowa) przestrzeni adresowych)
● możliwość mieszania się ● brak możliwości mieszania
pamięci ROM i RAM się pamięci

Obszary pamięci i rejestrów w mikrokontrolerze typu 51 (CISC - architektura harwardzka)

SFR - special function registers - spis rejestrów specjalnych

A(ACC) - Podstawowy rejestr procesora typu harwardzkiego (w przeciwieństwie do RISC, gdzie


nie ma wyróżnionych rejestrów specjalnych)

Adresowanie bezpośrednie

mov adr„t”,adr„s” przejście z komórki o adresie s (source) do o adresie t (target)


W adresowaniu bezpośrednim obsługiwane są tylko LOW RAM i SFR.

np.
1. mov 86h,C8h
2. mov 43h,C8h
Adresowanie pośrednie(dotyczy HIGH RAM i LOW RAM)

Adresowanie pośrednie jest wygodne gdy pamięć jest zalokowana jako tablica.
W procesorach typu 51 do adresowania pośredniego używa się rejestrów R0-R1, np.:
mov R0,#07h
mov @R0,a
w adresowaniu bezpośrednim odpowiadałoby to instrukcji:
mov 07h,a
# - oznacza, że za nim stoi wartość ← adresowanie natychmiastowe
@ - nakazuje wzięcie zawartości danego rejestru
Jeśli użyto rejestrów R (tylko w procesorach 51) to mamy doczynienia z adresowaniem
rejestrowym. W procesorach rodziny 51 wyróżniamy 4 banki rejestrów jak poniżej:

...
1
R2
R1
R0
R7
R6
R5
R4 0
R3
R2
R1
R0
00h
Wykład 3 16.10.2007

Asembler → mnemoniki + operanty + adresowanie + dyrektywy

mnemoniki - proste rozkazy dla procesora;


dyrektywy - informacje dla programu tłumaczącego

Niektóre zasady w programowaniu w języku asembler:


● etykiety powinny rozpoczynać się w pierwszej kolumnie tekstu,
● etykiety kończą się dwukropkiem → 'etykieta:' ,
● należy zachować odstęp jednej spacji:
○ pomiędzy etykietą i mnemonikiem,
○ pomiędzy mnemonikiem a operantem.

Program 1
Program ma za zadanie wysyłać z portu P4 na zmianę same 0 albo same 1.

P4

μC

piny wyjściowe

01. ORG 0000h


02. petla: mov P4,#FFh
03. mov P4,#00h
04. ljmp petla

1. Dyrektywa 'ORG _' wskazuje adres w pamięci, gdzie ma zacząć się program. Podobne
działanie ma dyrektywa 'CODE AT _'.
2. Mnemoniki 'mov P4,#FFh' i 'mov P4,#00h' nakazują przekazanie do portu P4 najpierw
samych jedynek, a później samych zer.
3. 'ljmp petla' nakazuje skok bezwarunkowy do etykiety 'petla'. Użycie tej instrukcji z
etykietą symboliczną jest możliwe tylko po ustaleniu adresu, gdzie zaczyna się program.
Powyższy przykład jest poprawny, aczkolwiek należy zwrócić uwagę, że na tak banalne zadanie
zużywana jest cała moc obliczeniowa procesora.
Program 2
Program ma przesyłać informacje z portu P5 do portu P4 zgodnie z wykresem:

OUT

FFh P5 P4

80h μC

80h FFh IN

01. ORG 0000h


02. mov a,P5
03. petla: jb acc.7, high
04. mov P4, a
05. ljmp dalej
06. high: mov P4, #80h
07. dalej: ljmp petla

Rejestr akumulatora
7 0
128 64 32 16 8 4 2 1

MSB LSB

Pamiętając, że rejestr akumulatora jest 8-bitowy, należy tylko sprawdzić, czy na ostatnim bicie jest
jedynka. Jeśli tak, mamy wartości z zakresu 80h-FFh, więc na wyjściu musi być 80h. Jeśli jest 0, na
wyjście przekazujemy sygnał wejściowy.
Skok warunkowy 'jb acc.7, high' - sprawdza czy siódmy bit rejestru akumulatora jest jedynką,
jeśli tak następuje skok do etykiety high, jeśli nie, program działa dalej.

Podobnie jak w poprzednim programie, tutaj także na bardzo proste zadanie jest zużywane 100%
mocy obliczeniowej procesora.

PORTY

Porty - to urządzenia do przesyłania dwustanowych informacji. Mogą być:


● równoległe - służą do równoległego przesyłania bitów,
● szeregowe - służą do szeregowego przesyłania bitów,
Z każdego portu równoległego programista ma możliwość zrobienia kilku portów szeregowych (np.
z równoległego portu 8-bitowego może zrobić 8 portów szeregowych)

Porty mogą być:


● wejściowe
● wyjściowe
● dwukierunkowe
● quasi dwukierunkowe
Bramki trzystanowe
Do szyny danych jednocześnie podłączone są pamięci, urządzenia I/O. Gdyby do tego
połączenia używano zwykłych bramek logicznych, które są dwustanowe, przy jednoczesnym
nadawaniu danych dochodziłoby do uszkodzeń elementów.

Bramki dwustanowe:

W takim wypadku następuje zwarcie źródła z górnej


bramki do masy w dolnej

RAM

IN

Aby uniknąć powyższych przypadków stosuje się bramki trzystanowe. Oprócz stanów
logicznych 0 i 1, występuję także trzeci stan - stan wysokiej impedancji (HZ). Bramka jest wtedy
wyłączona, a wyłączone tranzystory MOS dają impedancję rzędu MΩ.

Logika sterująca
CS - Chip Select
Port wejściowy
7

mov a,@DPTR
...........

I7 ................. I0
CL

Dekoder adresowy

ADDRESS BUS

Data Pointer (DPTR) - jedyny 16-bitowy rejestr w procesorach 5, wskazuje na adres w pamięci
zewnętrznej, który przekazywany jest przez 16-bitową szynę danych. Służy do adresowania
indeksowego. Zatem powyższy mnemonik nakazuje przekazanie zawartości DPTR do akumulatora.

Port wyjściowy

Przerzutniki zatrzaskowe typu D


D ................ D

O7 ............... O0
CL CL (clock) - zegar

Dekoder adresowy

ADDRESS BUS
Wykład 4 23.10.2007

Port dwukierunkowy

DATA BUS
μC

IN OUT

M ULTIPLEKSER

D0 - D7

CS R/W

Porty quasi dwukierunkowe (quasibidirectional)

+Vcc
bramka 3-stanowa

rezystor pull-up

Q
INTERNAL
DATA BUS D
OUTPUT (PIN)
Q'

bramka 3-stanowa
Rezystor pull-up/pull-down (podciągający) - rezystory, których jeden koniec podłączony jest albo
do źródła napięcia (rezystor pull-up) albo do masy (rezystor pull-down).
Zastosowania:
● „czyszczenie” szyny danych z szumów powstałych, gdy podłączone do niej urządzenia
znajdują się w stanie wysokiej impedancji,
● likwidowanie rezonansu w liniach długich
Linią długą jest każde urządzenie (pierwotnie linie przewodowe), w którym wymiar długości,
porównywalny jest z długością fali przebiegu elektrycznego rozchodzącego
się w urządzeniu. Przykładem linii długich są m.in. kable koncentryczne

Każdy przewód ma własną pojemność, indukcyjność i rezystancję, co może doprowadzić do


powstawania rezonansu. Rozwiązaniem jest dołączenia rezystora pull-down.

Działanie portu quasi dwukierunkowego


● jako wejściowy - sygnał '1' na wejściu → przerzutnik D zapamiętuje stan → na wyjściu Q'
mamy '0' → tranzystor odcięty → na wyjściu '1' z rezystora pull-up podłączonego do drena.
Obie bramki trzystanowe pozostają w stanie wysokiej impedancji.
● jako wyjściowy - ma dwie możliwości:
○ odczytanie stanu z pina,
○ odczytanie stanu z latcha,
W zależności od wyboru, sygnał przekazywany jest na szynę danych przez jedną z bramek
trzystanowych.

Program 3
Program ma spowodować świecenie się kolejnych diod.

P4.0
.... ....
P4.7

μC

Wersja 1

01. ORG 0000h


02. LJMP 1000h
03. ORG 1000h
04. mov a,#FEh
05. BEGIN: mov P4,a
06. rl a,
07. ljmp BEGIN
Program wpisuje do rejestru akumulatora liczbę FEh (254d). W wierszu 6. następuje rotacja bitów
w lewo, co przedstawia poniższy rysunek

1 1 1 1 1 1 1 0 ACC

F E

Program jest napisany teoretycznie dobrze, ale:


● zmiana świecenia diod zmieni się w ciągu kilku cykli maszynowych, czyli niemal
niezauważalnie, będziemy widzieli tylko żarzące się wszystkie diody jednocześnie,
● program zużywa 100% mocy obliczeniowej procesora

Wersja 2
Wprowadza pętlę opóźniającą, aby efekt działania programu był widoczny

01. ORG 0000h


02. LJMP 1000h
03. ORG 1000h
04. mov a,#FEh
05. BEGIN: mov P4,a
06. rl a,
07. lcall DELAY
08. ljmp BEGIN
09.
10. ORG 2000h
11. DELAY: mov R1, #250d
12. mov R2, #200d
13. LOOP: djnz R1, loop
14. mov R1, #250d
15. djnz R2, loop
16. RET

djnz _,_ - (decrease and jump if bit is not 0) - odejmuje 1 i sprawdza czy bit jest zerem, jeśli nie
idzie do podanej etykiety

Zatem w wierszach 11.-12. przypisujemy pewne liczby do rejestrów R1 i R2. W wierszu 13.
mamy pętlę, w której każdym obiegu następuje pomniejszenie wartości w R1. Gdy dojdzie do 0,
pętla idzie dalej. Zauważmy, że dla zanim zostanie wykonana instrukcja w wierszu 15., pętla z
wiersza 13. obiegnie 250 razy. Wiedząc, że wykonanie instrukcji 'djnz' trwa 2 cykle maszynowe
(1 cykl to ok. 1μs),a - 'mov' 1 cykl z łatwych obliczeń wynika, że pętla DELAY opóźnia działanie
programu o ok. 100 ms.
Mapa pamięci
Przykład - obsługa wyświetlacza 8x8. Mamy dwa wyjścia, jedno obsługuje kolumny, drugie
wiersze.

D001h DISPLAY (OUT)


D000h

C000h IN

7FFFh

Program
(ROM)

movx @DTPR,a

#D001h lub #D000h

DATA BUS

ADDRESS BUS

dekoder
adresowy

urządzenie 1
.....

urządzenie n

n - liczba podłączonych urządzeń


Wykład 5 30.10.2007

FFFFh
A11 D7

.... RAM ....


A0 D0
CS
8FFFh
RAM
8000h
7FFFh
A11 D7

.... ROM ....


A0 D0
CS
0FFFh
ROM
0000h DEKODER
ADDRESS BUS
DATA BUS

Zaprojektować dekoder, który będzie rozróżniał do którego urządzenia będą wysyłane dane.

FFFFh 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

... ... ... ... ...

8FFFh 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1

8000h 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
7FFFh 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0

... ... ... ... ...

0FFFh 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0
... ... ... ... ...
0000h 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
LSB 0 3 4 7 8 11 12 15 M SB

Patrząc na najstarszy bit (15) widzimy, że pokazuje on wartość 0 dla pierwszej połowy przestrzeni
adresowej (gdzie znajduje się pamięć ROM), natomiast 1 dla drugiej (pamięć RAM), zatem nasz
układ mógłby wyglądać następująco:
Jeśli na A15 jest:
A0 A11A15
A11 D7 - 0 → 0 na ROM → ROM aktywny
1 na RAM → RAM nieaktywny
.... RAM .... - 1 → 0 na RAM → RAM aktywny
A0 D0 1 na ROM → ROM nieaktywny
CS
Rozwiązanie spełnia warunki zadania,
A11
jednak powoduje, że pamięć ROM
D7
i RAM zajmują po połowie przestrzeni
.... ROM .... adresowej, a nie tyle, ile było
A0 D0 początkowo zarezerwowane (dekoder
CS niepełny).

ADDRESS
BUS
DATA BUS

DEKODER

Dekoder niepełny - dekoder, który rezerwuje całą przestrzeń adresową, uniemożliwiając dalszą
rozbudowę systemu.
Dekoder pełny - dekoder, który odzwierciedla w przestrzeni adresowej w skali 1:1 przestrzeń
adresową urządzeń, którymi steruje. Jest możliwa dalsza rozbudowa systemu

Projektując dekoder pełny, jeszcze raz należy spojrzeć na tabele z poprzedniej strony. Zwróćmy
uwagę, że 4 najstarsze bity (12-15) jednoznacznie wskazują miejsca pamięci, gdzie znajdują się
pamięci ROM i RAM.
Zatem nasz dekoder mógłby wyglądać tak:

A15 CS (RAM)

A14

A13

CS (ROM)
A12
Dekodowane są 4 najstarsze bity - dla ROM pokazują 0000, dla RAM → 0001. Reszta przestrzeni
adresowej jest wolna.
Przerwania
Procesor

Maska centralna

Maski
indywidualne

Flagi

Urządzenie

Maska centralna
Rejestr flag
Przerwanie maskowalne

Urządzenie

μP

Maski Przerwanie niemaskowalne


indywidualne

Urządzenie
Wykład 6 06.11.2007

Jak procesor przyjmuje przerwania?

Main Nie ma zależności czasowej pomiędzy przerwaniem,


... a wykonywanym fragmentem programu głównego
...
... ← procesor ustawia wewnętrzny
LJMP vector
...
wskaźnik poziomu przerwania
[ vector:
instrukcja
[ Body
przerwanie [
AP ...
... RETI
PC ← STOS
SP ← SP -(2)
LJMP AP

1. Przerwanie nie powoduje zaprzestania wykonywania bieżącej instrukcji, zostanie ona


zawsze dokończona.
2. STOS ← AP (na stos dokładany jest adres powrotny - adres następnej instrukcji po tej, w
której nastąpiło przerwanie)
3. SP ← (2) (wskaźnik stosu - stack pointer - zostaje zwiększony)
4. Ustawienie flagi poziomu przerwania - jest to wewnętrzna flaga, ustala hierarchię przerwań
(tworzona przez producentów, bez dostępu dla programistów). Następnie nie przyjmuje
następnych przerwań o takiej samej lub niższej hierarchii.
5. PC ← STOS (AP na szczycie)
6. SP ← SP - (2)
7. LJMP AP
8. Następuje kasowanie wskaźnika poziomu przerwania.

Na powyższe czynności programista nie ma najczęściej wpływu.

RETI - Return from interupt - używa się tylko do obsługi przerwań,


RET - Return
PUSH _ - wstawia na szczyt stosu, SP + 1
POP _ - przekazuje szczyt stosu do rejestru, SP - 1

Należy pamiętać, że podczas wykonywania obsługi przerwania (część BODY na powyższym


schemacie) może nastąpić zmiana zawartości rejestrów używanych także w programie głównym, co
spowoduje, że po powrocie do programu głównego zawartość rejestrów będzie inna niż przed
nastąpieniem przerwania. Dlatego zawartości wspólnych rejestrów należy chronić, np.
przechowując ich wartości na stosie.
vector: PUSH A,
PUSH B,
wstawianie wartości
rejestrów na stos B
BODY
A
APL
POP B, APH
odzyskiwanie danych POP A,
do rejestrów RETI ...
Ochrona komórki z wewnętrznej pamięci RAM

PUSH A
mov A, 24h
PUSH A

POP A
mov 24h, A
POP A

Przerwanie w trakcie drugiego przerwania

● Drugie przerwanie znajduje się w hierarchii wyżej niż przerwanie pierwsze.


Następuje dokończenie bieżącej instrukcji w Body1, następnie Body1 zostaje uznane za
program główny i dalej postępowanie wygląda przy poprzednim przerwaniu.

Main
...
...
...
... ...
[ vector1: Body1
instrukcja ...
[
przerwanie 1 [ ...
[ przerwanie 2
AP2 [ vector2:
AP1 ... ... Body2
... RETI ...
[
... [
...
RETI

...

Stos wygląda wtedy następująco:

APL2
APH2
APL1
APH1

...
● Drugie przerwanie znajduje się w hierarchii niżej lub na tym samym poziomie
Procesor ignoruje flagę, wykonuje Body1, wraca do programu głównego. Żądanie
przerwania przyjmuje dopiero podczas wykonywania następnej instrukcji.

Main
...
...
...
vector1: Body1
...
...
...
przerwanie 2 [
[ [
instrukcja
[ ...
przerwanie 1 [ RETI
AP1 [ ...
...
AP2
...
vector2: Body2

RETI

...

Na podobnej zasadzie działa wywołanie procedury (call, lcall, ...), z taką różnicą, że obsługę
przerwania kończy instrukcja RETI, a procedurę kończy RET. Podczas wykonywania procedury nie
ma także żadnej wewnętrznej flagi określającej hierarchię (jak flaga poziomu przerwania w
przypadku przerwań)

Wykład 7 20.11.2007

Rejestry adresowalne bitowo - znajdują się tam rejestry bitów, do których można odwołać się
bezpośrednio rejestr.bit (np. rejestry portów)
Rejestry nieadresowalne bitowo - nie można odwoływać się do pojedynczych bitów tych
rejestrów, należy „wyciągnąć” całą zawartość rejestru.
Spis rejestrów adresowalnych i nieadresowalnych bitowo podaje producent.

Program 4
Napisać program, który po naciśnięciu przycisku, będzie powodował zmianę stanu diody.

5V
AAA AAA
5V CPL P 5.0
P5.0 P3.2 CPL P 5.0

P3.2 BBB

P5.0
Wersja bez wykorzystania przerwań

01. ORG 0000h


02. LJMP 1000h
03. ORG 1000h
04. AAA: JB P3.2,AAA
05. CPL P5.0
06. BBB: JNB P3.2,BBB
07. LJMP AAA

Program wykorzystuje 100% mocy obliczeniowej procesora.

Wersja z wykorzystaniem przerwań

maska
indywidualna
''1''
priority

IED

''0'' EX0
IT0 flaga przerwania

bit konfiguracyjny
CPU
(sprawdzanie flag
w każdym cyklu
maszynowym)
EAL

maska centralna
(Enable All)

1 → zbocze opadające ustawia flagę przerwania


0 → stan niski (statyczny) ustawia flagę przerwania

Flagi przerwań są ustawiane zawsze, programista nie ma na to wpływu. Może jedynie przesłonić
(lub nie) flagę maską.

Podczas używania przerwań w programach należy pamiętać o:


1. Inicjalizacji hardware'owego generatora przerwań
2. Ustaleniu hierarchii (hierarchii się nie ustawia dla obsługi jednego przerwania)
3. Zezwoleniu na przerwania (zdjęcie/założenie maski)

1 → maska zdjęta (zezwolenie na przerwania)


0 → maska założona (brak zezwolenia)
01. ORG 0000h
02. LJMP 1000h
03. ORG 1000h
04.
05. SETB IT0
06. SETB EX0
07. SETB EAL
08. MAIN: LJMP MAIN
09.
10. ORG 0003h
11. LJMP 2000h
12. ORG 2000h
13. CPL P5.0
14. RETI

● wiersz 05. → inicjalizacja generatora przerwań,


● wiersz 06. → zezwolenie na przerwanie (zdjęcie maski indywidualnej)
● wiersz 07. → zezwolenie na przerwanie (zdjęcie maski centralnej)
● na niebiesko zaznaczono implementację obsługi przerwania:
○ 0003h - wektor przerwania zewnętrznego
○ RETI - wyjście i powrót do pętli MAIN

Zakładając, że przycisk będzie wciskany co 100ms, a na procesor wykona program po 11μs


(6 CM na operacje automatyczne, 1 CM na instrukcję CPL i 2 CM na instrukcje LJMP i RETI;
1 CM ≈ 1μs), to procesor zajmie się zapalaniem diody raz na 10 000 μs. Czyli na wykonanie tego
zadania zużywa się ok. 0,01% procesora.
Z punktu widzenia jednostki centralnej wszystkie przerwania są zewnętrzne. Spotykany jest
jeszcze inny podział: na przerwania wewnętrzne (pochodzące z hardware'u mikrokontrolera) i
zewnętrzne (pochodzące ze świata zewnętrznego)

Wykład 8 27.11.2007

TIMER/COUNTER
dwa 8-bitowe
rejestry liczące

flaga przerwania

CM
C/T

Tx TLX THX TFX


PIN

TRx - bity w rejestrach konfiguracyjnych


&
przełącznik włączony, gdy na
≥ wyjściu bramki AND jest 1
GATE

PIN TRx - bit startowy

Może zliczać 216 cykli maszynowych (timer) lub 216 sygnałów pojawiających się na pinie (counter).
Gdy rejestry zostaną przepełnione (FFFFh) następuje wyzerowanie liczników i flaga przerwania
ustawiana jest na 1. Jednak, ponieważ możemy zmieniać zawartości rejestrów liczących, zatem
możemy skrócić cykle:
zawartość TLX i TLH zawartość TLX i TLH

FFFFh FFFFh

TFX

TFX

Rejestry konfiguracyjne

7 0
GATE C/T M1 M0 GATE C/T M1 M0 ← TMOD
rejestr nieadresowalny bitowo

bity 0-3 ← Timer 0


bity 4-7 ← Timer 1
7 0
TF1 TR1 TF0 TR0 x x x x ← TCON
rejestr adresowalny bitowo

M1 M0
0 0 Licznik 8-bitowy

0 1 Licznik 16-bitowy

1 0 Licznik 8-bitowy z automatycznym przeładowaniem

1 1

Ustawiając flagi TF0 i TF1 można software'owo zainicjalizować przerwanie!

Program 5
Program ma spowodować świecenie się kolejnych diod.

P4.0 Wersja napisana wcześniej (patrz Program 3)


zajmowała 100% mocy obliczeniowej procesora.
.... .... Użycie timera rozwiązuje ten problem.
P4.7

μC
01. ORG 0000h
02. LJMP 1000h
03. ORG 1000h
04.
05. MOV a,#FEh
06. MOV TMOD,#01h
07. SETB TR0
08. SETB ET0
09. SETB EAL
10. MAIN: LJMP MAIN
11.
12. ORG 000Bh
13. LJMP 2000h
14. ORG 2000h
15.
16. MOV P4,a
17. RL a
18. MOV THO,#WARTOSC1
19. MOV TL0,#WARTOSC2
20. RETI

● wiersz 05. - ustawienie warunków początkowych - zapisanie do akumulatora liczby FEh


● wiersze 06-07 - inicjalizacja hardware'u
wiersz 06 → ustawia każdy bit w rejestrze TMOD na 0, z wyjątkiem bitu LSB, który jest 1,
czyli ustawiony jest 16-bitowy tryb pracy timera 0 (bit M1 - 0, bit M0 -1)
● wiersze 08-09 - inicjalizacja przerwań (08. → zdjęcie maski timera 0, 09. → zdjęcie maski
głównej)
● na niebiesko zaznaczono implementację obsługi przerwania,
○ 000Bh → wektor obsługi przerwania timera
○ wiersze 18.-19. wyznaczają wartości początkowe,
Zauważmy, że kod zaznaczony na niebiesko zajmie procesorowi ok. 10 cykli. Zatem,
jeśli zadamy takie wartości początkowe żeby zmiana zapalenia diody następowała co 50
ms, to zużycie procesora będzie rzędu 2%.

Wykład 9 4.12.2007

Program 6

5V
P5.1
P3.2

P3.2

P5.1
Na P5.0 ma być generowany sygnał prostokątny o półokresie 1s tak jak przedstawia wykres.

01. ORG 0000h


02. LJMP 1000h
03. ORG 1000h
04.
05. D50L EQH B0h
06. D50H EQH 3Ch
07.
08. MOV TMOD,#01h
09. SETB TR0
10. MOV TLO,#D50L
11. MOV TH0,#D50H
12. SETB ET0
13. SETB EAL
14. MOV R0,#14h
15.
16. MAIN: LJMP MAIN
17.
18. ORG 000Bh
19. LJMP 2000h
20. ORG 2000h
21. JNB P3.2, BBB
22. CLR P5.1
23. RETI
24. BBB: DJNZ R0,CCC
25. MOV R0,#14h
26. CPL P5.1
27. CCC: RETI

● wiersze 05.-06. → przypisanie zmiennym wartości,


● wiersze 08.-11. → inicjalizacja timera,
wartości zapisane do rejestrów liczących TL0 i TH0 określają ile cykli ma zliczyć timer (w
tym wypadku zapełnienie timera będzie trwać 50ms)
● wiersze 12.-13. → inicjalizacja przerwań,
● wiersz 14. i 25. → zapisanie do rejestru R0 ile razy timer ma się przepełnić, aby program nie
przeszedł od razu do wykonywania pętli CCC, tylko zmienił sygnał na P5.1 (w tym
wypadku po 20 razach, czyli sygnał będzie się zmieniał co 20 x 50ms = 1s),
● wiersze 18.-27. → obsługa przerwania.

Program 7 5V
5V
P5.6 Dioda ma się palić, tylko gdy przycisk jest
wciśnięty.

P3.0

01. ORG 0000h


02. LJMP 1000h
03. ORG 1000h
04.
05. WARTOSC_L EQH ...
06. WARTOSC_H EQH ...
07.
08. MOV TMOD,#01h
09. SETB TR0
10. MOV TLO,#WARTOSC_L
11. MOV TH0,#WARTOSC_H
12. SETB ET0
13. SETB EAL
14.
15.
16. MAIN: LJMP MAIN
17.
18. ORG 000Bh
19. LJMP 2000h
20. ORG 2000h
21. JB P3.0, AAA
22. CLR P5.6
23. LJMP BBB
24. AAA: SETB P5.6
25. BBB: RETI

● wiersze 05.-06. → przypisanie zmiennym wartości,


● wiersze 08.-11. → inicjalizacja timera,
● wiersze 12.-13. → inicjalizacja przerwań,
● wiersze 18.-25. → obsługa przerwania.
○ wiersz 21. → sprawdza czy przycisk jest włączony, jeśli tak to ustawia 0 w P5.6 i dioda
się świeci, jeśli nie, skacze do pętli AAA i ustawia 1 na P5.6 i dioda się nie świeci.

Wykład 10 11.12.2007

Rejestry stanu procesora i znaczniki

Rejestry stanu przechowują bity stanu mówiące np. o przepełnieniu rejestrów procesora:

7 0
CY AC F0 RS1 RS0 OV F1 P ← PSW

PSW - Program Status Word

Bity charakterystyczne dla wszystkich procesorów:


● CY (lub C) - carry/borrow - przeniesienie/pożyczka
● AC - auxillary carry - pomocniczy bit przeniesienia
● P - pairity bit - bit parzystości
● OV - Overflow - przpełnienie

Dla procesorów rodziny 51:


● RS1 i RS0 - bity określające bank rejestrów wg tabeli poniżej:

RS1 RS0 bank rejestr bank adres pamięci


0 0 0 R0 0 00h
0 1 1 R1 0 01h
1 0 2 R2 0 02h
...
1 1 3
R7 0 07h
R0 1 08h
...
R7 1 0Fh
R0 2 10h
...
R7 2 17h
...
R7 3 1Fh
Przykład

ORG 0000h
LJMP 1000h
ORG 1000h

MOV R7,#43h ← zapisuje do rejestru R7 w banku 0 wartość 43h


SETB RS1 ← ustawia bit RS1 na 1 → bank 2
MOV a,R7 ← przeniesienie zawartości rejestru R7 banku 3 do akumulatora
...

● F0, F1 - flagi ogólnodostępne

Bit CY - jako znacznik przeniesienia, wykorzystywany jest przy wykonywaniu operacji


dodawania. Ustawiany:
● na 1:
○ jeśli wynik dodawania przekracza zakres słowa obsługiwanego przez procesor (w 51 - 8
bitów),
● na 0:
○ jeśli wynik dodawania mieści się w zakresie słowa obsługiwanego przez procesor.

Bit CY - jako znacznik pożyczki, wykorzystywany jest przy wykonywaniu operacji


odejmowania (procesor wykonuje operacje dodawania/odejmowania bez znaków!) . Ustawiany:
● na 1:
○ jeśli odjemna jest mniejsza niż odjemnik,
● na 0:
○ jeśli odjemna jest większa niż odjemnik.

Bit AC - pomocniczy bit przeniesienia - spełnia podobną rolę co bit CY, tylko stosowany jest do
operacji w kodzie BCD, natomiast znacznik C - dla kodu naturalnego binarnego.

Znacznik OV (overflow) - bit przepełnienia. Używany do operacji ze znakiem.

Ustawiony na 1:
● jeśli jest przeniesienie z pozycji 7. na wyższą i jednocześnie nie z 6. na 7.
● jeśli jest przeniesienie z pozycji 6. na 7. i jednocześnie nie z 7. na 8.

P - bit parzystości.
Ustawiany na 1 jeśli w wyniku jest parzysta liczba „jedynek”.

Należy pamiętać, że znaczniki nie są ustawiane po wykonaniu każdej operacji. Na znaczniki


wpływają najczęściej instrukcje logiczne i arytmetyczne.
Wykład 11 18.12.2007

Program 8
Napisać program dodający dwie 8-bitowe liczby jak na schemacie:

→ P3 P5 → low

→ P4 P6 → high

Wersja 1
01. ORG 0000h
02. LJMP 1000h
03. ORG 0000H

04. MOV P5, #00h


05. MOV P6, #00h
06.
07. BBB: MOV a,P3
08. ADD a,P4
09. MOV P5,a
10. JC AAA
11. CLR P6.0
12. LJMP BBB
13. AAA: SETB P6.0
14. LJMP BBB

● samo dodawanie P3 do P4 odbywa się w wierszach 07.-08. (w procesorach rodziny 51


dodawanie musi się odbyć w akumulatorze)
● JC _ - jeśli znacznik przeniesienia jest równy jeden następuje skok do etykiety/ adresu _

Wersja 2

01. ORG 0000h


02. LJMP 1000h
03. ORG 0000h

04. MOV P5, #00h


05. MOV P6, #00h
06.
07. BBB: MOV a,P3
08. ADD a,P4
09. MOV P5,a
10. MOV P6.0,C
11. LJMP BBB

Obie wersje zajmują 100% mocy obliczeniowej procesora.


Program 9
Napisać program dodający liczbę 8-bitową i 16-bitową jak na schemacie:

R1 R0 liczba 16-bitowa

+ R2 liczba 8-bitowa

R4 R5 R6

01. ORG 0000h


02. LJMP 1000h
03. ORG 0000h
04.
05. MAIN: LCALL DOD16P8
06. LJMP MAIN
07.
08. MOV a,R0
09. ADD a,R2
10. MOV R4,a
11. MOV a, R1
12. ADDC a,#00h
13. MOV R5,a
14. JC AAA
15. MOV R6,#00h
16. LJMP BBB
17. AAA: MOV R6,#01h
18. BBB: RET

● ADDC a,__ - dodaj do akumulatora z przeniesieniem (patrz na końcu skryptu)


● program zużywa 100% mocy obliczeniowej procesora

Wykład 12 8.01.2008

Przetwornik analogowo/cyfrowy

pin

Rejestr
MUX S&H ADC wyjściowy
(w 51 - ADDAT)

VREF+ VREF-
MUX - multiplekser
S&H - Sample And Hold
ADC - Analog Digital Converter - przetwornik z kompensacją wagową, najczęściej 12-14 bitowy
VREF - wartości referencyjne napięcia określające zakres przetwarzania przetwornika
Rejestr konfiguracyjny ADCON (rodzina 515)

7 0
x x x BSY ADM MX2 MX1 MX0

ADCON jest rejestrem adresowalnym bitowo.

BSY - flaga zajętości (busy)


Ustawiana jest na 1 przez hardware przetwornika gdy przetwornik pracuje
ADM - tryb konwersji
Ustawiona na 1 → po starcie następuje stałe przetwarzanie
Ustawiona na 0 → konwersja jednokrotna start → konwersja → stop

MX2
MX1 - sterowanie multipleksera (wybór kanału wejściowego)
MX0

Rejestr DAPR - służy do ustawiania wartości referencyjnych, wpisanie dowolnej wartości


spowoduje start przetwornika
np.:
mov DAPR,#00h
spowoduje ustawienie górnej wartości na wartość napięcia zas. = 5V, natomiast dolna wartość = 0V.

Program 10
Zmierzyć wartość analogową napięcia na M6 i przesłanie na P4 wartości w kodzie BCD.

Wersja 1

00. ORG 0000h


01. LJMP 1000h
02. ORG 1000h
03.
04. CLR ADM
05. SETB MX2
06. SETB MX1
07. CLR MX0
08.
09. BBB: MOV DAPR,#00h
10. AAA: JB BSY,AAA
11. MOV P4,ADDAT
12. LJMP BBB

● wiersz 04. → inicjalizacja hardware'u,


● wiersze 05. - 07. → ustawienie wejścia M6 multipleksera
● wiersz 09. → ustawienie VREF 0-5V, start przetwornika
● wiersz 10. → pętla czekająca na koniec pracy przetwornika
● wiersz 11. → transfer na P4
● program zużywa 100% mocy obliczeniowej procesora
Wersja 2

00. ORG 0000h


01. LJMP 1000h
02. ORG 1000h
03.
04. MOV TL0,#wartoscL
05. MOV TH0,#wartoscH
06. MOV TMOD, #01h
07. SETB TR0
08.
09. CLR ADM
10. SETB MX2
11. SETB MX1
12. CLR MX0
13.
14. SETB ET0
15. SETB EADC
16. SETB EAL
17.
18. MAIN: LJMP MAIN
19.
20. ORG 000Bh
21. LJMP 2000h
22. ORG 2000h
23.
24. MOV TL0,#wartoscL
25. MOV TH0,#wartoscH
26. MOC DAPR,#00h
27. RETI
28.
29. ORG 00H3h
30. LJMP 3000h
31. ORG 3000h
32.
33. MOV P4,ADDAT
34. CLR IADC
35. RETI

● działanie tego programu opiera się na wykorzystaniu przerwań timera i przetwornika:


co pewien czas (określony przez programistę) timer startuje przetwornik, który po
skończeniu pracy wywołuje własne przerwanie, podczas którego następuje przekazanie
wartości na P4,
● należy pamiętać, że flagę przerwania przetwornika IADC należy zdjąć software'owo

Wersja 3
00. ORG 0000h
01. LJMP 1000h
02. ORG 1000h
03.
04. MOV TL0,#wartoscL
05. MOV TH0,#wartoscH
06. MOV TMOD, #01h
07. SETB TR0
08.
09. CLR ADM
10. SETB MX2
11. SETB MX1
12. CLR MX0
13.
14. SETB ET0
15. SETB EAL
16.
17. MAIN: LJMP MAIN
18.
19. ORG 000Bh
20. LJMP 2000h
21. ORG 2000h
22.
23. MOV P4,ADDAT
24. MOV TL0,#wartoscL
25. MOV TH0,#wartoscH
26. MOC DAPR,#00h
27. RETI

● w tej wersji następuje przekazanie wartości na P4 z opóźnieniem - przerwanie timera


najpierw przekazuje wartość na P4 (za pierwszym razem będzie to 0) a dopiero później
startuje przetwornik. Zatem otrzymujemy wartość z opóźnieniem o jeden okres timera.

Wykład 13 15.01.2008

Połączenie typu point-to-point

Magistrala (bus)
Magistrale:
● wewnętrzne:
○ równoległe:
■ ISA,
■ PCI,
■ AGP,
○ szeregowe:
■ 1-wire,
2
■ IC
● zewnętrzne:
○ równoległe:
■ HPIB,
■ PCMCIA,
■ Centronics,
○ szeregowe:
■ RS485,
■ USB,
■ CAN.

Żeby wejść na magistrale potrzebny jest interfejs - hardware i software

Magistrala równoległa:
Połączenie asynchroniczne

W zasadzie jest to połączenie point-to-point

Interfejs szeregowy

rejestr przesuwny
zegar
B0 B7 OUT

D0 D7

INTERNAL DATA BUS

zegar IN
D0 D7
Zazwyczaj transfer jest 8 bitowy lub 9 bitowy (8 bitów + bit parzystości, jak na powyższym
schemacie). Podczas trwania transmisji każdy bit jest 3 razy próbkowany. Jeśli 2 kolejne próbki nie
są takie same, to transmisja jest wstrzymywana.
Ramka transmisji - 10 bitów
Bond rate [Hz] - częstotliwość przekazywania bitów ramki (nie danych)

Master nadaje - wszystkie slave'y odbierają, po przekazaniu adresu dane odbiera tylko slave
docelowy, reszta przechodzi w stan uśpienia. Jeśli na 9 bicie paczki jest 1 → jest nadawany adres,
jeśli 0 → są nadawane dane.
Wykład 14 22.01.2008

SCL
SCL

SDA
SCL
SCL

SDA
SCL

SDA
SDA

SDA

MASTER 1 SLAVE 1 SLAVE 2 MASTER N SLAVE N

I2C (Inter-Integrated Circuit bus) –opracowano w firmie Philips, pozwala na komunikację


pomiędzy różnymi układami za pomocą dwuprzewodowej magistrali. Układami tymi mogą być np:
pamięci (EEPROM, RAM), multipleksery, porty I/O, sterowniki wyświetlaczy LED, przetworniki
A/C, układy zegarów i inne.
Magistrala składa się z dwóch dwukierunkowych linii:
SDA – linia służąca do transmisji danych,
SCL – linia impulsów zegarowych.
Układy są dołączane do tych linii bezpośrednio
Układy pracują w jednym z dwóch trybów:
Master – układ może przejąć kontrolę nad magistralą i przebiegiem transmisji
danych, jego zadaniem jest wysyłanie sekwencji start i stop; wytwarza
sygn. zegarowy.
Slave – układ jest dopuszczany do transmisji danych przez urządzenie master.

VDD

Master Slave 1 Slave 2 Slave 3


Rp Rp
SCL

SCL

SCL
SCL

SDA

SDA
SDA
SDA

SCL
SDA
Do innych układów Do innych układów
Master i/lub Slave Master i/lub Slave
Każdy z układów posiadających interfejs I2C ma własny adres, który jest sprzętowo ustalony przez
producenta, jakkolwiek użytkownik może wpływać na część nastawy tego adresu (np. za pomocą
DIP-switch; ustawia się zazwyczaj 3 najmłodsze bity).
Urządzenia podłączane mogą też być wykonane w różnych technologiach (np. NMOS, CMOS,
TTL, ...).
I2C jest interfejsem multi-master, tzn. że możliwe jest zastosowanie wielu układów typu master
podłączonych do jednej magistrali.
Transmisja może się odbywać bardzo wolno, można ją także wstrzymać bez żadnych konsekwencji.

Górna granica szybkości transmisji:


- 100 kb/s – w trybie standard,
- 400 kb/s – w trybie fast,
- 3,4 Mb/s – w trybie high speed.

W specyfikacji interfejsu nie jest określona maksymalna liczba urządzeń,które można podłączyć do
magistrali. Ograniczeniem jest tylko suma pojemności pasożytniczych i wejściowych układów,
która nie powinna przekraczać 400pF dla każdej linii sygnałowej.

Standard określa również takie parametry jak np:


- max. i min. częstotliwość sygnału SCL,
- min. czas pomiędzy sygn. START i STOP,
- min. czas trwania wysokiego i niskiego stanu sygnału SCL,
- czas narastania i opadania zboczy sygnałów SDA i SCL,
- czas oczekiwania po wysłaniu sygnału START,
- czas ustalenia po powtórnym wysłaniu sygn. START.

Budowa portów
● Linie SDA i SCL są dwukierunkowymi liniami podłączonymi do dodatniego napięcia
zasilania przez rezystory podciągające (pull-up).
● Kiedy magistrala jest wolna obie linie są w stanie wysokim.
● Porty – typu otwarty dren (lub otwarty kolektor), tak aby można było wykonać operację
iloczynu logicznego na drucie (wired-AND).
Transmija danych
● Dane przesyłane sformatowane są w ramki o długości 8 bitów.
● Liczba przesyłanych bajtów jest zmienna i zależy od układów zastosowanych w systemie.
● Zwykle po każdym bajcie następuje jego potwierdzenie (ACK–acknowledge).
● Gdy przesyłamy słowa dłuższe niż jednobajtowe, to jako pierwszy przesyłany jest zawsze
bajt bardziej znaczący (MSB).
● Transmisja może być wstrzymana (np. gdy posiada niższy priorytet) poprzez wymuszenie
na linii SCL stanu niskiego.

Sekwencje START i STOP


Sygnał stopu
Sygnał startu
(końca transmisji)
(początku transmisji)
SDA
SDA

SCL
SCL

Układ master synchronizuje przesył za pomocą sygnału na linii SCL. Stan na linii SDA musi być
ustalony przed pojawieniem się „1” na linii SCL i powinien trwać stabilnie przy opadającym
zboczu SCL.

Sekwencja przesyłania jednego bitu

SDA

SCL

obszar stabilnego obszar zmian stanu


stanu linii danych linii danych
Typowa ramka danych wraz z niezbędnymi sekwencjami sterującymi

Po sygnale START układ master najczęściej wysyła adres docelowego układu slave i
oczekuje potwierdzenia gotowości z jego strony za pomocą sygnału ACK. W praktyce odbiór ACK
odbywa się w taki sposób, że master ustawia linię SDA na „1” i generuje 9-ty impuls zegarowy.
Układ slave odbierając ten impuls wymusza stan niski na SDA. Ta zmiana jest traktowana jako
potwierdzenie gotowości do nadawania lub odebranie bajtu danych.
Jeśli po wysłaniu adresu slave nie generuje sygnału ACK, linia SDA musi być ustawiona
przez niego na „1”. W takim przypadku master powinien wygenerować STOP, zwalniając
magistralę. Jeśli dane są wysyłane przez slave’a a odbierane przez master’a,to wysłanie przez ten
układ bitu braku potwierdzenia jest informacją dla slave’a (nadającego dane), że zakończono
właśnie transmisję ostatniego bajtu danych. Wtedy slave zwalnia linię danych SDA, by umożliwić
układowi master wysłanie sygnału STOP.

Formanty ramek danych:

Dane mogą być przesyłane następująco:

Sposób przesyłania danych z układu master do slave.


Odczyt danych z układu slave przez master bezpośrednio po przesłaniu bajtu adresu.

R/W - bit kierunku przesyłania danych (0 = zapis; 1 = odczyt)


ACK - potwierdzenie przesłane przez układ slave – „0” – SDA w stanie niskim
NACK - potwierdzenie przesłane przez układ slave – „1” – SDA w stanie wysokim

Arbitraż – konfiguracje multi-master


W większości przypadków arbitraż nie jest potrzebny ponieważ transmisja danych może być
zainicjowana przez master’a tylko wtedy, gdy magistrala jest wolna. Jednak, gdy dwa urządzenia
master jednocześnie wygenerują sygnał START, wówczas arbitraż jest niezbędny.

Arbitraż przeprowadzony dla dwóch układów master: master_1 przegrywa podczas transmisji
trzeciego bitu. Dzieje się tak, ponieważ stan wewnętrznej linii danych (DANE_1) nie jest zgodny ze
stanem lini SDA. Arbitaraż przegrywa ten master, który pierwszy nada 0.
Lista rozkazów mikrokontrolerów rodziny MCS-51
Instrukcje arytmetyczne
Wykonywane Cykle Rozmiar
Mnemonik Argumenty Opis
operacje maszynowe [bajty]
''Add to acummulator'' – dodaj do akumulatora. Do wartości przechowywanej w akumulatorze dodawany jest wskazany
ADD
argument, a wynik zostaje wpisany do akumulatora.
ADD A,Rn (A)←(A)+(Rn) 1 1 Do akumulatora dodawana jest zawartość rejestru Rn.

ADD A,addr8 Do akumulatora dodawana jest zawartość komórki


(A)←(A)+(addr8) 1 2
w wewnętrznym RAM.
Do akumulatora dodawana jest zawartość komórki
ADD A,@Ri (A)←(A)+((Ri)) 1 1 w wewn. RAM o adresie wskazywanym przez rejestr Ri
(R0 lub R1).
ADD A,#data8 (A)←(A)+data8 1 2 Do akumulatora dodawany jest argument stały.
''Add to acummulator with carry'' – dodaj do akumulatora z przeniesieniem. Do wartości przechowywanej w
ADDC akumulatorze dodawany jest wskazany argument oraz zawartość znacznika przeniesienia C, a wynik zostaje wpisany do
akumulatora.

ADDC A,Rn Do akumulatora dodawana jest zawartość rejestru Rn


(A)←(A)+(Rn)+(C) 1 1
oraz C.

ADDC A,addr8 Do akumulatora dodawana jest zawartość komórki


(A)←(A)+(addr8)+(C) 1 2
w wewnętrznym RAM oraz znacznik C.
Do akumulatora dodawana jest zawartość komórki
ADDC A,@Ri (A)←(A)+((Ri))+(C) 1 1 w wewnętrznym RAM o adresie wskazywanym przez
rejestr Ri (R0 lub R1) oraz znacznik C.

ADDC A,#data8 Do akumulatora dodawany jest argument stały


(A)←(A)+data8+(C) 1 2
i znacznik C.
'' Substract from acummulator with borrow” – odejmij od akumulatora z pożyczką. Od wartości przechowywanej
SUBB w akumulatorze odejmowany jest wskazany argument oraz zawartość znacznika przeniesienia C,a wynik zostaje wpisany
do akumulatora.

SUBB A,Rn Od akumulatora odejmowana jest zawartość rejestru Rn


(A)←(A)-(Rn)-(C) 1 1
oraz C.

SUBB A,addr8 Od akumulatora odejmowana jest zawartość komórki


(A)←(A)-(addr8)-(C) 1 2
w wewnętrznym. RAM oraz znacznik C.
od akumulatora odejmowana jest zawartość komórki w
SUBB A,@Ri (A)←(A)-((Ri))-(C) 1 1 wewnętrznym R A M o adresie wskazywanym przez
rejestr Ri oraz znacznik C.
od akumulatora odejmowany jest argument stały
SUBB A,#data8 (A)←(A)-data8-(C) 1 2
(8−bitowa liczba) oraz znacznik C .

INC ''Increment'' – zwiększenie o 1, inkrementacja. Do wskazanego argumentu jest dodawana jedynka


INC A (A)←(A)+1 1 1 Do akumulatora dodawana jest jedynka.
INC Rn (Rn)←(Rn)+1 1 1 Do zawartości rejestru Rn dodawana jest jedynka.

INC addr8 Do zawartości komórki o podanym adresie dodawana


(addr8)←(addr8)+1 1 2
jest jedynka.

INC @Ri Do zawartości komórki o adresie wskazywanym przez


((Ri))←((Ri))+1 1 1
Ri dodawana jest jedynka.
Do 16−bitowego wskaźnika danych DPTR złożonego z
INC DPTR (DPTR)←(DPTR)+1 2 1 rejestrów SFR: DPH (bardziej znaczący bajt) i DPL
(mniej znaczący bajt) dodawana jest jedynka.
DEC ''Decrement'' – zmniejszenie o 1, dekrementacja. Od wskazanego argumentu odejmowana jest jedynka.
DEC A (A)←(A)-1 1 1 Od akumulatora odejmowana jest jedynka.
DEC Rn (Rn)←(Rn)-1 1 1 Od zawartości rejestru Rn odejmowana jest jedynka.

DEC addr8 Od zawartości komórki o podanym adresie odejmowana


(addr8)←(addr8)-1 1 2
jest jedynka.

DEC @Ri Od zawartości komórki o adresie wskazywanym przez


((Ri))←((Ri))-1 1 1
Ri odejmowana jest jedynka.
„Multiply” – pomnóż. 8−bitowa liczba bez znaku
znajdująca się w akumulatorze jest mnożona przez
MUL A,B (BA)15..0← (A)·(B) 4 1 8−bitową liczbę bez znaku z rejestru B. 16−bitowy wynik
wpisywany jest do rejestrów B i A (bardziej znaczący bajt
do B, mniej znaczący bajt do A.
„Divide” – podziel. 8−bitowa liczba bez znaku,
znajdująca się w akumulatorze jest dzielona przez
8−bitową liczbę z rejestru B. Cześć całkowita ilorazu
DIV A,B całości:(A)← int(A/B) wpisywana jest do akumulatora, a reszta z dzielenia
4 1
reszta:(B)← mod(A/B) do rejestru B. W przypadku, gdy dzielnik jest równy 0
(B=0) to po wykonaniu operacji zawartość akumulatorze
i rejestru B jest nieokreślona oraz dodatkowo ustawiony
zostaje znacznik OV.
„Decimal adjust” – korekcja dziesiętna. Wykonywana jest
korekcja dziesiętna wyniku dodawania. Operacja ta
sprowadza wynik do postaci dwóch cyfr dziesiętnych w
kodzie BCD, jeżeli argumenty były w kodzie BCD.
Rozkaz ten powinien być używany jedynie w połączeniu
z rozkazem dodawania (ADD, ADDC). Także
inkrementacja powinna odbywać się poprzez instrukcję
Jeśli [[(A)3..0 > 9] ADD A, #1, a nie INC A, bowiem w tym drugim
lub [AC = 1]] przypadku nie są ustawianie znaczniki C i AC, tak więc
DA A to (A)3..0 ← (A)3..0 + 6 nie może być wykonana korekcja dziesiętna. Korekcja
1 1
Jeśli [[(A)7..4 > 9] polega na tym że w przypadku kiedy po wykonanej na
lub [C = 1]] akumulatorze operacji dodawania (ADD, ADDC)
to (A)7..4 ← (A)7..4 + 6 zawartość jego bitów 3...0 jest większa od 9 lub jest
ustawiony znacznik AC, to do wartości akumulatora doda
wana jest liczba 6. Po tym jeżeli okaże się że zawartość
bitów 7...4 jest większa od 9 lub jest ustawiony znacznik
C to do tych bitów dodawana jest także liczba 6. Jeżeli
podczas tej ostatniej operacji wystąpiło przeniesienie to
do znacznika wpisywana jest 1, w przeciwnym wypadku
stan znacznika C nie zmienia się.

Instrukcje logiczne
Cykle Rozmiar
Mnemonik Argumenty Wykonywane operacje Opis
maszynowe [bajty]
''Logical AND'' – iloczyn logiczny. Wykonywany jest iloczyn logiczny AND (mnożenie bitów „bit po bicie”) wskazanych
ANL
w instrukcji dwóch argumentów. Wynik operacji jest wpisywany do argumentu pierwszego instrukcji

ANL A,Rn Wymnożona logicznie zostaje zawartość akumulatora


(A)←(A) and (Rn) 1 1
i rejestru Rn, wynik w akumulatorze.
Wymnożona logicznie zostaje zawartość akumulatora i
ANL A,addr8 (A)←(A) and (addr8) 1 2 komórki o podanym adresie, wynik zostaje
umieszczony w akumulatorze.
Wymnożona logicznie zostaje zawartość akumulatora
ANL A,@Ri komórki w wewnętrznym RAM o adresie
(A)←(A) and ((Ri)) 1 1
wskazywanym przez rejestr Ri, wynik zostaje
umieszczony w akumulatorze.
Wymnożona logicznie zostaje zawartość akumulatora
ANL A,#data8 (A)←(A) and data8 1 2 przez argument stały, wynik zostaje umieszczony w
akumulatorze.
Wymnożona logicznie zostaje zawartość komórki o
ANL addr8,A podanym adresie i zawartość akumulatora, wynik
(addr8)←(addr8) and (A) 1 2
zostaje umieszczony w komórce pamięci o podanym
adresie.
wymnożona logicznie zostaje zawartość komórki o
ANL addr8,#data8 (addr8)←(addr8) and data8 2 3 adresie „adres” przez argument stały, wynik zostaje
umieszczony w komórce pamięci o podanym adresie.
ORL ''Logical OR'' – suma logiczna. Wykonywana jest suma logiczna OR (dodawanie bitów „bit po bicie”) wskazanych w
instrukcji dwóch argumentów. Wynik operacji jest wpisywany do argumentu pierwszego instrukcji.

ORL A,Rn Dodana logicznie zostaje zawartość akumulatora


(A)←(A) or (Rn) 1 1
i rejestru Rn, wynik w akumulatorze.
Dodana logicznie zostaje zawartość akumulatora
ORL A,addr8 (A)←(A) or (addr8) 1 2 i komórki o podanym adresie, wynik zostaje
umieszczony w akumulatorze.
Dodana logicznie zostaje zawartość akumulatora
ORL A,@Ri (A)←(A) or ((Ri)) 1 1 komórki w wewnętrznym RAM o adresie
wskazywanym przez rejestr Ri, wynik w akumulatorze.

ORL A,#data8 Dodana logicznie zostaje zawartość akumulatora przez


(A)←(A) or data8 1 2
argument stały, wynik w akumulatorze.
Dodana logicznie zostaje zawartość akumulatora
ORL addr8,A (addr8)←(addr8) or (A) 1 2 i komórki o podanym adresie, wynik zostaje
umieszczony w komórce pamięci o adresie.
Dodana logicznie zostaje zawartość komórki o adresie
ORL addr8,#data8 (addr8)←(addr8) or data8 2 3 oraz argument stały, wynik zostaje umieszczony
w komórce pamięci o adresie.
XRL ''Logical XOR'' – zsumuj mod 2 (różnica symetryczna). Wykonywana jest różnica symetryczna wskazanych w instrukcji
dwóch argumentów. Wynik operacji jest wpisywany do argumentu pierwszego instrukcji.

XRL A,Rn Zsumowana (mod 2) zostaje zawartość akumulatora i


(A)←(A) xor (Rn) 1 1
rejestru Rn, wynik w akumulatorze.
Zsumowana (mod 2) logicznie zostaje zawartość
XRL A,addr8 (A)←(A) xor (addr8) 1 2 akumulatora i komórki o podanym adresie, wynik
zostaje umieszczony w akumulatorze.
Zsumowana (mod 2) logicznie zostaje zawartość
XRL A,@Ri akumulatora komórki w wewnętrznym RAM o adresie
(A)←(A) xor ((Ri)) 1 1
wskazywanym przez rejestr Ri, wynik zostaje
umieszczony w akumulatorze.
Zsumowana (mod 2) logicznie zostaje zawartość
XRL A,#data8 (A)←(A) xor data8 1 2 akumulatora przez argument stały, wynik zostaje
umieszczony w akumulatorze.
Zsumowana (mod 2) logicznie zostaje zawartość
XRL addr8,A akumulatora i komórki o podanym adresie „adres”,
(addr8)←(addr8) xor (A) 1 2
wynik zostaje umieszczony w komórce pamięci o
adresie.
Zsumowana (mod 2) logicznie zostaje zawartość
XRL addr8,#data8 (addr8)←(addr8) xor data8 2 3 komórki o adresie „adres” oraz argument stały, wynik
zostaje umieszczony w komórce pamięci o adresie.

CLR A ''Clear accumulator'' – zeruj akumulator. Do


(A) ← 0 1 1
akumulatora zostaje wpisana wartość 0.
''Complement accumulator'' – zaneguj akumulator.
CPL A (A) ← not(A) 1 1 Wartość akumulatora zostaje zanegowana, wynik
wpisany zostaje do akumulatora.

RL A (A) ← rotacja w lewo ''Rotate left” – przesuń w lewo. Zawartość akumulatora


1 1
(A) zostaje przesunięta w lewo o 1 pozycję (o 1 bit).
''Rotate left through carry” – przesuń cyklicznie w lewo
ze znacznikiem C. Zawartość akumulatora zostaje
przesunięta w lewo o 1 pozycję (o 1 bit) z
uwzględnieniem znacznika C, to znaczy że:
(A) ← rotacja w lewo (A)
RLC A 1 1 znacznik C przyjmuje wartość bitu 7
zC
bit 1 przyjmuje wartość bitu 0
bit 2 przyjmuje wartość bitu 1 (...)
bit 7 przyjmuje wartość bitu 6
bit 0 przyjmuje wartość znacznika C.
''Rotate right” – przesuń w prawo. Zawartość
RR A (A) ← rotacja w prawo
1 1 akumulatora zostaje przesunięta w prawo o 1 pozycję
(A)
(o 1 bit).
'' Rotate right through carry'' – przesuń cyklicznie w
prawo ze znacznikiem C. Zawartość akumulatora
zostaje przesunięta w prawo o 1 pozycję (o 1 bit) z
uwzględnieniem znacznika C, to znaczy że:
RRC A (A) ← rotacja
1 1 znacznik C przyjmuje wartość bitu 0)
w prawo (A) z C bit 0 przyjmuje wartość bitu 1
bit 1 przyjmuje wartość bitu 2 (...)
bit 6 przyjmuje wartość bitu 7
bit 7 przyjmuje wartość znacznika C.
''Swap nibbles within accumulator'' – wymień półbajty
w akumulatorze. W wyniku tej instrukcji wymieniona
SWAP A zostaje zawartość bitów 3...0 (mniej znaczący półbajt)
(A3...0) ↔ (A7...4) 1 1
i bitów 7...4 (bardziej znaczący półbajt) akumulatora.
Operacja ta jest równoważna 4−krotnemu przesunięciu
zawartości akumulatora

Instrukcje transferu
Cykle Rozmiar
Mnemonik Argumenty Wykonywane operacje Opis
maszynowe [bajty]
''Move'' – przesuń, przenieś. Ogólne instrukcję MOV można zapisać jako: MOV <d> <s>, gdzie: <d> jest miejscem
przeznaczenia (''destination''), a <s> źródłem pobrania danej (''source''). W wyniku wykonania instrukcji MOV zawartość
MOV źródła <s> zostaje skopiowana do obiektu przeznaczenia <d>. We wszystkich przypadkach (oprócz jednego) argumentami
instrukcji MOV są wyrażenia 8–bitowe: rejestry, dane adresy pośrednie itp. Jedynie załadowanie 16–bitowego wskaźnika
adresu DPTR wymaga odpowiedniego 16–bitowego (stałej) argumentu.

MOV A,Rn Do akumulatora zostaje załadowana zawartość rejestru


(A) ← (Rn) 1 1
Rn.
Do akumulatora zostaje załadowana zawartość
MOV A,addr8 (A) ← (addr8) 1 2 komórki wewnętrznej pamięci RAM o podanym
adresie.
Do akumulatora zostaje załadowana zawartość komórki
MOV A,@Ri (A) ← ((Ri)) 1 1 wewn. R A M, której adres znajduje się w rejestrze Ri.

MOV A,#data8 Instrukcja załadowania 8–bitowej liczby do


(A) ← data8 1 2
akumulatora

MOV Do rejestru Rn zostaje załadowana zawartość


Rn, A (Rn) ← (A) 1 1
akumulatora.

MOV Rn,addr8 Do rejestru Rn zostaje załadowana zawartość komórki


(Rn) ← (addr8) 1 2
o podanym adresie.
MOV Rn,#data8 (Rn) ← data8 1 2 Do rejestru Rn zostaje wpisana 8–bitowa liczba.

MOV addr8, A Do komórki o podanym adresie zostaje wpisana


(addr8) ← (A) 1 2
zawartość akumulatora

MOV addr8,Rn Do komórki o podanym adresie zostaje wpisana


(addr8) ← (Rn) 2 2
zawartość rejestru Rn.
addr81, Przepisanie zawartości komórki o adresie (addr82), do
MOV (addr81) ← (addr82) 2 3
addr82 komórki o adresie (addr81).
Do komórki o podanym adresie zostaje wpisana
MOV addr8,@Ri (addr8) ← ((Ri)) 2 2 zawartość komórki której adres znajduje się w rejestrze
Ri.

MOV
addr8, Do komórki o podanym adresie zostaje wpisana
#data8 (addr8) ← data8 2 3
wartość stała.

MOV @Ri,A Do komórki o adresie znajdującym się w rejestrze Ri


((Ri)) ← (A) 1 1
zostaje wpisana zawartość akumulatora

MOV Do komórki o adresie znajdującym się w rejestrze Ri


@Ri,addr8 ((Ri)) ← (addr8) 2 2
zostaje wpisana zawartość komórki o podanym adresie.
@Ri, Do komórki o adresie znajdującym się w rejestrze Ri
MOV ((Ri)) ← data8 1 2
#data8 zostaje wpisana wartość stała

DPTR, Instrukcja załadowania 16–bitowego, bezwzględnego


MOV D PTR ← data16 2 3 adresu do wskaźnika danych DPTR (data16 → liczba
#data16
16-bitowa)
MOVC

Instrukcje sterujące
bezwarunkowe
warunkowe
Instrukcje bitowe

Korzystałem z „MCS(R) 51 Microcontroller Family User's Manual”


Legenda:
● Rn - jeden z rejestrów R0 do R7 aktywnego banku rejestrów,
● addr8 - 8-bitowy adres w wewnętrznej pamięci danych adresowanej bezpośrednio,
● @Ri - 8-bitowy adres umieszczony w jednym z dwóch rejestrów R0 lub R1 aktywnego
banku rejestrów.
● #data8 - 8-bitowa stała kodowana wewnątrz instrukcji.
● #data16 - 16-bitowa stała kodowana wewnątrz instrukcji.
● addr16 - 16-bitowy adres używany w instrukcjach LJMP i LCALL (praktycznie
zastępowany przez etykietę).
● addr11 - 11-bitowy adres używany w instrukcjach AJMP oraz ACALL (praktycznie
zastępowany przez etykietę).
● rel - 8-bitowe przesuniecie traktowane jako liczba ze znakiem w kodzie U2 i używane w
instrukcji SJMP oraz wszystkich instrukcjach skoków warunkowych (praktycznie
zastępowane przez etykietę).
● bit - adres bitu z wewnętrznej pamięci danych adresowanego bitowo lub obszaru SFR.
● (x) - w opisie operacji oznacza zawartość komórki w wewnętrznej pamięci danych o
adresie bezpośrednim x.
● ((x)) - w opisie operacji oznacza zawartość komórki wewnętrznej pamięci danych o
adresie zapisanym w rejestrze x.
● (y)XDATA - w opisie operacji oznacza zawartość komórki w zewnętrznej pamięci danych o
adresie y.
● (z)CODE - w opisie operacji oznacza zawartość komórki w pamięci kodu o adresie z.
● Xy..z - W opisie operacji oznacza bity od y do z rejestru X.

You might also like