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 :)