background image

1. Zbiór typu .hex jest wynikiem pracy assemblera. Jest to standardowy format zapisywany w 
kodzie ASCII wierszami o następujących polach: kod startu ':', liczba bajtów danych (dwa znaki), 
adres pamięci kodu, od którego wpisywane będą dane tego wiersza (4 znaki), typ pola danych (dwa 
znaki, 00 - oznacza treść programu, 01 - oznacza wiersz końca), 2n znaków dla n bajtów danych, 
najmniej znaczący bajt sumy kontrolnej utworzonej ze wszystkich bajtów bez pola ':' i bez siebie 
samej. Ten bajt sumy przed zapisem ma zmieniony znak wg "uzupełnienia dwójkowego" (czyli 
wynik powstaje z odjęcia od 0x100 albo przez XOR x 0xFF i dodaniu 0x01). Przykład wiersza 
programu do ładowania od adresu 00A0, oraz wiersza sygnalizującego koniec zbioru: 
 

(pozwoliłem sobie to zapisać w bardziej czytelny sposób) 

:10 00A0 00 C0E0C0D0D2D3C2D4C2AAC218753AFFC2 2F 
:00 0000 01 FF 
 
Wyjaśnienie znaczenia 1 wiersza: 
: (znak startu), 10 (dec. 16 - liczba bajtów), 00A0 (jakiś adres, nas nie interesuje), 00 (oznacza treść 
programu), teraz sekwencja 16 bajtów (każdy po 2 znaczki, to by się zgadzało), 2F (suma kontrolna). 
 
Obliczanie sumy kontrolnej (dodajemy wszystkie bajty prócz sumy kontrolnej i dwukropka): 
10 + 00 + A0 + 00 + C0 + E0 + C0 + D0 + D2 + D3 + C2 + D4 + C2 + AA 
+ C2 + 18 + 75 + 3A + FF + C2 = BD1 
Zostawiamy najmniej znaczący bajt (tj. D1; B wyrzucamy). 
Odejmujemy od 0x100 najmniej znaczący bajt, czyli nasze D1 i otrzymujemy sumę kontrolną. 
Wszystko się zgadza: 0x100 – 0xD1 = 0x2F 
 
Sprawdź, czy następujący wiersz jest poprawny (działanie analogiczne...): 
:10 0220 00 D2A8D2A9D2ABD2ACE4F52FF52AF54775 06 
 
2. Napisz obsługę przerwania timera T0, zliczającego cykle maszynowe w trybie 16-bitowym. 
Załóż, że T0 jest uruchomione. W przerwaniu zwiększana jest wartość zmiennej ILE aż 
osiągnie ona wartość 0xDE. Wtedy T0 ma zostać zatrzymane. 
 
Adres przerwania T0: 0Bh 
Rejestr TMOD dla trybu 16-bitowego timera 0 wygląda tak: 00000001b 
On/Off przerwań dla timera 0: ET0 
On/Off timera 0: TR0 
On/Off globalny przerwań: ET 
 

ILE DATA 20h 
 
CSEG AT 0Bh 
AJMP timer0_interrupt 
 
CSEG AT 0h 
AJMP reset 
 
CSEG AT 30h 
 

reset: 

 

 

MOV  TMOD, #0000001b 

 

 

SETB ET0 

 

 

SETB EA 

 

 

SETB TR0 

 

 

CLR A 

 
 

start: 

        SJMP $ 

background image

 
timer0_interrupt: 
 

INC A 

 

MOV ILE, A 

 

CJNE A, #0DEh, dalej 

 

CLR TR0 

 

dalej: 

 

 

RETI 

 
END 

 
3. Podaj cechy architektury ARM, które zasadniczo różnią ją od „rodziny 8051” i AVR. 
 

a)  ARM wykonuje prawie wszystkie instrukcje w jednym cyklu, podczas gdy w 8051 praktycznie 

wszystkie instrukcje potrzebują więcej niż jednego cyklu. Przykład instrukcji skoku 
warunkowego: DJNZ w 8051: 3 cykle, BNEQ w ARM: 1 cykl.  

b)  ARM oparte jest o architekturę RISC, 8051 o CISC (ma mniejszą liczbę instrukcji w 

porównaniu do ARM opartego o RISC). 

c)  W ARM instrukcje przetwarzania danych nie mogą odwoływać się bezpośrednio do pamięci, 

przetwarzane dane muszą znajdować się w rejestrach. 8051 może odwoływać się 
bezpośrednio do pamięci. 

