Musimy dokładnie zrozumieć różnicę między przerwaniem, a zdarzeniem. Jest to niezbędne każdemu, kto kiedykolwiek będzie zajmował się programowaniem mikrokontrolerów.
Zdarzenie a przerwanie
Po zgłoszeniu przerwania, procesor przerywa dotychczas wykonywane operacje, przechodzi do procedury obsługi przerwania, po czym wraca do dotychczas wykonywanego programu. Zdarzenie może zostać zrealizowane bez jakiejkolwiek reakcji ze strony rdzenia procesora. Służy do tego, aby jeden układ peryferyjny mógł sterować innym układem. Przykładem zdarzenia może być przepełnienie timera, które inicjuje pomiar przetwornikiem analogowo-cyfrowym. Innym zdarzeniem może być zmiana stanu komparatora analogowego, która jest rejestrowana przez timer.
Zdarzenie może wygenerować układ zwany nadajnikiem. Można zdarzenie generować również programowo. Do każdego nadajnika możemy podłączyć jeden lub kilka odbiorników. Większość peryferiów dostępnych w XMEGA może być zarówno nadajnikami i odbiornikami. Nic nie stoi na przeszkodzie, by odbiornik jednego zdarzenia był nadajnikiem kolejnego. W ten sposób można łączyć timery w łańcuszek i można stworzyć timer 64-bitowy lub jeszcze dłuższy. Przykład nadajnika i odbiornika przedstawiono na rysunku 1.
Ważną zaletą zdarzenia nad przerwaniem jest duża szybkość reakcji. Wystarczą zaledwie dwa cykle zegarowe od wygenerowania zdarzenia do jego realizacji przez odbiornik. W przypadku przerwania - samo wejście do procedury zajmuje dużo więcej czasu. Zdarzenia mają w 100% przewidywalny czas realizacji i jak już wspomniano, nie angażują procesora, więc może zajmować się innymi zadaniami. Mało tego, rdzeń procesora można nawet wyłączyć, wprowadzając go w stan uśpienia! W związku z tym zastosowanie systemu zdarzeń może radykalnie zmniejszyć zużycie energii.
Nadajniki i odbiorniki połączone są ze sobą przy pomocy sieci połączeń (rounting network) przedstawionej na rysunku 2. W przypadku mikrokontrolera ATxmega128A3U składa się ona z ośmiu kanałów, które doprowadzone są do wszystkich peryferiów, mogących funkcjonować jako odbiorniki zdarzeń. Na "początku" każdego kanału jest multiplekser, czyli elektroniczny przełącznik, którym można ustawić, jaki układ peryferyjny ma być nadajnikiem zdarzenia. W ten sposób możemy budować sieć połączeń według własnych potrzeb (jeszcze trochę i będzie jak w FPGA...). Choć może wydawać się to bardzo skomplikowane, w praktyce wykorzystanie systemu zdarzeń jest trywialnie proste.
System zdarzeń nie jest wyłącznie biernym pośrednikiem i siecią połączeń. Umożliwia także kilka ciekawych funkcji, takich jak filtr cyfrowy oraz dekoder kwadraturowy. Filtr umożliwia likwidację szumów, co przydatne jest w sytuacji, gdy nadajnikiem zdarzenia jest pin procesora połączony np. z przyciskiem. Dekoder kwadraturowy umożliwia bardzo proste podłączanie enkoderów obrotowych, takich jak w pokrętłach oscyloskopów. Dzięki całkowicie sprzętowej obsłudze, zastosowanie enkodera w programie staje się równie proste jak podłączenie klawiatury.
Proste zdarzenia
Na początek sprawa bardzo prosta - zwyczajne zliczanie impulsów. Zdarzenie będzie generował pin E5, czyli ten, który jest połączony z przyciskiem FLIP na płytce X3- -DIL64. Odbiornikiem zdarzenia będzie timer C0, który będzie zwiększał swoją wartość o 1 przy każdym wciśnięciu przycisku. Schemat układu do zbudowania na płytce stykowej przedstawiono na rysunku 3. Przejdźmy od razu do pisania programu!
Zaczynamy, jak to zwykle, od skonfigurowania pinów. Zdarzenie ma generować pin E5, dlatego musimy go skonfigurować jako wejście oraz uaktywnić rezystor podciągający do zasilania. Czytelnicy pamiętający artykuł o przerwaniach w Xmega (EP 12/2013) zapewne zwrócą uwagę, że poniższy kod niczym nie różni się, od tego, który uaktywnia przerwania. W rzeczy samej! Parametr PORT_ISC_FALLING_gc wpisany do rejestru PINxCTRL konfiguruje, co ma wywoływać przerwania, jak i również zdarzenia.
Pamiętajmy, że żeby uaktywnić przerwanie, trzeba było jeszcze skonfigurować kontroler przerwań PMIC oraz odblokować przerwania, które chcemy używać, a na końcu trzeba jeszcze wykonać instrukcję sei(). Jednak my tego nie zrobimy. Mamy przecież zająć się systemem zdarzeń.
Wykorzystajmy kanał 0 systemu zdarzeń. W procesorze ATxmega128A3U, dostępne jest osiem kanałów zdarzeń i moglibyśmy użyć dowolnego z nich. Musimy wskazać, jaki układ ma być nadajnikiem zdarzenia i wpisać go do rejestru EVSYS.CH0MUX. Rzućmy okiem na dokumentację, której fragment przedstawiono na rysunku 4.
Jak widać, wybór jest bardzo szeroki i bardzo pomocne są podpowiedzi, generowane automatycznie przez Atmel Studio podczas wpisywania tekstu. Aby zdarzenie generował pin E5, musimy do rejestru CH0MUX wpisać wartość EVSYS_CHMUX_PORTE_PIN5_gc.
Ponieważ przycisk jest elementem mechanicznym, generującym chaotyczne wielokrotne impulsy podczas przyciskania, dobrym pomysłem będzie zastosowanie filtru cyfrowego. W przeciwnym razie, procesor mógłby pojedyncze wciśnięcie zinterpretować jako kilka, kilkanaście, lub nawet kilkadziesiąt wciśnięć. Filtr cyfrowy powoduje ignorowanie impulsów trwających krócej niż wyznaczoną liczbę cykli zegara systemowego. Maksymalna wartość, jaką możemy wybrać to 8 cykli zegarowych - prawdę mówiąc, nie jest to ilość wystarczająca do całkowitego wyeliminowania problemu, ale choć trochę go zmniejszymy. Aby uruchomić filtr cyfrowy, do rejestru CH0CTRL musimy wpisać wartość EVSYS_ DIGFILT_8SAMPLES_gc.
To wszystko, jeśli chodzi o nadajnik. Przejdźmy teraz do konfiguracji odbiornika zdarzenia, czyli timera C0. Timery w mikrokontrolerach XMEGA zostały dokładniej opisane w poprzedniej części kursu w EP 02/1024. Dotychczas w naszych ćwiczeniach, timer był zawsze taktowany sygnałem zegarowych podzielonym wstępnie przez preskaler, co konfigurowaliśmy w rejestrze CTRLA timera. Z punktu widzenia timera, system zdarzeń jest takim samym sygnałem taktującym jak sygnał zegarowy - impulsy przychodzące przez system zdarzeń mogą być traktowane przez niego jak sygnał zegarowy. Dlatego wybór kanału systemu zdarzeń dokonujemy również w rejestrze CTRLA. ...i to wszystko! Pozostaje tylko inicjalizacja wyświetlacza LCD (EP 12/2014) oraz procedura pętli głównej, cyklicznie wyświetlająca aktualną wartość rejestru CNT timera C0. Zwróć uwagę, że w pętli głównej nie ma jakiejkolwiek instrukcji związanej z pinem E5. Kod pierwszego programu demonstrującego możliwości systemu zdarzeń przedstawiono na listingu 1.
Enkoder obrotowy
Enkodery obrotowe, zwane również impulsatorami, służą do budowy przyjaznych interfejsów człowiek-komputer. Istnieje wiele parametrów, które łatwiej jest regulować kręcąc pokrętłem niż wpisując wartości liczbowe z klawiatury. W odbiornikach radiowych do regulacji głośności dawniej stosowano potencjometry, a współcześnie, w dobie techniki cyfrowej, stosuje się enkodery. Urządzenie, w którym znajdziemy kilka lub nawet kilkanaście enkoderów to oscyloskop. Mikrokontrolery XMEGA umożliwiają bardzo łatwe wykorzystanie enkoderów, dzięki systemowi zdarzeń i wbudowanemu dekoderowi kwadraturowemu. Schemat układu demonstracyjnego z enkoderem przedstawia rysunek 5, a jego przykład wykonania na płytce stykowej przedstawia fotografia 6.
Enkoder ma piny oznaczone literami A i B oraz masę. Jeśli enkoder ma możliwość wciskania, wówczas są jeszcze dwie dodatkowe nóżki. Piny A i B muszą być podciągnięte do zasilania rezystorami pull-up - na szczęście XMEGA jest wyposażona w takie i nie musimy dodawać osobnych. Wewnątrz niego znajdują się dwa styki, które są zwierane do masy w zależności od pozycji pokrętła. Obracając pokrętło uzyskamy przebiegi takie, jak na rysunku 7 - przesunięte o 90º w zależności od kierunku obrotu. Dzięki sprzętowemu dekoderowi, jaki znajduje się w mikrokontrolerach XMEGA, nie musimy wgłębiać się w szczegóły i wnikliwie badać tych przebiegów. Dekoder zrobi wszystko za nas, a pozycję pokrętła będziemy mogli łatwo i szybko odczytać, korzystając z rejestru CNT timera. Program przedstawiono na listingu 2. Na początku funkcji main(), musimy skonfigurować piny, które będzie wykorzystywał enkoder. Ustawiamy je jako wejścia i włączamy wewnętrzne rezystory pull-up. Ponieważ piny wykorzystywane przez enkoder znajdują się w obrębie jednego portu, do ich konfiguracji możemy wykorzystać rejestr PORTCFG.MPCMASK i zdefiniować w nim, jakie piny chcemy skonfigurować. Następnie, po wpisaniu odpowiednich wartości do rejestru PORTx.PINxCTRL (wskazującego, które konkretnie piny chcemy konfigurować w następnej instrukcji), ustawienia te zostaną skopiowane do rejestru kontrolnego każdego pinu wskazanego w MPCMASK. W ten sposób możemy szybko skonfigurować piny C1 i C0, które podłączymy do enkodera. Następnie, przechodzimy do konfiguracji systemu zdarzeń.
W rejestrze EVSYS.CH0MUX wskazujemy pierwszy z dwóch pinów, wykorzystywanych przez enkoder. Pamiętaj, że enkoder musi być podłączony do pinów sąsiadujących ze sobą!
Każdy kanał systemu zdarzeń ma swój rejestr kontrolny. Zobaczmy fragment dokumentacji tego rejestru na rysunku 8. Interesuje nas bit QDEN, uruchamiający dekoder kwadraturowy. Pozostałe opcje związane z dekoderem są związane z enkoderami z indeksowaniem. Przydatną rzeczą, jaką jeszcze możemy w tym rejestrze ustawić, to filtr cyfrowy. Filtr cyfrowy sprawia, że sygnał zostanie rozpoznan,y jeżeli będzie utrzymywał się na wejściu dłużej niż wybrana liczba cykli zegarowych. Ustawmy więc filtr na osiem cykli.
Dekoder kwadraturowy jest nadajnikiem zdarzenia, a odbiornikiem musi być timer, który będzie zliczał odebrane impulsy. Wykorzystajmy do tego celu timer C0. W rejestrze CTRLA, jak pamiętamy z odcinka o timerach w XMEGA, musimy w nim zdefiniować źródło sygnału taktującego. Jest nim oczywiście kanał 0 systemu zdarzeń. W rejestrze CTRLD musimy tak skonfigurować timer, by był w stanie poprawnie odbierać impulsy z dekodera. W szczególności jest to ważne, by timer wiedział kiedy ma zwiększyć swoją wartość, a kiedy zmniejszyć, w zależności od kierunku obrotu enkodera.
I to wszystko! Wystarczy teraz dopisać prostą procedurę pokazującą stan licznika na wyświetlaczu LCD. Pamiętać trzeba, że pojedynczy impuls enkodera powoduje zwiększenie lub zmniejszenie wartości timera o 4 - dlatego przed wyświetleniem wartości rejestru TCC0.CNT, musimy ją podzielić najpierw podzielić przez 4.
Dominik Leon Bieczyński
www.leon-instruments.pl