tm termin 1 wersja by stru 896


Zad 1
mamy 2 funkcje obsługi przerwań: recv() i disp(). Pierwsza wywoływana w chwili skończenia
odbierania pakietu, druga w chwili skończenia jego przetwarzania. Mamy napisać je w ten sposób
żeby wyłączyć obsługę przerwań jeśli odebrano i nie przetworzono więcej niż 16 pakietów. Oraz
mamy ustawiać flagę  zero za każdym razem jak odebrano nieparzysty pakiet (jeśli przerwanie nie
jest zamaskowane).
a)
idea jest taka, że tworzymy zmienną zliczającą nasze pakiety odebrane i nie przetworzone. Powinna
ona być inkrementowana za każdym razem jak pakiet odbierzemy, a dekrementowana jeśli go
przetworzyliśmy. Następnie trzeba tylko wstawić warunek sprawdzający czy licznik przekroczył
wartość 16 a w nim ustawienie flagi rejestru maskującą przerwania. Z tego co pamiętam był to 7 bit
(od zera licząc, flaga  IRQ disable ) 0x80.
Int liczba_pakietow = 0;
void recv()
{
liczba_pakietow = liczba_pakietow + 1;
if(liczba_pakietow > 16)
{
CMSR = CMSR | 0x80; // ustawia 7 bit
}
}
void disp()
{
liczba_pakietow = liczba_pakietow  1;
}
i tyle :D
b)
tutaj potrzebujemy zmiennej zliczającej wszystkie pakiety odebrane. Potem, jeśli nie zamaskowano
w międzyczasie przerwania, sprawdzamy czy jest to pakiet nieparzysty, i jeśli jest ustawiamy flagę
zero (bit 30. CMSR) a jeśli jest parzysty to ją
zerujemy.
Int liczba_pakietow = 0;
int wszystkie = 0;
void recv()
{
wszystkie = wszystkie + 1;
liczba_pakietow = liczba_pakietow + 1;
if(liczba_pakietow > 16)
{
CMSR = CMSR | 0x80; // ustawia 7 bit
} else if(wszystkie % 2 == 1)
{
CMSR = CMSR | (1<<30);
} else {
CMSR = CMSR & (~(1<<30));
}
}
void disp()
{
liczba_pakietow = liczba_pakietow  1;
}
krótki komentarz dla tych co operacji logicznych w C nie pamiętają:
 zmienna = zmienna | (1< ustawienie x-tego bitu zmiennej
 zmienna = zmienna & (~(1< zerowanie x-tego bitu zmiennej
warunek Liczba % 2 == 1 sprawdza czy liczba jest nie parzysta jak by ktoś nie wiedział to to jest
dzielenie modulo ;)
Zad 2.
Mamy dany mniej więcej taki kod asemblera, z wartościami rejestrów po każdej instrukcji:
mov ax, 0x1AF4 ; ax = 0x1AF4, bx = ???, cx = ???
mov bx, 8 ; ax = 0x1AF4, bx = 8, cx = ???
xor cx ; ax = 0x1AF4, bx = 8, cx = 0
push bx
push ax
push cx
add ax, 0xFF ; ax = 0x1BF5, bx = 8, cx = 0
or cx, 0x10 ; ax = 0x1BF5, bx = 8, cx = 0x10
mul ax, cx ; ax = 0xBF50, bx = 8, cx = 0x10
add cx, bx ; ax = 0xBF50, bx = 8, cx = 0x10
pop bx
pop ax
pop cx
and ax, 0 ; ax = 0, bx = 0, cx = 8
co najmniej jednej instrukcji nie pamiętam bo było 9 z uzupełnieniem wartości rejestrów, chyba że
na push/pop było.
Stos po 8 instrukcji:
???
->SP 0
0x1AF4
8
???
???
???
??? = wartość niezdefiniowana.
Zad 3
baudrate = 19200
data = 8
2 bity stopu
kontrola parzystości ODD
prędkość transmisji w bajtach na sekundę : prawdopodobnie 200 :p
bo: (baudrate/wielkosc_ramki)/8
wielkość ramki to 12 bitów : bit startu, 8 bitów danych, bit parzystości, 2 bity stopu (tak chyba
miała być narysowana ta ramka)
czyli 19200/12 = 1600, a że wynik w bajtach ma być to jeszcze 1600/8 = 200 B/s
mamy rejestr SSR którego 7 bit oznacza gotowość wysłania danych, i rejestr bufora nadajnika TDR.
Programik ma wysyłać 8 bajtów z tablicy buf[] oraz liczyć ich sumę kontrolną i potem ją też
wysłać.
Void fun()
{
for(int i = 0; i < 8; i++)
{
while(!(SSR&0x80));
TDR = buf[i];
}
for(int i = 0; i < 8; i++)
{
suma = suma + buf[i];
}
suma = ~suma + 1;
TDR = suma;
}
to prawdopodobnie jest trochę naciągana wersja ale powinno być za to sporo punktów :D
Zad 4.
łączymy to tak:
generator->wejscie CLK pierwszego timera
wyjście pierwszego timera -> wejście CLK drugiego
i na wyjściu drugiego mamy mieć 8Hz przy generatorze 5.242880 MHz
timery pracują jako zliczacze więc sygnał na wyjścia generowany jest po przepełnieniu rejestru
OCR , który jest dekrementowany z każdym taktem wejścia CLK. Z tego wynika, że potrzebujemy
zliczyć do 5242880/8 = N taktów
N = 655360, jest większe niż 2^16=65536 stąd to połączenie w kaskadę.
Czyli reasumując nasz pierwszy timer liczy do swojego maksimum czyli 65536 i na jego wyjściu
jest 80 Hz, które biegnie jako taktowarka do drugiego licznika, który musi zliczyć do 10 żeby na
jego wyjściu było 8 Hz. Innymi słowy te timery pracują jak dzielniki częstotliwości podanej na
CLK gdzie dzielnik = OCR
odp :
OCR1 = 65536 OCR2 = 10
teraz jeśli wiemy że timer 2 pracuje z częstotliwością 8 Hz, i że za każdym jego taktem
wywoływana jest procedura obsługi przerwania timer2() to żeby wywołać funkcję KeyCheck() co
125 ms, wystarczy jej wywołanie tam wpisać, bo 1/8 = 0.125 = 125ms. Co do LCDUpdate()
wywoływanej co 500 ms, trzeba ją wywoływać w co czwartym takcie więc:
int cnt = 0;
void timer2()
{
KeyCheck();
if(cnt % 4 == 0)
{
LCDUpdate();
}
cnt = cnt + 1;
}
funkcja obsługi pierwszego przerwania nic nie musi robić :)
i to by było na tyle :D
Jeśli ktoś uważa że coś z tego jest zle, to proszę mi nie psuć mi humoru przed końcem łikendu. A
tak serio to zgłaszać wszelkie nieścisłości :)


Wyszukiwarka