Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[ATMEGA 8][AVR-gcc] - Priorytetowość przerwań

skyguy 15 Feb 2013 17:28 2838 11
  • #1
    skyguy
    Level 14  
    W jaki sposób można ustawić priorytetowość przerwań?

    Mam taki problem:
    Za pomocą przerwań zewnętrznych mierzę długość impulsów na 2 wejściach.Wszystko gra do póki nie podłącze do atmegi USART który wypytuje co jakiś czas o te dane.
    Kiedy leci pytanie i Atmega ma przerwanie od USART co jakiś czas są przekłamania odnoście czasu trwania długości impulsu.

    Mam 2 przerwania od zbocza opadającego i narastającego, i między nimi może wpakowuję się przerwanie od USART?

    Macie jakiś pomysł jak to załatwić?
  • Helpful post
    #3
    BlueDraco
    MCUs specialist
    AVR ma jednopoziomowy system przerwań. Można co prawda odblokować przyjmowanie przerwań w obsłudze przerwania, które uznajemy za takie o niskim priorytecie, ale na ogół więcej będzie z tego kłopotu niż pożytku. Podstawa - to dobrze napisana obsługa przerwań.
    W procesorze z jednopoziomowym systemem przerwań przerwanie nie może zawierać jakiegokolwiek oczekiwania (wyjątek - to oczekiwanie o krótkim i deterministycznym czasie, do kilku us, ale tego wyjątku też nie należy nadużywać).

    Myślę, że problem leży w błędnej obsłudze przerwań. Pokaż kod, to znajdziemy błędy.
  • Helpful post
    #4
    tmf
    Moderator of Microcontroller designs
    Dokładniej to nie AVRy, tylko ATMega ma jednopoziomowy sytem przerwań, XMEGA (która też należy do AVR) ma 3-poziomowy system przerwań. ATMegi mają też sztywnie przydzielone priorytety przerwań (o ile jest w ogóle sens mówić tu o priorytetach), XMEGA mają kilka schematów priorytetowania. Tak jak piszą koledzy powyżej można zrobić obsługe nieblokującą przerwania, ale lepiej wykonywać pomiary sprzętowo, przy pomocy ICP. W końcu po to w ATMedze jest.
  • #5
    skyguy
    Level 14  
    Poniżej wrzucam kod odnośnie przerwań. Używam 4:
    1) Od konwersji ADC
    2) Od przyjścia znaku na USART
    3) Od przerwań zewnętrznych
    4) Od przepełnienia timera do update zmieannych

    Po krótce ma on działać tak: jeżeli pojawi się coś na USART to przerwij i sprawdź co to za znak. Zrób odpowiednią funkcję. Jeżeli jest to jeden ze specjalnych znaków to przychodzi ciąg znaków który należy poskładać w jedną całość INT.

    Czyli jeżeli przyjdzie B:
    Atmega wykonuje funkcje R_Batery() gdzie wysyła po USARCIE stan baterii mierzony w ADC w formacie "B123456789"

    Jeżeli przyjdzie X - to jest specjalny znak:
    To atmega czeka na wszystkie znaki jakie przyjdą zapisuje je do "read0"->"read5"
    i w zależnośi jaki był pierwszy znak składa w np: bat_off=(int)(read1-48)*100+(int)(read2-48)*10+(int)(read3-48);

    Code: c
    Log in, to see the code
  • Helpful post
    #6
    BlueDraco
    MCUs specialist
    1. Przerwanie ADC (zapewne w ogóle zbędne) zżera b. dużo czasu na niepotrzebne obliczenia zmiennopozycyjne - moim zdaniem to jest główny błąd w programie.

    2. Bezsensowny switch w obsłudzie odbioru UART.

    3. MyDelay w przerwaniu UART - po co? W przerwaniu się nie czeka.
  • Helpful post
    #7
    tmf
    Moderator of Microcontroller designs
    1. Poza tym zapis EEPROM w przerwaniu to też niedobry pomysł - to kilka ms/zapis. Od tego EEPROM generuje swoje przerwania, żeby zapisy buforować i zapisywać do EEPROM niezależnie. 2. Poza tym mieszanie ISR i SIGNAL czyli starej i nowej obsługi przerwań tez nie jest zalecane.
    3. Wysyłanie znaku przez USART w obsłudze przerwania też może nie być dobrym pomysłem (jeśli jest blokujące).
    4. Funkcje typu MyDelay to katastrofa - raz, że ich używanie w przerwaniu nie powinno mieć miejsca, dwa - AVRlibc już udostępnia funkcje opóźniające (co nie zmienia faktu, że w 90% używanie ich świadczy o źle napisanym programie).
  • #10
    BlueDraco
    MCUs specialist
    Jeśli procedura obsługi przerwanai ma tylko ustawiać znacznik, to znaczy, że nei jest ona w ogóle potrzebna - żeby zostało zgłoszone przerwanie, sprzęt ustawia najpierw jakiś znacznik, i ten znacznik można testować programowo bez potrzeby zgłaszania przerwania.
    Przerwanie, które tylko ustawia znacznik - to fatalna technika programowania.
  • #11
    skyguy
    Level 14  
    Największy priorytet ma dla mnie w kolejności:
    1) Mierzenie długości impulsu z 2 przerwań zewnętrznych
    2) Mierzenie poziomu baterii na ADC
    3) Komunikacja USART
    4) Update/zapis zmiennych do EEPROM


    Zaczynając od organizacji USART:
    1) Wiem już że opóźnienia to nie jest najlepszy pomysł w przerwaniu
    2) Zapis do eeprom - wtedy kiedy będzie na to czas

    Dodam tylko że zapis do eeprom zdarza się bardzo bardzo rzadko można powiedzieć raz na włączenie Atmegi (5h dziennie)

    Wrzućcie jakąś propozycje co do obsługi USART - jak w prawidłowy sposób wymienić dane pomiędzy aplikacją na PC a Atmegą. Wszędzie są przykłady jak skonfigurować ale w dateschit nie ma jak to zorganizować.

    Atmega mierzy poziom baterii i zapytana przez PC wysyła go po USARTcie, ale z PC można wysłać do Atmegi poziomy baterii przy których ma odpowiednio zareagować.

    W tej chwili mam do tego taką ramkę z PC do Atmegi:
    B123456
    Gdzie B-uwaga znak specjalny będzie zapis
    123=1,23V - pierwsza wartość przy której ma zareagować
    456=4,56V przy której druga wartość przy której ma zareagować

    I tak jak wcześniej wspomniałem wszystkie znaki są zapisane do osobnej zmiennej a potem scalone w odpowiednie wartości czyli 1,23 i 4,56.

    W jaki prawidłowy sposób to powinno zostać zrealizowane? Czy takie podejście jest prawidłowe? Nie chodzi mi o kod ale też może być jakiś przykład, bardziej o technikę sposób przesyłania, strategię podejścia.
  • #12
    BlueDraco
    MCUs specialist
    Sugestie:
    - Wyrzuć przerwanie ADC, mierz sobie tę baterię w jakiej wolnej chwili i broń Boże nie używaj zmiennego przecinka do przeliczania odczytu ADC.

    - Całą obsługę logiczną komunikacji wrzuć do pętli głównej, o ile masz taki styl programowania, że masz pętlę główną (akurat w przypadku AVR to rozwiązanie nie jest tak bezsensowne, jak w nowszych procesorach).
    To, czy potrzebujesz przerwania UART zależy od protokołu transmisji po obu stronach - da się go na pewno tak zdefiniować, żebyś nie potrzebował przerwania, o ile każdy będzie grzecznie czekał na przeciwnika.

    Obsługę EEPROM też wrzuć do za przeproszeniem pętli głównej.