Rys. 22 Badanie liczby cykli obsługi przerwania
że dokładnie co taki czas zmienna g_Akt Wyświetlacz jest zerowana. Już teraz zapewne domyślasz się, że te kilkadziesiąt cykli nic jest dużą wartością dla procesora. Aby się o tym upewnić, policzmy co ile cykli pojawia się przerwanie. 256 zliczeń licznika, który zlicza co ósmy takt zegara systemowego - 2048 cykli. Nic potrzeba już więcej obliczeń.
W tej chwili było to tylko ćwiczenie, jednak pozwoliło na zaznajomienie się z rzeczywistym problemem. Warto wiedzieć, jak sprawdzić czas wykonywania przerwania, zwłaszcza że w rzeczywistym, rozbudowanym programie może pojawić się konieczność jego optymalizacji. Jeżeli jednak nic chcemy przyspieszać wywoływania przerwania wyświetlacza aż 8 razy, istnieje inna możliwość. Możemy przywrócić poprzednią wartość preskalera licznika, a w obsłudze przerwania na jego przepełnienie wpisywać do niego jakąś wartość początkową. W tym celu wystarczy, jeszcze przed wygaszeniem wyświetlaczy, dopisać linię:
TCNTO = 128;
Wartość 128, odpowiadająca połowie zakresu zliczania, spowoduje dwukrotne zwiększenie częstotliwości wywoływania przerwania.
Jakkolwiek postanowimy rozwiązać problem niskiej częstotliwości przemiatania wyświetlacza i czy w ogóle postanowimy go rozwiązywać, poznając oraz wykorzystując przerwania dokonaliśmy wielkiego skoku jakościowego — teraz, w wątku głównym, możemy zapomnieć o przełączaniu wyświetlaczy, poświęcając uzyskane miejsce na inne działania. Z tego punktu widzenia wyświetlacz stał się tablicą czterech zmiennych dokładnie odwzorowujących wygląd wyświetlanych znaków.
Do tej pory milcząco zakładałem, że używana w programie instrukcja if jest w pełni zrozumiała. Wydaje mi się, że tak jest w istocie -została tutaj wykorzystana jej najprostsza składnia, a działania można domyślić się z kontekstu. Dla porządku i aby rozwiać wszystkie wątpliwości, na tej i następnej stronie przedstawiam dwie ramki. Zwróć szczególną uwagę na ramkę „Warunki”. Z zawartych tam informacji będziemy jeszcze wielokrotnie korzystać.
Na koniec poprzedniej części wspomniałem o tym, żc zmienna zawierająca informacje aktywacji poszczególnych wyświetlaczy -g_DaneComm, marnuje nasze zasoby — niepotrzebnie zajmuje cenną pamięć danych, której mamy tylko 128B. Jednocześnie jej kopia jest przechowywana w pamięci programu w celu inicjacji wartości... których tak naprawdę nigdy nie chcemy zmieniać. Ze zmiennej tylko czytamy. Bardziej optymalnym rozwiązaniem w tym przypadku wydaje się bezpośrednie czytanie danych z pamięci programu.
W tym miejscu zwraca się przeciw nam architektura procesorów AVR. Mimo iż producent zapewnia w swoich materiałach, żc procesor ten był opracowywany pod kątem wykorzystania języków wysokiego poziomu, takich jak C, okazuje się, że specyfikacja ANSI C została stworzona dla procesorów niewyróżniąjących pamięci danych i programu. W takim przypadku rozróżnienie, do której pamięci chcemy się odwołać, powinno następować za pomocą, tylko i wyłącznie, różnych adresów. W naszym procesorze niestety oba wymienione rodzaje pamięci pod względem adresów' nachodzą na siebie (pierwsze 224 adresy odnoszą się do pamięci danych, przestrzeni wejścia wyjścia oraz rejestrów... jednak jednocześnie adresy tc są jak najbardziej właściwe dla pamięci programu!). Jedynym sposobem odróżnienia obu pamięci są różne instrukcje dostępu.
Producenci kompilatorów w różny sposób rozwiązują przedstawiony problem. W GCC postanowiono utworzyć oddzielne instrukcje umożliwiające dostęp do pamięci programu. Warto o tym pamiętać — sam wielokrotnie wpadałem w pułapkę, gdy chciałem wykorzystać zmienną umieszczoną w pamięci programu tak samo, jakby była ona umieszczona w pamięci danych.
Dużo informacji o wykorzystaniu pamięci programu znajdziesz w kolejnej ramce ABC... C. Gdy tylko przejrzysz zaw'arte tam informacje, możemy rozpocząć dalszą modyfikację naszego, coraz doskonalszego, programu.
Może już zauważyłeś, że w ramkach napisałem, co musimy zmienić w naszym kodzie. Teraz, tylko dla porządku, zbiorę te informację w jednym miejscu. Umieść więc kursor zaraz na końcu sekwencji dyrektyw itinclude. Dodaj potrzebny nam nagłówek za pomocą komendy łiinclude <avr\pgmspace!h>. Od tej chwili możemy korzystać z pamięci programu w sposób opisany w ramkach. Następnie
ABC... C
Instrukcja warunkowa if
Instrukcja if występuje praktycznie w każdym języku programowania. W C jej działanie nie odbiega od ogólnie przyjętej normy. Jej składnia jest następująca:
if(warunek)
instrukcja [else instrukcja]
Jeśli warunek jest spełniony, wykonywana jest instrukcja znajdująca się zaraz za komendą if. Jeśli nie, to albo wykonyw-ana jest instrukcja znajdująca się za komendą else, albo - w przypadku jej braku — program przechodzi do dalszego działania.
Pamiętaj, że w obu przypadkach, jeśli występuje instrukcja prosta, musi kończyć się ona znakiem średnika. Za pomocą klamer można wprowadzić także instrukcje złożone.
40 Lipiec2005 Elektronika dla Wszystkich