d)  ARM posiada warunkowe instrukcje przetwarzania danych (tj. przed wykonaniem instrukcji 

sprawdzany jest określony warunek), 8051 nie posiada takiej funkcji.  

 
Bonus, różnice między AVR a 8051: 
Główną różnicą między rodziną AVR a 8051 są typy adresowania. O wiele więcej rejestrów możemy 
zaadresować w AVR niż w 8051, co ułatwia programowanie i skraca kod. Inną różnicą jest to, że 
instrukcje AVR zmieniają o wiele więcej flag mikrokontrolera. 
 
4. Napisz w assemblerze program, który ustawia zmienną PARITY na 1, gdy liczba jedynek w 
trzech bajtach 24-bitowej zmiennej umieszczonej w adresach BAJT, BAJT+1, BAJT+2 jest 
nieparzysta, a ustawia 0 w przypadku przeciwnym. 
 
PSW.0 (bit 0) – oznaczany jako P, to znacznik parzystości, ustawiany automatycznie w każdym cyklu 
maszynowym wskazuje na to czy liczba jedynek (na poszczególnych) pozycjach bitowych w 
akumulatorze A jest parzysta (P=0) czy nieparzysta (P=1). 

ZMIENNA DATA 30h 
PARITY BIT 0h 

CSEG AT 0H 
AJMP start 

start: 
    MOV 30h, #00010001B 
    MOV 31h, #01000000B 
    MOV 32h, #00000000B 
    CLR PARITY 
    MOV R0, #ZMIENNA 
    MOV R1, #3 

sprawdzaj: 
    MOV A, @R0 

background image

    JNB PSW.0, dalej 
    CPL PARITY 

dalej: 
    INC  R0 
    DJNZ R1, sprawdzaj 
    MOV  P2, 20h 

END 

5. Wymień najważniejsze różnice architektur RISC i CISC. 
Patrz zad. 3, to praktycznie cała odpowiedź. 
 
6. Z tablicy pod adresem 0x50 o długości 0x40 wybierz bajty z parzystą liczbą jedynek i utwórz z 
nich nową tablice. 
 
Ogólnie pod adresem na który wskazuje zmienna BUFOR (50h) mamy aktualną tablice. Przenosimy te 
elementy, które mają parzystą liczbę jedynek w zapisie bitowym do tablicy o adresie zdefiniowanym 
w TABLICA (70h). Wykorzystujemy bit PSW.0 (patrz zad. 4). 

ILE EQU 8 ; 0x60 = dec. 64 = 8 bajtów (elementów) 
BUFOR DATA 50h 
TABLICA DATA 70h 
 
CSEG AT 0h 
JMP start 
start: 
 

MOV R0, #TABLICA 

 

MOV A, #0 

 

MOV DPTR, #BUFOR 

 

MOV R1, #ILE 

 
loop: 
 

MOV  A, #0 

 

MOVC A, @A+DPTR ; Do A ladujemy WARTOSC z adresu 0x50 ... 

 

INC  DPTR       ; ... ktory zwiekszamy z kazdym obrotem petli 

 

JNB  PSW.0, dodaj_do_tablicy ; jezeli PSW.0 = 0 (parzyste) to skocz 

do event 
 

 

powrot: 
 

DJNZ R1, loop ; licznik petli 8 do 0 

 

AJMP $ 

 
dodaj_do_tablicy: 
 

MOV  @R0, A ; Ladujemy element do adresu 0x70... 

 

INC  R0     ; ...ktory zwiekszamy z kazdym obrotem petli 

 

AJMP powrot 

 
CSEG AT BUFOR 
DB 1,2,3,4,5,6,7,8  
; tablica z kolejnymi wartosciami 
; bitowo: 1, 10, 11, 100, 101, 110, 111, 1000 
; mamy 3 elementy z parzysta liczba bitow 
 
END 

 
7. Mamy DAC 10-bitowy o napięciu odniesienia U

ref

 = 2,048 V. Jaka będzie odpowiedź analogowa, 

gdy rejestry danych przechowują wartosci: DACDATAH = 0, DACDATAL = 0xF3. 

background image

Nie jestem pewien co do tego wzoru, ale ciężko znaleźć coś sensownego na ten temat. 
D = 0xF3 = 243 dec. 
N = 10 
U

ref

 = 2,048 

 

U

out

=U

ref

*D/2

 
U

out

 = 2,04800 * (243 / (2^10)) = 0,486 

 
