logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Xmega A1 - Jak poprawnie zrealizować USART z przerwaniami?

12 Gru 2014 17:51 1788 9
REKLAMA
  • #1 14216435
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • Pomocny post
    #2 14216759
    tmf
    VIP Zasłużony dla elektroda
    Po pierwsze enkoder możesz obsługiwać sprzętowo na XMEGA - w tym celu konfigurujesz event system na QDEC, a dowolny timer będzie ci zliczał impulsy i pracował jako enkoder. Co do transmisji USART - można paczki odbierać przez DMA, co jest wygodne, można to zrobić w oparciu o przerwania. W tym celu odblokowujesz przerwanie RXComplete sygnalizujące gotowy bajt danych i w funkcji obsługi przerwania umieszczasz go w buforze. W przykładach do moich książek o XMEGA znajdziesz przykłady i jak zrealizować obsługę enkodera i jak odbierać dane z USART przy pomocy przerwań/DMA.
  • #3 14224337
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • Pomocny post
    #4 14224527
    tmf
    VIP Zasłużony dla elektroda
    Oczywiście możesz zrobić przerwania od QDEC - pin generujący event może też generować przerwanie. Lecz nie jest to potrzebne. Porównanie z określoną wartością możesz uzyskać sprzętowo - np. timer porównuje wartość CNT (licznik impulsów z enkodera) z CCx, równość może wywołać przerwanie. Co do przeliczania impulsów - jeśli zostaną ci wolne timery to możesz je wykorzystać do dzielenia. Np. timer z QDEC liczy do 10 impulsów i co 10-ty generuje OVF, które zlicza kolejny timer. W efekcie masz w nim impulsy/10. Nie wiem, czy ma to sens, ale można.
  • REKLAMA
  • #5 14225243
    Konto nie istnieje
    Konto nie istnieje  
  • Pomocny post
    #6 14225566
    tmf
    VIP Zasłużony dla elektroda
    Prawdę mówiąc nie widzę sensu w realizacji dzielenia przez 40 sprzętowo. Ale jak pisałem, jeśli masz wolny timer, to do rejestru PER timera za pomocą którego realizujesz QDEC wpisujesz 39, wtedy co 40 impulsów wygeneruje ci przepełnienie, które możesz transmitować przez event system jako zegar dla drugiego timera, który w efekcie będzie zliczał co 40 impuls, czyli będziesz miał wartość CNT tego timera wyrażoną w mm. Możesz sobie w nim ustawić np. CCA na 10 i wtedy po 10mm wygeneruje ci przerwanie informujące, że twój enkoder przejechał właśnie 10mm. IMHO to sztuka dla sztuki i zabawa, z drugiej strony jeśli wolne zasoby sprzętowe mają się marnować...
  • #7 14225638
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #8 14225752
    tmf
    VIP Zasłużony dla elektroda
    Stosując opisaną przeze mnie metodę tracisz informację o kierunku. Można ją odzyskać bawiąc się rejestrami porównań zamiast sygnałem OVF, ale wymaga to dwóch kanałów event system - jeden do zliczania i drugi do przestawiania licznika do liczenia góra/dół (wykorzystując event action na liczniku). Ale IMHO to już totalnie sztuka dla sztuki mająca sens o tyle, żeby pokazać, że tak się da. Chociaż nawet nic być może nie trzeba robić - w trybie QDEC jeden kanał event system zawiera informację o kierunku zliczania, wystarczy więc ten kanał podpiąć jako event action dla drugiego timera. Nie testowałem takiej konfiguracji, ale powinna działać.
  • #9 14226258
    Konto nie istnieje
    Konto nie istnieje  
  • #10 14226365
    tmf
    VIP Zasłużony dla elektroda
    System event może dla timera robić dwie rzeczy - być źródłem zegara - to już zrobiłeś, ale oprócz tego każdy timer ma rejestr (CTRLD), w którym można powiązać kanał zdarzeń z akcją, jedną z dozwolonych akcji jest zmiana kierunku zliczania góra/dół (UPDOWN). Zresztą już to musiałeś wykorzystać, bo jedną z akcji jest QDEC, czyli dekoder kwadraturowy. Dekoder kwadraturowy wymaga dwóch kanałów zdarzeń - jednym transmitowane są zliczane impulsy generowane przez enkoder, drugim kierunek zliczania góra/dół. Jeśli ten drugi kanał podepniesz pod event action innego timera jak UPDOWN action, to w efekcie oba timery będą zliczać w zależności od kierunku obrotu enkodera. Zauważ jednak, że to wszystko jest niepotrzebne, bo kombinujemy tylko po to, żeby podzielić wartość CNT licznika przez stałą. Zamiast kombinować podziel to po prostu w kodzie programu, myślałem, że kombinujesz w celach edukacyjnych.
    Żeby zapalić diodę przy określonym stanie licznika nie potrzeba przerwań - wystarczy podpiąć ją pod jeden z kanałów wyjściowych (CCx) timera pracującego w trybie PWM - wtedy stan wyjścia zmieni się jeśli CNT=CCx, możesz sobie ustalić czy ma wtedy być niski, wysoki, czy zmienić się na przeciwny.
    Można to też zrobić w oparciu o przerwania - timer musi być w trybie w którym CCx jest porównywane (compare), a nie przechwytywane (capture), czyli w jednym z trybów generowania PWM (mimo, że żadnego PWM nie generujesz). Musisz odblokować przerwania globalne (sei), zezwolenie na określony poziom przerwań (PMIC), ale także skonfigurować poziom przerwań zgłaszanych przez wybrany kanał układu peryferyjnego - rejestr timera INTCTRLB. Inaczej skąd timer ma wiedzieć, żeby zgłaszać przerwania i jakie mają one mieć priorytet? W obu przypadkach pin do którego jest podłączona dioda musi być wyjściem (rejestr DIR).
    Myślę, że zabrałeś się do tego wszystkiego od złej strony. Zmieniając architekturę zawsze zaczynaj od początku. Nawet jeśli wydaje ci się, że coś jest oczywiste i proste - przeskakujesz jakiś temat a potem wychodzą kwiatki. Jak widzisz w XMEGA, w przeciwieństwie do starych procków wiele można zrobić całkowicie sprzętowo, ale oczywiście za cenę jaką jest dogłębne poznanie tego sprzętu. A podkreślniki to tylko podkreślniki, jeśli ci przeszkadzają to masz a Atmel Studio opcję refactoringu kodu - jedno kliknięcie i możesz sobie podkreślniki zamienić na serduszka :)
REKLAMA