Brak produktów
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.
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 (chyba, że mamy problem z drganiem styków, to wtedy mogą się przydać). 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 poniżej – 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.
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, 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.
// wejścia enkodera PORTCFG.MPCMASK = 0b00000011; // wybór pinów 0 i 1 do konfiguracji PORTC.PIN0CTRL = PORT_ISC_LEVEL_gc | // reagowanie na poziom niski PORT_OPC_PULLUP_gc; // podciągnięcie do zasilania
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 3. 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 rozpoznany jeżeli będzie utrzymywał się na wejściu dłużej niż wybrana liczba cykli zegarowych. Ustawmy więc filtr na osiem cykli.
// konfiguracja systemu zdarzeń EVSYS.CH0MUX = EVSYS_CHMUX_PORTC_PIN0_gc; // pin C0 wywołuje zdarzenie EVSYS.CH0CTRL = EVSYS_QDEN_bm| // włączenie dekodera w systemie zdarzeń EVSYS_DIGFILT_8SAMPLES_gc; // filtr cyfrowy
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.
// konfiguracja timera TCC0.CTRLA = TC_CLKSEL_EVCH0_gc; // taktowanie zegarem 2MHz TCC0.CTRLD = TC_EVACT_QDEC_gc | // włączenie dekodera kwadraturowego TC_EVSEL_CH0_gc; // dekoder zlicza impulsy z kanału 0
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 rejestruTCC0.CNT, musimy ją podzielić najpierw podzielić przez 4.
#define F_CPU 2000000UL #include <avr/io.h> #include <util/delay.h> #include "hd44780.h" int main(void) { // wejścia enkodera PORTCFG.MPCMASK = 0b00000011; // wybór pinów 0 i 1 do konfiguracji PORTC.PIN0CTRL = PORT_ISC_LEVEL_gc | // reagowanie na poziom niski PORT_OPC_PULLUP_gc; // podciągnięcie do zasilania // konfiguracja systemu zdarzeń EVSYS.CH0MUX = EVSYS_CHMUX_PORTC_PIN0_gc; // pin C0 wywołuje zdarzenie EVSYS.CH0CTRL = EVSYS_QDEN_bm| // włączenie dekodera w systemie zdarzeń EVSYS_DIGFILT_8SAMPLES_gc; // filtr cyfrowy // konfiguracja timera TCC0.CTRLA = TC_CLKSEL_EVCH0_gc; // taktowanie systemem zdarzeń TCC0.CTRLD = TC_EVACT_QDEC_gc | // włączenie dekodera kwadraturowego TC_EVSEL_CH0_gc; // dekoder zlicza impulsy z kanału 0 // wyświetlacz LcdInit(); while(1) { // wyświetlenie aktualnej wartości licznika CNT // CNT = ... LcdClear(); Lcd("CNT = "); LcdDec(TCC0.CNT / 4); // jeden przeskok to 4 impulsy _delay_ms(100); // czekanie 100ms } }