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

AVR - Obsługa przerwań dla enkodera przy dużej prędkości obrotowej

Marek_Gorecki 28 Maj 2015 23:08 4677 49
Najlepsze odpowiedzi

Czy mogę pozwolić, aby przerwanie od enkodera INT0 mogło przerywać inne procedury obsługi przerwań, i czy jest to bezpieczne?

Tak, możesz to zrobić, ale na AVR nie ustawisz sprzętowo innego priorytetu — INT0 i tak ma najwyższy priorytet po RESET, więc zwykle lepiej najpierw maksymalnie skrócić ISR enkodera i uprościć pozostałe obsługi niż bawić się w „priorytety” [#14729628][#14730145][#14730808] Jeśli mimo to chcesz zagnieżdżania, użyj `ISR_NOBLOCK` albo ręcznie: w innych ISR zablokuj wszystkie przerwania poza INT0, potem wykonaj `sei()`, a przed końcem `cli()` i ponownie odblokuj potrzebne źródła [#14729341][#14734245][#14734700] Trzeba przy tym uważać na reentrantność funkcji, współdzielone wielobajtowe zmienne i zużycie stosu/RAM, bo przy zagnieżdżaniu kolejne przerwania mogą wchodzić jedno w drugie [#14729634][#14734700] Przy Twoich kilku kHz i 14,74 MHz forumowicze ocenili, że powinno być dość czasu na obsługę, więc warto najpierw zrobić test z `ISR_NOBLOCK` i sprawdzić oscyloskopem/analizatorem, czy rzeczywiście gubisz impulsy; możliwa jest też przyczyna sprzętowa, np. zbyt duży rezystor podciągający 10 kΩ i wolne zbocza [#14730808][#14731538][#14730758]
Podsumowanie wygenerowane przez AI na podstawie treści dyskusji.
  • #1 14729209
    Marek_Gorecki
    Poziom 16  
    Posty: 494
    Pomógł: 2
    Ocena: 30
    Witam;

    mam program, w którym używam kilku przerwań (timery, 4xUART).

    Niestety, muszę kontrolować encoder o bardzo dużej ilości impulsów.
    Wszystko działa prawidłowo, ale przy dużej prędkości obrotowej encodera, czasem procesor źle zinterpretuje dane i pojawi się bład w liczeniu impulsów.
    Jak wiadono Encoder wysyła dwa przesunięte impulsy A i B. Problem w tym, że jeśli powstanie kolejka przerwań to zanim procesor wejdzie w procedurę obsługi przerwania dla INT0 (tu jest podpięty encoder), to w tym czasie stan tego drugiego kanału ulega zmianie i zamiast dodać procesor odejmie impuls.
    Takie mam przypuszczenia.

    Nie mogę zwiększyć czestotliwości takowania, bo mam na 14.74Mhz, a procesor to AMEGA 2560. Czyli max jest 16MHz.

    I teraz pytanie - czy mógłbym odblokować w innych procedurach tylko to jedno przerwania od tego encodera , które byłoby bardzo krótkie (sprawdzenie stanu kanału B i ustawienie flagi)?
    Czy to jest bezpiecznie?

    pozdrawiam
  • #2 14729239
    excray
    Poziom 41  
    Posty: 5500
    Pomógł: 739
    Ocena: 656
    Oczywiście że możesz. Konkretne rozwiązanie wymaga podania języka w jakim piszesz. Niemniej moim zdaniem powinieneś zupełnie inaczej podejść do tematu. Opisz szerzej swoja aplikację a dokładniej w jakim celu wykorzystujesz enkoder.
  • #3 14729267
    Marek_Gorecki
    Poziom 16  
    Posty: 494
    Pomógł: 2
    Ocena: 30
    Encoder służy do pomiaru odległości.
    Wiem , że mógłbym użyć innego , z mniejszą ilością impulsów, ale mam tylko taki.
    Ten encoder jest optyczny i ma najprawdopodobniej 1000 imp/obrót.
    Kółka pomiarowego nie mogę zwiększyć, bo nie ma miejsca.
    Oprocz tego odbieram jeszcze dane po RS z kilku zródeł, a także pracuja 2 timery z przerwaniami.

    Pisze w języku C.
    Zatem, aby odblokować to jedno przerwanie w każdym innym przerwaniu to musze zablkować wszystkie inne przerwania, a następnie dać "sei" ?
  • #5 14729279
    excray
    Poziom 41  
    Posty: 5500
    Pomógł: 739
    Ocena: 656
    Czy kierunek jest Ci rzeczywiście potrzebny?
  • #6 14729298
    Marek_Gorecki
    Poziom 16  
    Posty: 494
    Pomógł: 2
    Ocena: 30
    excray napisał:
    Czy kierunek jest Ci rzeczywiście potrzebny?


    tak.

    Jeśli chodzi o częstotlwość impulsów to jest to max kilka KHz .
    Problem pojawia się jeśli szarpnę mocno mierzonym wężem.
    Wtedy pojawiają się błedy, i po wysunięciu a następnie zwinięciu węża nie mam zera na wyświetlaczu.

    Dodano po 2 [minuty]:

    Może częstotliwość nie jest porażająca, ale czas przesunięcia impuslów wzgledem siebie jest bardzo mały.
  • #7 14729316
    dondu
    VIP Zasłużony dla elektroda
    Posty: 13906
    Pomógł: 1292
    Ocena: 809
    W takim przypadku możesz w pozostałych funkcjach przerwań użyć atrybut ISR_BLOCK co spowoduje, że kompilator doda na ich początku rozkaz sei() i każde inne przerwanie będzie mogło przerwać takie przerwanie.

    Oczywiście wtedy ostrożnie musisz podchodzić do ilości wolnej pamięci RAM, bo w skrajnym przypadku stos może ją przepełnić.
  • #8 14729326
    Marek_Gorecki
    Poziom 16  
    Posty: 494
    Pomógł: 2
    Ocena: 30
    dondu napisał:
    W takim przypadku możesz w pozostałych funkcjach przerwań użyć atrybut ISR_BLOCK co spowoduje, że kompilator doda na ich początku rozkaz sei() i każde inne przerwanie będzie mogło przerwać takie przerwanie.

    Oczywiście wtedy ostrożnie musisz podchodzić do ilości wolnej pamięci RAM, bo w skrajnym przypadku stos może ją przepełnić.


    ale ja bym chciał, aby tylko to jedno przerwanie od INT0 się mogło odbyć w trakcie trwania innych przerwań.
    Jeśli otworze inne, to boję się że może dojść do tragedii.
  • Pomocny post
    #9 14729341
    dondu
    VIP Zasłużony dla elektroda
    Posty: 13906
    Pomógł: 1292
    Ocena: 809
    Bez obawy :)
    Wprawdzie nie znamy programu, ale spokojnie dasz radę - spróbuj.

    Alternatywnie możesz oczywiście sam decydować o tym, dodając na początku każdego przerwania innego niż INT0 rozkazy blokujące wszystkie pozostałe z wyjątkiem INT0 i dodać sei() + na końcu dodać cli(), a po nim odblokować zablokowane przerwania.

    Ale najpierw spróbuj ISR_BLOCK i możliwie najkrótszą funkcję obsługi przerwania INT0.

    Dodano po 10 [minuty]:

    Miałem na myśli oczywiście ISR_NOBLOCK :)
  • #10 14729606
    Marek_Gorecki
    Poziom 16  
    Posty: 494
    Pomógł: 2
    Ocena: 30
    A czy można zmienić priorytet przerwań. Chodzi mi o to, aby jeśli w trakcie wykonywania jakiegoś przerwania, zgłosily się przykładowo 2 kolejne, to aby jedno z nich było zawsze wykonywane w pierwszej koilejności?
  • Pomocny post
    #11 14729628
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #12 14729634
    Andrzej__S
    Poziom 28  
    Posty: 567
    Pomógł: 182
    Ocena: 65
    Chciałbym jeszcze coś dodać, bo moim zdaniem zapotrzebowanie na RAM to nie jedyny problem w przypadku zagnieżdżania przerwań.

    Nie znamy programu, więc trudno przewidzieć, czy sprawa dotyczy tego konkretnego przypadku. W przypadku zagnieżdżania przerwań należy jednak pamiętać o pewnych zasadach. Procedury obsługi przerwań, które ustawiają globalną flagę zezwalającą na przerwania muszą np. zapewniać atomowy dostęp do współdzielonych wielobajtowych zmiennych czy też używać funkcji reentrant (w przypadku wywoływania tej samej funkcji również w procedurach obsługi innych przerwań). W niektórych przypadkach może i tak być konieczne zablokowanie przerwań np. w czasie modyfikacji zmiennej wielobajtowej lub wykonywania niektórych funkcji, co z kolei opóźni obsługę przerwania, którego priorytet chcemy podnieść. Normalnie flaga I w SREG jest wyzerowana w czasie obsługi przerwania, więc nie trzeba się o takie rzeczy martwić.

    Piszę o tym, bo widzę 4xUART, więc jest duże prawdopodobieństwo, że procedury obsługi przerwań wywołują tę samą funkcję np. dodającą dane do bufora cyklicznego. Jeśli tak jest to należałoby sprawdzić, czy funkcje te spelniają wymogi reentrant.
  • #13 14729673
    Marek_Gorecki
    Poziom 16  
    Posty: 494
    Pomógł: 2
    Ocena: 30
    No widze że jednak to chyba jest niebezpieczny kierunek.
    Zastanawiam się , czy można te impulsy podzielić , aby nie dręczyły tak obficie procesora. Tylko, że chodzi mi o to, aby po podziale zwiększył się dystans pomiędzy impulsami, bo to właśnie ten dystans dla mnie jest najważniejszy.
    Jeśli podzielę oba impulsy przez np 16 na przerzutnikach , to nic mi to nie da, odległość się nie zmieni.
    Macie może jakieś pomysły ?
    Czy tylko dodatkowy mały procesor?
  • #14 14729811
    dondu
    VIP Zasłużony dla elektroda
    Posty: 13906
    Pomógł: 1292
    Ocena: 809
    Ponowię:

    dondu napisał:
    Bez obawy :)
    ... spokojnie dasz radę - spróbuj.

    ... spróbuj ISR_BLOCK i możliwie najkrótszą funkcję obsługi przerwania INT0.

    Zrób w końcu test, a przekonasz się, czy Twoje obawy są słuszne. Ja sądzę (nie znając programu), że jeżeli pozostałe przerwania nie są napisane w jakiś kosmicznie blokujący mikrokontroler sposób, to bez problemu je obsłużysz.
  • #15 14729829
    Konto nie istnieje
    Poziom 1  
  • #16 14730145
    Andrzej__S
    Poziom 28  
    Posty: 567
    Pomógł: 182
    Ocena: 65
    Marek_Gorecki napisał:
    No widze że jednak to chyba jest niebezpieczny kierunek.

    Skąd ten pesymizm. Nikt nie napisał, że się nie da (włącznie ze mną), tylko uświadamiamy Ci, na co zwrócić uwagę.

    Marek_Gorecki napisał:
    A czy można zmienić priorytet przerwań. Chodzi mi o to, aby jeśli w trakcie wykonywania jakiegoś przerwania, zgłosily się przykładowo 2 kolejne, to aby jedno z nich było zawsze wykonywane w pierwszej koilejności?

    Priorytetu nie da się w AVR zmienić (jedynie pozornie poprzez zagnieżdżanie), ale akurat INT0 ma priorytet najwyższy (zaraz po RESET). W przypadku, kiedy w czasie trwania wykonywania jednej procedury obsługi przerwania pojawią się dwa przerwania (lub więcej), to przerwanie INT0 będzie obsłużone w pierwszej kolejności.
    Jeśli łączny czas najdłuższej z procedur obsługi przerwań i tej od INT0 nie jest dłuższy od najkrótszego odstępu między zboczami impulsów z enkodera, to na pewno nie zgubisz impulsu, nawet jeśli nie będziesz zagnieżdżał przerwań.

    atom1477 napisał:
    Jeżeli impulsy masz co max kilka kHz, przyjmijmy najgorszy wariant 10kHz, to masz aż 14740 cykli na obsługę. Może Ci chodziło o cały cykl a nie impulsy, a więc to będą 4 zbocza (enkoder odczytywany kwadraturowo). No to wtedy masz 4 razy więcej zbocz, czyli 4 razy mniej czasu na obsługę. To i tak aż 3685 cykli.

    Kolega się chyba pomylił o jedno miejsce dziesiętne :wink:
    No ale może się uda wyrobić w 368 taktach, może wystarczy jedno przerwanie na cały cykl (zamiast 4 na każdym zboczu) i wtedy mamy do dyspozycji 1474 takty, może enkoder nie osiąga aż 600 obrotów na minutę. Dobrze byłoby mieć jakieś dokładniejsze dane.

    Marek_Gorecki napisał:
    Jeśli podzielę oba impulsy przez np 16 na przerzutnikach , to nic mi to nie da, odległość się nie zmieni.


    Zwykły dzielnik częstotliwości na przerzutnikach tu nic nie da i nie chodzi tu tylko o odległość między zboczami. Aby podzielić dobrze częstotliwość impulsów z enkodera na obu kanałach z zachowaniem przesunięcia fazowego między nimi potrzebowałbyś jeszcze sporo innych elementów. Tak bym nie kombinował.
  • #17 14730382
    Konto nie istnieje
    Poziom 1  
  • #18 14730644
    bootrecord
    Poziom 14  
    Posty: 55
    Pomógł: 4
    Ocena: 10
    Proponuje rozważyć zmianę procesora na jeden z rodziny PIC18F. One w standardzie obsługują dwa priorytety przerwań ... i za to je lubię. Wtedy taki problem można bardzo łatwo rozwiązać. Encoder robi się na obsłudze normalnego przerwania a wszystkie pozostałe na przerwaniu z niskim priorytetem.

    Oczywiście jeśli chcesz przejść na innego producenta - przyzwyczajenie robi swoje.
  • #19 14730713
    Marek_Gorecki
    Poziom 16  
    Posty: 494
    Pomógł: 2
    Ocena: 30
    Zmiana procesora, raczej nie możliwa.
    Jeśli już to zmieniłbym na Xmega co ma sprzetową obsługę encodera.
    Ale na razie bede probował na ATMEGA2560.

    Jeśli chodzi o przerwania to wyglądają one tak (kompilator Codevision):

    1) Procedura odczytu encodera (przerwanie na obu zboczach):

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Procedury odbioru danych z UARTA sa 4 i wszystkie identyczne:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Jest też jedna przerwanie od Timera:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Wydaje mi się, że wszystkie te procedury nie są zbyt obciążające.
    Co o tym sądzicie?
  • #20 14730758
    Konto nie istnieje
    Poziom 1  
  • #21 14730808
    Andrzej__S
    Poziom 28  
    Posty: 567
    Pomógł: 182
    Ocena: 65
    @Marek_Gorecki
    Jeden cykl enkodera składa się z czterech zboczy (po 2 na każdy kanał). Sądząc po tym co piszesz nie potrzebujesz dużej precyzji i zliczasz tylko jedno z nich, więc częstotliwość przerwań INT0 wyniesie:
    
        f = n*N/60
    
    gdzie:
        n - prędkość obrotowa enkodera [1/min]
        N - ilość cykli ekodera na obrót
    

    Ilość taktów procesora pomiędzy przerwaniami będzie równa F_CPU/f.

    Ilość taktów od wystąpienia przerwania INT0 do zmiany stanu drugiego z kanałów będzie czterokrotnie mniejsza (w tym czasie należy odczytać stan drugiego pinu). Przy założeniu F_CPU = 14,74MHz i prędkości obrotowej 600obr./min będzie to około 380-390 taktów, a więc całkiem sporo. W procedurze obsługi INT0 interesuje nas głównie czas na prolog i odczytanie stanu drugiego pinu, co nie powinno zająć więcej niż ok. 30-40 taktów. Jeśli jesteś w stanie zrobić tak, by reszta (około 350 taktów) wystarczyła na wykonanie dowolnej z pozostałych procedur obsługi przerwań, jakich używasz, to obędzie się bez zagnieżdżania przerwań.

    Można oczywiście użyć zagnieżdżania, jest to jak najbardziej wykonalne, ale należy pamiętać o tym, o czym napisałem w poście #12. Trzeba też pamiętać, że samo ISR_NOBLOCK włączy wszystkie aktywne przerwania, więc w najgorszym przypadku zagnieżdżanie osiągnie poziom równy ilości aktywnych przerwań, konsumując RAM (stos) i powodując, że obsługa przerwania, które wystąpiło pierwsze, zakończy się jako ostatnia. Osobiście zamiast ISR_NOBLOCK (które zdaje się włącza globalną flagę przerwań zaraz na początku przed prologiem procedury) użyłbym sei() na początku obsługi po prologu i wcześniejszym wyłączeniu wszystkich przerwań oprócz INT0, a na końcu procedury włączyłbym wszystkie przerwania ponownie.

    Marek_Gorecki napisał:
    Wydaje mi się, że wszystkie te procedury nie są zbyt obciążające.

    Myślę, że można sprawdzić w symulatorze, ile taktów potrzebują na wykonanie - należy rozpatrzyć najgorszy przypadek.

    EDIT:
    Jak pisałem post, to nie widziałem jeszcze Twojego kodu. Widzę, że przerwania masz na obu zboczach, więc będą dwa razy częściej, ale limit (ok. 350 taktów) pozostaje bez zmian.
  • #22 14731109
    dondu
    VIP Zasłużony dla elektroda
    Posty: 13906
    Pomógł: 1292
    Ocena: 809
    Andrzej__S napisał:
    Osobiście zamiast ISR_NOBLOCK (które zdaje się włącza globalną flagę przerwań zaraz na początku przed prologiem procedury) użyłbym sei() na początku obsługi po prologu i wcześniejszym wyłączeniu wszystkich przerwań oprócz INT0, a na końcu procedury włączyłbym wszystkie przerwania ponownie.


    W poście #9 sugerowałem autorowi, ale nie sprawdził tego jeszcze:

    dondu napisał:
    Alternatywnie możesz oczywiście sam decydować o tym, dodając na początku każdego przerwania innego niż INT0 rozkazy blokujące wszystkie pozostałe z wyjątkiem INT0 i dodać sei() + na końcu dodać cli(), a po nim odblokować zablokowane przerwania.

    Ale najpierw spróbuj ISR_BLOCK i możliwie najkrótszą funkcję obsługi przerwania INT0.


    Marek_Gorecki napisał:
    Wydaje mi się, że wszystkie te procedury nie są zbyt obciążające.
    Co o tym sądzicie?

    to:
    atom1477 napisał:
    No ale przede wszystkim to zrób w końcu ten test z ISR_NOBLOCK.

    dondu napisał:
    Zrób w końcu test, a przekonasz się, czy Twoje obawy są słuszne.
  • #23 14731422
    Andrzej__S
    Poziom 28  
    Posty: 567
    Pomógł: 182
    Ocena: 65
    @dondu
    No chyba faktycznie nie doczytałem i powieliłem radę. Jeśli Cię tym uraziłem to przepraszam.

    Wreszcie autor tematu uchylił rąbka tajemnicy i sypnął fragmentami kodu :)
    Odnoszę wrażenie, że te procedury powinny się wyrobić bez konieczności zagnieżdżania przerwań, chyba, że nie mamy prawidłowych danych odnośnie prędkości obrotowej enkodera i/lub ilości impulsów na obrót. Nawet jeśli prędkości transferu przez UART'y są duże i przerwania występują często, to i tak prędzej spodziewałbym się gubienia znaków przez UART niż impulsów z enkodera, bo przecież procedury obsługi przerwań zewnętrznych mają wyższy priorytet.

    @Marek_Gorecki
    Mógłbyś może dokładniej opisać relację wąż-enkoder?
  • #24 14731434
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #25 14731538
    Fredy
    Poziom 27  
    Posty: 915
    Pomógł: 117
    Ocena: 28
    A czy czasem ten encoder nie ma wyjścia typu OC (otwarty kolektor)?
    Jeśli tak, to przy takiej dużej częstoliwości impulsów, odległość pomiędzy może być tak mała, że na skutek tworzenia się układu całkującego możesz źle interpretować te impulsy.
    Jeśli rzeczywiście jest to encoder o wyjściu OC to :
    Jakie rezystory masz na kolektorach?
    Spróbuj je zmniejszyć do najmniejszej dopuszczalnej wartości, lub zrób wzmacniacz niskoimpedancyjny np na dwóch tranzystorach NPN i PNP.

    Możesz jeszcze spróbować, czy detekcja tylko na opadającym zboczu działa prawidłowo.
    Mam wrażenie że tak będzie - jeśli tak, to masz rozwiazanie, bo zbocze opadające będzie bardzo ostre i szybkie.
    Drugie zbocze będzie uzależnione od rezystora kolekterowego i pojemności kabla.
  • #26 14731817
    dondu
    VIP Zasłużony dla elektroda
    Posty: 13906
    Pomógł: 1292
    Ocena: 809
    Andrzej__S napisał:
    @dondu
    No chyba faktycznie nie doczytałem i powieliłem radę. Jeśli Cię tym uraziłem to przepraszam.

    Nie, nie :)
    Chodziło mi tylko o to, by autor tematu zaczął wreszcie wykonywać próby, bo już sporo napisaliśmy i odpowiedzi zaczynają się powtarzać.
  • #27 14731926
    Andrzej__S
    Poziom 28  
    Posty: 567
    Pomógł: 182
    Ocena: 65
    Marek_Gorecki napisał:
    Problem pojawia się jeśli szarpnę mocno mierzonym wężem.
    Wtedy pojawiają się błedy, i po wysunięciu a następnie zwinięciu węża nie mam zera na wyświetlaczu.

    Zastanawia mnie jeszcze rodzaj sprzężenia między enkoderem a obiektem mierzonym. Jeśli jest to sprzężenie cierne, jak się domyślam, to być może po prostu występuje poślizg przy szarpnięciu węża i z tego wynika błąd.

    atom1477 napisał:
    Może po prostu dane z enkodera są zakłócone i występuje więcej impulsów niż wynikało by z prędkości obrotowej enkodera. Przy kwadraturowym jest jeszcze o tyle dobrze że zakłócenia się same niwelują. Tzn. licznik będzie zliczał do przodu i do tyłu na przemian. Tyle że ten licznik musi po prostu nadążać z tym zliczaniem. A tutaj liczy procek i go może po prostu zamulają te zakłócenia.

    Fredy napisał:
    A czy czasem ten encoder nie ma wyjścia typu OC (otwarty kolektor)?
    Jeśli tak, to przy takiej dużej częstoliwości impulsów, odległość pomiędzy może być tak mała, że na skutek tworzenia się układu całkującego możesz źle interpretować te impulsy.


    Jak widać wina niekoniecznie musi leżeć po stronie mikrokontrolera. W celu rozgraniczenia problemu zbudowałbym prosty symulator enkodera na innym mikrokontrolerze, który po wciśnięciu przycisku wygeneruje np. 50000 impulsów w prawo z maksymalną oczekiwaną częstotliwością i później 50000 impulsów w lewo z częstotliwością np. o połowę mniejszą, aby mieć pewność, że wracając żadnego impulsu nie zgubi. Wystarczy prosty programik oparty o funkcję delay() i pętlę for(), nie potrzeba jakiejś super dokładności. Wtedy byłoby wiadomo, czy mikrokontroler się nie wyrabia, czy przyczyna leży gdzie indziej.
    Przy okazji, zmieniając wartości opóźnień, można ustalić częstotliwość graniczną, przy której mikrokontroler zaczyna gubić impulsy.
  • #28 14732735
    jnk0le
    Poziom 18  
    Posty: 172
    Pomógł: 33
    Ocena: 31
    Marek_Gorecki napisał:

    Procedury odbioru danych z UARTA sa 4 i wszystkie identyczne:


    Wydaje mi się, że wszystkie te procedury nie są zbyt obciążające.
    Co o tym sądzicie?


    Zakładając że rx0_index jest typu 'volatile' można zrobić coś takiego :

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Zaoszczędzi to parę cykli potrzebnych na dostęp do pamięci.

    No i jestem bardzo ciekaw jak wygląda odbiór danych w pętli głównej bo na bufor cykliczny mi to nie wygląda :D
  • #29 14733873
    Marek_Gorecki
    Poziom 16  
    Posty: 494
    Pomógł: 2
    Ocena: 30
    jnk0le napisał:


    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Zaoszczędzi to parę cykli potrzebnych na dostęp do pamięci.

    No i jestem bardzo ciekaw jak wygląda odbiór danych w pętli głównej bo na bufor cykliczny mi to nie wygląda :D


    To dodawanie na końcu znaku null rzeczywiscie nie jest potrzebne. Moge je przeciez dodać wtedy gdy potrzebuję.
    A jeśli chodzi o Twój program - to czemu miałby on zajmowac mniejszą ilosc danych?

    Do kolegów co podpowiadają mi użycie makr, tak jak pisałem wczesniej, uzywam Codevision a w nim nie ma czegoś takiego - chyba.
  • #30 14734161
    jnk0le
    Poziom 18  
    Posty: 172
    Pomógł: 33
    Ocena: 31
    Marek_Gorecki napisał:

    A jeśli chodzi o Twój program - to czemu miałby on zajmowac mniejszą ilosc danych?


    Bo zmiennych 'volatile' kompilator nie optymalizuje gdyż zakłada iż są modyfikowane przez jakieś zewnętrzne peryferia i w każdym cyklu moga mieć inną wartość. Co oznacza że każde użycie będzie się wiązało z ładowaniem zmiennej z pamięci do rejestrów i dopiero wykonanie koniecznych zadań. I tak przy każdym kolejnym użyciu, a dostęp do pamięci to co najmniej 2 cykle zamiast jednego.

Podsumowanie tematu

✨ W dyskusji poruszono problem obsługi przerwań w mikrokontrolerze ATmega 2560 przy wysokich prędkościach obrotowych enkodera optycznego, który generuje do 1000 impulsów na obrót. Użytkownik zauważył błędy w zliczaniu impulsów, które mogą wynikać z opóźnień w obsłudze przerwań, gdyż procesor nie nadąża z interpretacją stanów kanałów A i B. Proponowane rozwiązania obejmują użycie atrybutu ISR_BLOCK, aby umożliwić obsługę przerwania INT0 w trakcie innych przerwań, oraz optymalizację kodu obsługi przerwań, aby zredukować czas ich wykonania. Zwrócono również uwagę na możliwość zakłóceń w sygnale enkodera oraz na znaczenie odpowiedniego doboru rezystorów w obwodzie. Użytkownik rozważał także zmianę procesora na Xmega, który ma sprzętową obsługę enkodera, ale postanowił najpierw przetestować rozwiązania na ATmega 2560.
Podsumowanie wygenerowane przez AI na podstawie treści dyskusji.
REKLAMA