Mikrokontrolery AVR XMEGA w praktyce, część 6. Przerwania

W procesorach ATmega kontroler przerwań był tak prosty, że prostszy już być nie może. Można go było włączyć lub wyłączyć. W XMEGA kontroler przerwań został znacznie rozbudowany i traktowany jest jako pełnoprawny układ peryferyjny o nazwie PMIC, czyli Programmable Multilevel Interrupt Controller.

Największym plusem PMIC jest to, że mamy do dyspozycji trzy priorytety przerwań – niski, średni i wysoki. Oznacza to, że procedura obsługi przerwania o niskim priorytecie może być przerwana przez przerwanie o priorytecie średnim lub wysokim. Przerwanie o priorytecie wysokim nie może być przerwane wcale (wyjątek: wykrycie nieprawidłowego sygnału taktującego). Dzięki temu możemy ustalić jakie zadania są dla nas najważniejsze, by procesor mógł na nie reagować jak najszybciej, a mniej ważne zadania zostawił do dokończenia na później. Jest też dostępny scheduler round-robin, by mieć kontrolę nad kolejnością wykonywanych przerwań o tym samym priorytecie, w razie natłoku zgłoszeń. Jest to konieczne, gdyż w procesorach XMEGA mamy bardzo wiele różnych przerwań do dyspozycji – w ATxmega128A3U, zamontowanym na płytce X3-DIL64 z Leon Instruments, jest ponad 100 wektorów przerwań!

Przerwania dzielą się na maskowalne i niemaskowane. Niemaskowalne jest zaledwie jedno – wykrycie nieprawidłowego działania generatora sygnału zegarowego. Przerwania maskowalne mogą generować wszystkie układy peryferyjne i podobnie jak w ATmega, musimy je odblokować, aby móc je wykorzystać. Kolejnym podobieństwem jest konieczność użycia makra sei(), aby uruchomić system przerwań.

W tej części kursu zrobimy prosty program, demonstrujący działanie przerwań o różnych priorytetach. Poznamy również jak skonfigurować przerwania INT od portów, omawianych w poprzedniej części kursu. W pętli głównej procesor będzie zajmował się wyłącznie mruganiem diodą, podłączoną do pinu B0. Przerwania będą wywoływane przyciskami na pinach E5 i E6, a procedury tych przerwań będą powodowały mruganie diodami, odpowiednio, podłączonymi do pinów C1 i C0.

Oprócz mrugania diodami, wykorzystamy również popularny wyświetlacz tekstowy 16×2 ze sterownikiem HD44780. Nie będę tu omawiał jego obsługi i wykorzystamy gotową bibliotekę, którą znajdziesz na płycie dołączonej do EP (zostało to omówione w części 5 kursu). Biblioteka jest autorstwa Radosława Kwietna (radzio.dxp.pl) i przystosowałem ją do wykorzystania w mikrokontrolerach XMEGA.

Schemat układu wykorzystywanego w tej części kursu przedstawiono na rysunku 1, a zdjęcie układu zbudowanego na płytce stykowej przedstawia rysunek 2.

 

Rys. 1. Schemat układu demonstrującego działanie przerwań

Rys. 1. Schemat układu demonstrującego działanie przerwań

 

Rys. 2. Zdjęcie układu zmontowanego na płytce stykowej

Rys. 2. Zdjęcie układu zmontowanego na płytce stykowej

 

Program zaczynamy, jak zwykle, od konfiguracji portów. W tym fragmencie kodu jedyna nowość to PORT_ISC_FALLING_gc wpisane do rejestrów PORTxCTRL. W ten sposób decydujemy, jakie konkretnie zdarzenie ma wywoływać przerwanie. FALLING oznacza zbocze opadające, a możliwe są jeszcze opcje: RISING (zbocze rosnące), BOTHEDGES (zbocze rosnące lub opadające) oraz LEVEL, czyli stan logicznego zera.

Każdy port w XMEGA może generować przerwanie INT0 i INT1, jednak to my sami możemy wybrać, który pin jakie przerwanie ma wywoływać. Mało tego, nawet kilka pinów może wywoływać tę samą procedurę przerwania! Nic nie stoi na przeszkodzie, by jeden pin wywoływał zarówno INT0 i INT1, choć takie rozwiązanie raczej nie ma sensu praktycznego.

Na przykładzie poniższego kodu widać, jak przypisać piny do poszczególnych przerwań. Następnie, w rejestrze INTCTRL musimy ustalić priorytety przerwań INT0 i INT1 – dostępne opcje to LO, MED, HI albo można przerwanie wyłączyć wpisując PORT_INTxLVL_OFF_gc.

Przejdźmy teraz do skonfigurowania kontrolera przerwać PMIC. Musimy w jego rejestrze CTRL odblokować przerwania o priorytecie HI oraz LO. Na koniec, należy wpisać instrukcję sei(), dobrze znaną z ATmega i ATtiny, aby procesor mógł obsługiwać przerwania.

Pętla główna naszego programu jest trywialnie prosta.

Zobaczmy, jak należy napisać procedurę obsługi przerwania.

Każdy port może generować przerwanie INT0 i INT1 – stąd nazwa przerwania PORTE_INT0_vect. Procedura zawiera pętlę, dzięki której dioda na pinie C0 mrugnie dziesięciokrotnie. Procedura przerwania INT1 jest bardzo podobna.

Zobaczmy więc, jak to działa w praktyce, wykorzystując płytkę rozwojową X3-DIL64 z Leon Instruments, którą można kupić w KAMAMI. Po wgraniu programu mruga dioda podłączona do B0. Naciśnięcie przycisków wywołuje odpowiadające im procedury przerwań. Co się stanie, jeśli wciśniemy przycisk E6, wywołujący przerwanie o priorytecie niskim, a chwilę potem E5, który wywoła przerwanie o wyższym priorytecie? Dioda C1 przestanie mrugać, a dioda na C0 zacznie. Kiedy C0 skończy migać, procesor wróci do mrugania diodą C1.

Należy wyraźnie zaznaczyć, że procedury przerwań powinny być wykonywane jak najszybciej i nie powinno być w nich żadnych funkcji opóźniających. W tym artykule została zastosowana funkcja _delay_ms(), aby móc zobaczyć działanie przerwań i ich priorytetów. Pamiętaj, że w normalnym programie stosowanie opóźnień w przerwaniach jest wysoce niewskazane.

Kompletny program

Dystrybutorem zestawu X3-DIL64 jest KAMAMI.pl.

Dominik Leon Bieczyński

http://leon-instruments.blogspot.com

Do pobrania

O autorze