Mikroprocesorowa ośla łączka, część 29
Istotnym elementem w oprogramowaniu jest obsługa przerwań. Ta operacja w języku programowania C jest prosta i realizuje się wręcz naturalnie. Trochę gorzej to wygląda przy tworzeniu programu w języku C++ (pomijając oczywiście rozwiązanie zaczerpnięte z języka C, gdyż język C jest podzbiorem C++).
Obsługa przerwania w jakichkolwiek mikroprocesorach ma pewną specyfikę: zawsze jest uruchamiana w sposób sprzętowy (zaistnienie potrzeby obsługi przerwania prowadzi do wywołania odpowiedniej funkcji, która nie pochodzi z kodu programu). Występuje tu kilka możliwych wariantów uzależnionych od wyposażenia sprzętowego. Niektóre mikroprocesory są wyposażone w tryb wektorowy, odpowiedni kontroler obsługi przerwań skieruje wykonanie programu w docelowe miejsce w przestrzeni pamięci zawierającej kod programu (mówiąc w uproszczeniu, wykona wywołanie dedykowanej funkcji do obsługi). W takim przypadku na początku programu koniecznością jest odpowiednie zaprogramowanie kontrolera przerwań przede wszystkim w zakresie podania adresów funkcji do obsługi przerwań. Taka funkcja może znajdować się w dowolnym miejscu przestrzeni programu, więc kontroler przerwań musi wcześniej „wiedzieć” gdzie one się znajdują. Innym wariantem jest przydzielenie każdej funkcji obsługi przerwania stałego miejsca w przestrzeni adresowej i taki wariant występuje w mikrokontrolerach AVR. W odpowiedniej dokumentacji można znaleźć szczegółowe informacje dotyczące lokacji funkcji obsługi przerwań w przestrzeni adresowej (rysunek 1 pokazuje taką tabelę dla mikrokontrolera ATMEGA328P, gdzie jest zaznaczone miejsce obsługi przerwania przetwornika analogowo-cyfrowego). Uruchomienie pomiaru wartości analogowej trwa ileś czasu, więc program musi poczekać aż ten pomiar zostanie zakończony. Możliwym rozwiązaniem jest odczyt rejestru statusowego związanego z przetwornikiem ADC i sprawdzenie odpowiedniego bitu, który zostanie ustawiony przez sam przetwornik w chwili zakończenia konwersji napięcia analogowego na wartość liczbową. Innym wariantem jest takie skonfigurowanie przetwornika, by po zakończeniu działania zgłosił przerwanie, w obsłudze którego można odczytać liczbę wynikającą z konwersji.
Obsługa każdego przerwania finalnie trafia do odpowiedniej funkcji w programie (czy to w wyniku wektoryzowanego adresu, czy stałej lokacji w przestrzeni adresowej) jako jej wywołanie bez podania parametrów (każda obsługa przerwania jest funkcją bezparametrową). W przypadku klasycznego języka C nie stanowi to problemu, wystarczy zgłosić odpowiednią funkcję do obsługi przerwania. Taka funkcja ma specyficzny nagłówek. W rzeczywistości używa się odpowiedniej konstrukcji utworzonej przez #define. W dotychczasowych przykładach było używane rozwiązanie z użyciem SIGNAL, jak pokazuje listing 1:
SIGNAL ( TIMER0_OVF_vect )
{
( . . . )
} /* TIMER0_OVF_vect */
W nawiasach umieszczana jest informacja identyfikująca przerwanie, również utworzona przez #define (aby kompilator wraz z linkerem poprawnie skojarzył funkcję obsługi z odpowiednim przerwaniem). Podobnie w przypadku programów w języku C++ tworzone są funkcje obsługi przerwania, z tym, że do jej konstrukcji zamiast wyrażenia SIGNAL używa się ISR (ang. Interrupt Service Routine – procedura obsługi przerwania), wystarczy zamienić słowo SIGNAL na ISR. Konstrukcja z użyciem SIGNAL obecnie jest uważana za przestarzałą (ale poprawną). Pod kątem technicznym oba makra generują funkcję obsługi przerwania, która domyślnie blokuje wykonywanie innych przerwań podczas swojego działania (nie ma obsługi przerwań zagnieżdżonych). Nowoczesność ISR w stosunku do SIGNAL polega na tym, że istnieje możliwość specyfikowania dodatkowych informacji pozwalających przykładowo na obsługę przerwań zagnieżdżonych jak również powiązanie dwóch różnych przerwań z tą samą funkcją obsługi (to są już bardziej zaawansowane rozwiązania, wykraczające poza zakres tego cyklu artykułów). Typowym elementem w programach w języku C++ jest korzystanie z obiektów i klas. Ich składnikami są między innymi metody (jako funkcje działające na danych zawartych w obiektach). Specyfiką metod jest istnienie jednego ukrytego parametru wywołania (identyfikowanego słowem kluczowym this). Nawet bezparametrowa funkcja będąca elementem klasy ma jeden niejawny parametr. Z tego względu standardowa metoda będąca składnikiem klasy nie może być zgłoszona do obsługi przerwania. Ten wymóg nie eliminuje możliwości wykorzystania klas i obiektów do obsługi przerwań, gdyż można z funkcji obsługi przerwania (napisanej w konwencji języka C) użyć wywołania odpowiedniej metody z obiektu.
(…)
——– ciach! ——–
To jest tylko fragment artykułu, którego pełna wersja ukazała się w październikowym numerze czasopisma Zrozumieć Elektronikę (ZE 10/2026). Pełną wersję czasopisma znajdziesz pod tym linkiem. Natomiast niepełna, okrojona wersja, pozwalająca zapoznać się z zawartością numeru ZE 10/2026 znajduje się tutaj.
Andrzej Pawluczuk
apawluczuk@vp.pl
Uwaga! Wskazówki, jak nabyć pełne wersje dowolnych numerów ZE znajdują się na stronie:
https://piotr-gorecki.pl/n11.
