Programowanie mikrokontrolerów Xmega cz.5. System zdarzeń

Programowanie mikrokontrolerów Xmega cz.5. System zdarzeń
Pobierz PDF Download icon
W mikrokontrolerach XMEGA układów peryferyjnych jest bardzo dużo, ale rdzeń procesora jest tylko jeden. Mogłoby się okazać, że rdzeń nie jest w stanie przetwarzać danych wysyłanych przez peryferia. Projektanci układów XMEGA udostępnili narzędzia, pozwalające peryferiom komunikować się ze sobą zupełnie bez pośrednictwa rdzenia - są to DMA oraz system zdarzeń. W tym artykule zajmiemy się zdarzeniami, a DMA zostanie omówione w kolejnych częściach.

Rysunek 1. Timer i przetwornik ADC połączone systemem zdarzeń

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.

Rysunek 2. Sieć połączeń (rounting network)

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.

Rysunek 3. Schemat układu demonstrującego podstawowe funkcje systemu zdarzeń

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!

Rysunek 4. Wybór nadajnika zdarzenia

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.

Rysunek 5. Schemat układu z enkoderem obrotowym

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.

Fotografia 6. Prototyp na płytce stykowej

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

Rysunek 7. Przebiegi na wyjściach A i B enkodera

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.

Rysunek 8. Dokumentacja rejestru CHxCTRL

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

Artykuł ukazał się w
Elektronika Praktyczna
marzec 2014
DO POBRANIA
Pobierz PDF Download icon
Zobacz też
Elektronika Praktyczna Plus lipiec - grudzień 2012

Elektronika Praktyczna Plus

Monograficzne wydania specjalne

Elektronik lipiec 2020

Elektronik

Magazyn elektroniki profesjonalnej

Raspberry Pi 2015

Raspberry Pi

Wykorzystaj wszystkie możliwości wyjątkowego minikomputera

Świat Radio lipiec 2020

Świat Radio

Magazyn użytkowników eteru

APA - Automatyka Podzespoły Aplikacje lipiec 2020

APA - Automatyka Podzespoły Aplikacje

Technika i rynek systemów automatyki

Elektronika Praktyczna lipiec 2020

Elektronika Praktyczna

Międzynarodowy magazyn elektroników konstruktorów

Praktyczny Kurs Elektroniki 2018

Praktyczny Kurs Elektroniki

24 pasjonujące projekty elektroniczne

Elektronika dla Wszystkich lipiec 2020

Elektronika dla Wszystkich

Interesująca elektronika dla pasjonatów