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 $
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
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.
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
N
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
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
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
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
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