8. Napisz podprogram dla uzyskania opóźnienia 1ms. Procesor ma cykl maszynowy równy 0.5us. 
 
Obliczamy x - liczbę potrzebnych cykli 
1ms = 1000µs 
1000 = x*0,5 
x = 2000 
 

MOV R1, #4 
petla: 
    MOV R0, #165 
    DJNZ R0, $ 
    DJNZ R1, petal 
NOP 
NOP 
NOP 

 
1+(1+165*3+3)*4 = 1997 + 3 = 2000 
 
NOP, MOV – 1 cykl 
DJNZ – 3 cykle 
 
9. Bufor danych znajduje się w pamięci pod adresem umieszczonym w R0 o długości umieszczoniej 
w R1. Utwórz 16 bitową sumę kontrolną w parze R2, R3. 
 
Nie do końca poprawnie, bo adres pamięci jest adresowany bezpośrednio (MOV DPTR, #50h) a nie 
poprzez R0. 
 

CSEG AT 0h 
JMP start 
 
start: 
 

MOV R1, #08h 

 

 

 

MOV R2, #0 

 

MOV R3, #0 

 

 

 

MOV DPTR, #50h 

 

 

 

petla: 

 

 

MOV A, #0 

 

 

MOVC A, @A+DPTR 

 

 

 

 

 

; tmp 

 

 

MOV R5, A 

 

 

 

 

 

MOV A, R3 

 

 

ADD A, R5 

background image

 

 

MOV R3, A 

 

 

MOV A, #0 

 

 

ADDC A, R2 

 

 

MOV R2, A 

 

 

 

 

 

INC DPTR 

 

 

DJNZ R1, petla 

 
CSEG AT 50h 
DB 132,245,135,234,215,134,156,159 
 
END 
 
 
 

1. Na wejście 8-mio bitowego przetwornika ADC podawane jest napięcie wzrastające liniowo od 
zera do wartości 10V z szybkością wzrostu 1 V / minutę. Proszę przyjąć, że ADC „próbkuje” sygnał 
co minutę i podać wartości rejestru odczytu ADC (binarnie, lub szesnastkowo) w kolejnych 10 
minutach, Napięcie referencyjne ADC wynosi 2.55 V. 
Po minucie masz 1V czyli liczymy tak: 
2,55 V = 255 (bo to jest maks do zapisania na 8 bitach) a 1V = x zatem:  
x = 255/2,55 = 100 zatem binarnie to jest 01100100  
Po drugiej minucie 2V to x = 2x255/2,55 = 200 to binarnie 11001000  
ITD.. 
 
2. Potrzebujemy, by w programie dla 8-mio bitowego mikro-kontrolera, o cyklu maszynowym 
wynoszącym 500ns nastąpiło opóźnienie pomiędzy wykonaniem dwóch instrukcji.  
a: ---- instrukcja  
opóźnienie  
b: ----- instrukcja  
Opóźnienie ma wynosić 1 sekundę. Przy rozwiązaniu można podać/założyć które z użytych komend 
są jedno, a które dwu-cyklowe. 
 
z obliczen wyszlo że potrzebujemy 2000000 cykli;  
 
1 s – 1000000000 ns  
Xs – 500 ns  
 
X= 0,0000005 s  
 
1 cykl – 0,0000005 s  
X cykli – 1s  
X = 2000000  
 
program:  
 
stala EQU 999 999  
 
start:  
mov R3, #stala // dwa cykle  
 
petla:  
DJNZ R3, petla //dwa cykle za każdym razem – petla przechodzi 999 999 , 999 999*2 +2 = 2000 000 
 

background image

3. Do magistrali I2C przyłączonych jest wiele procesorów. W pewnym momencie dwa z nich 
rozpoczynają równocześnie transmisję (, która, jak wiadomo, po sekwencji „start” rozpoczyna się 
od wysyłania adresu „slave'a”, z którym ma być nawiązane połączenie). Procesor A wysyła bajt o 
zawartości 0x8F, a procesor B bajt o treści 0x1F. Który procesor uzyska dostęp do magistrali. Jaki 
jest adres urządzenia, z którym „zwycięski” procesor nawiąże kontakt? Czy kolejny bajt wysyłany 
będzie od czy do procesora, który uzyskał dostęp? 
 
A – 0E = 0000 1110  
B – 1F = 0001 1111  
 
Procesor A uzyska dostęp do magistrali dlatego że bit zerowy jest rowny 0 a wiec master będzie pisać  
Adres urządzenia z którym nawiąże kontakt to : 0000 111  
 
Pytanie co w przypadku gdy zawartość bajtów wysyłanych przez procesory to:  
A - 8F = 1000 1111  
B - 1F = 0001 1111 
 
4. Rejestr PSW (Program Status Word) na pozycji 0 ma bit parzystości. Jest on ustawiany (na 1) jeśli  
aktualnie liczba jedynek w ACC jest nieparzysta, zerowany w przeciwnym, wypadku. W obszarze  
pamięci danych od adresu 0x50 do adresu 0xAF znajdują się bajty o różnych wartościach. Napisz  
program zliczający liczbę bajtów o nieparzystej liczbie jedynek. 
 
Stos Data 0Fh  
Bufor Data 50h  
Licz Data 22h  
Buforend Data BFh  
 
CSEG  
ORG 0  
 
AJMP start  
ORG 80h  
 
Start  
MOV SP, #stos  
(wypelnianie bufora)  
 
MOV Licz, #00  
MOV R0, #Bufor  
MOV A,@R0  
JNB PSW, dalej  
INC Licz  
 
dalej:  
 
INC R0  
CJNE R0, Bufend, ..  
 
END 
 
 

background image

5. Mikroprocesor wyposażony jest w 8-bitowy „timer”, który skonfigurowany jest tak, że 
przepełnienie powoduje przerwanie programowe. Timer zlicza cykle gdy ustawiony jest bit o 
nazwie TR1 (jeśli ten bit jest 0, to timer nie zlicza cykli). Należy napisać podprogram obsługi 
przerwania od tego Timer'a tak, by po piątym przepełnieniu ustawił rejestr R7 na wartość 0xFF oraz 
przestał zliczać cykle maszynowe.  
 
DO PIEC DATA 30h  
….  
Start:  
 
MOV DO PIEC, #00  
 
PUSH ACC  
PUSH PSW  
 
INC DO PIEC  
MOV A,DO PIEC  
CJNE A,#05, dalej  
CLR TR1  
MOV R7,#FF  
 
Dalej:  
POP PSW  
POP  
ACC  
RETI 
 
6. Załóżmy, że interfejs USART procesora skonfigurowany jest tak, że przesyła i odbiera 9 bitów 
danych (8 bitów, pełny bajt odbierany jest do rejestru SBUF, a bit dziewiąty do bitu o nazwie TB8). 
Zmienna BLAD ma być wyzerowana, gdy odczytany bajt z SBUF ma nieparzystą liczbę jedynek i 
równocześnie TB8 jest ustawione na 1 lub gdy SBUF ma parzystą liczbę jedynek i TB8 jest zerem. W 
przeciwnych wypadkach BLAD ma być różny od zera. Napisz fragment programu ustawiający 
właściwą wartość BLAD. 
 
 
7. Rozpoznaj funkcję poniższego programu i opisz sens każdej linii kodu:  
;SUBROUTINE TOINT  
TOINT:  
CLR C  
JZ toend  
MOV R4,#00H  
toi1:  
RRC A  
INC R4  
JNC toi1  
MOV A,R4  
toend:  
RET 
 
;SUBROUTINE TOINT  
TOINT:  
CLR C - zerowanie znacznika przeniesienia C  

background image

JZ toend - spr wartosc akumulatora, jeśli =0 to do PC jest dodawane przesunięcie toend ??  
MOV R4,#00H – zerowany jest rejestr R4  
toi1:  
RRC A - zawartosc a przesuwana w prawo o 1 bit z uwzględnieniem C  
INC R4 – dodajemy 1 do wartosci w R4  
JNC toi1 – spr jest bit przeniesienia C jesli =0 to do rejestru PC dodajemy ?  
MOV A,R4 - R4 wpisujemy do akumulatora  
toend:  
RET – adres powrotu z podprogramu wpisywany do licznika PC 
 
 
8. Napisz podprogram, który wywołany zastaje w akumulatorze liczbę całkowitą z zakresu 0-7,  
a w wyniku zmienia ACC tak że ma on ustawiony jeden bit na pozycji odpowiadającej tej liczbie  
całkowitej. 
 
CJNE A,#00, JEDEN  
MOV A, #0000 0001B  
SJMP KONIEC  
JEDEN:  
CJNE A,#01,DWA  
MOV A,#0000 0010B  
SJMP KONIEC  
DWA  
…  
KONIEC:  
NOP  
END