Top wwwj
APARATURA KONTROLNO POMIAROWA: mierniki parametrów instalacji elektrycznych, jakośd energii elektrycznej, badań środowiskowycn, testery maszyn urządzeń 11
ELEMENTY I SYSTEMY AUTOMATYKI: regjlatory i czujniki temperatur/
SERWIS I KALIBRACJA APARATURY, NARZĘDZIA I AKCESORIA DLA ELEKTRYKÓW I ELEKTRONIKÓW
•tałtfcl wedNryeh tUbu^ nł» pnradnlą powafcr/ch MfMw-. jOifcgytdwJ«pwntfd~| Pij—wUatnła udeptu |
Idea rozwiązania Kolejka komunikatów
Kolejka komunikatów umożliwia przekazywanie informacji pomiędzy różnymi fragmentami programu. To rodzaj pamięci FIFO, w której możemy umieścić informację o wystąpieniu jakiegoś zdarzeń a. W naszym przypadku wykorzystamy ją do odciążenia przerwań zadaniem przerwuniu będzie wpisanie komunikatu o wystąpieniu zdarzenia, jego obsługa zostanie przejęta przez pętlę główną. Zastosowanie kolejkowania wiadomości sprawia, że nawet leśli program jest chwilowo zajęty obliczeniami, zdarzenie nie zostanie przeoczone. Przypomina to trochę sytuację, gdy obc ążony komputer reaguje z opóźnieniem.
Do kolejki wrzucamy wszystkie komunikaty, jakie mogą nam się przydać. Pętla główna będzie oo prostu ignorować te, których nie potrzebuje.
Realizując kolejkę komunikatów, musimy pamiętać o tym, że jest to element, do którego wpisujemy dane w funkcjach obsługi przerwaniu, u odczytujemy w pętli głównej. Stosowanie „typowo szkolnego" rozwiązania programo
wej oamięci FIFO może wywołać błędy w działaniu programu - problem ilustruje rysunek A. Moment krytyczny może wystąpić także w chwili przesuwania wskaźnika, jednak dla uproszczenia zakładamy, ze przerwania mogą jedynie zapisywać do kole ki. a pętla główna może z niej tylko czytać.
.OMfrtii MnMnitolUiniui. -
Problem można rozwiązać, wyłączając przerwania na krótką chwilę oznaczoną jako moment krytyczny, można też podejść inaczej du kunsliukiji pamięci FIFO. Dlaczego stosujemy licznik danych? Przecież aktualną tlość danych w pamięci można wyliczyć na podstawie aktualnej pozycji zapisu i odczytu. Jest z tym tylko jeden problem: jeśli wskaźnik te pokrywają się, nie wiemy, czy marny du czynienia /. pamięcią całkowicie pustą, czy całkowicie zapełnioną. Wyeliminujmy ten problem, uniemożiiwiąjąc zapis ostatniej komórki. Zmarnujemy w ten sposób _eden
--- _ jMUwwfniałaaarttjaal
9 \ ragywtrtctd-pranwrt
bajt. Jednak /. drugiej struny oszczędzimy bajt przeznaczony poprzednio na licznik. Jeśli uwzględnimy, że dodatkowo uprościmy algorytm - rozwiązanie stąje się ciekawe. Rozwiązanie oraz jego zalety przedstawia rysunek U. Warto wspomnieć, źc w praktyce nic będziemy obliczać ilości miejsca w kolejce - interesuje nas jedynie, czy miejsce jest czy go nic ma Ważna uwaga
Nasza pamięć będzie działała prawidłowo tak długo, jak wskaźniki będą zmiennymi ośmiobitowymi. Muszą być zapisane prawidłowo jedną instrukcją asemblera. Zapisywanie oddzielnie każdego bajtu większej liczby, jeśli zostanie przerwane może prowadzić do Węd negu wniosku, czy w pamięci jest. czy nic ma miejsca. W tukim przypadku przerwania i lak powinny być hlnkowana w krytycznym momencie.
się miejsce, gdzie aktualnie zmieścimy resztę naszej funkcji mam listing 109.
Ponieważ sukcesywnie przenieśliśmy fragmenty kodu pliku matn.c, aktualnie może on być bardzo prosty, a jego pełną zawartość można zobaczyć na listingu 110.
W tej chwili nie zrobiliśmy nic wielkiego - poprzenosiliśmy jedynie fragmenty gotowego już programu w nne miejsca. Program powinien zachowywać się identycznie jak do tej pory.
Jeśli przeniosłeś do modułu systemu funkcję sw wait, skasuj ją przed dalszą pracą.
l isting 110- plik inoin.c
#inc'ude <inttypes.h>
#include „system.h“
int main (voi d)
{
systemrur();
return C;
}
Kolejka komunikatów
Obsługą kolejki komunikatów zajmie się w naszym przypadku moduł systemu do niego też dodamy niezbędne zmienne oraz funkcje.
Listingi od 111 do 113 przedstawiają kolejne etapy obsługi kolejki komunikatów. Zwracam uwagę na listing 112. Przyjęto tutaj zasadę, że indeks zapisu wskazuje na aktual
nie wolne miejsce i jest zwiększany po dokonaniu wpisu. Indeks odczytu wskazuje na miejsce, gdzie aktualnie znajduje się komunikat i także jest zwiększany dopiero po odczycie.
Funkcja systemmsgPut jest nieco bardziej rozbudowana ze względu na testowanie przed zapisem, czy po przesunięciu indeksu zapisu nie pokryje się on z indeksem odczytu.
Funkcje systemu obsługujące kolejkę deklarujemy w pliku nagłówkowym zgodnie z listingiem 114.
Aktualnie jedyne, co będziemy przesyłać za pomocą komunikatów, będą informacje o stanie klawiatury. W pliku system.h, zgodnie z listingiem 115, stwórzmy stałe oznaczające odpowiednie zdarzenia. Zauważ dwie rzeczy:
Listing 111- dane kolejki
VOid system_run(void) _attribute_((_noreturn_))J
Listing 112 - obsługa pamięci FIFO kolejki
VOid 3ystem_msgClear(void)
memsel(&s.ystem_msg, 0, SIzeof(sy::tem maa)) ;
1
uint8_t in — (system_msg.indoxIn + i) %
ELEMG (3y3tem_rti3ę • qu3ne) J
if(in 1= systeiu msg.indexGut)
systen\_msg.quene[systernjnsg.indexln] - msg; system -nsg.indexln = in; return 0;
1
return 1;
// Funkcja pobiera wiadomość z kolejki.
uint8 t system_nsgGet(VOid)
if(systern_nsg.indexlr = systeir_msg>ir.dex0uO return 0;
uint8_t resg — system_msg.quenG [system msg. indexOut.] ; systeawrtsg. indexOut - (3ystem_rr3g, indcxOut + 1) % SLEMSCaystemjnsy . guejic) \
Listing 113 - oczekiwanie na komunikat
uint8_t 3y3tcra_mcgWaitFor(void)
uint8 t msg;
while(0 = (msg ■ systerajnsguet ())) {}; return msg;
Elektronika dla Wszystkich Sierpień2006 41