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

Atmega 16 - nieprawidłowe działanie przerwań INT0, INT1 przy 16MHz

krzysztofh 08 Kwi 2014 10:51 1983 2
  • #1 13487810
    krzysztofh
    Poziom 29  
    Mam problem z uzyskaniem oczekiwanego działania przerwań INT0 i INT1.
    Procesor to ATMEGA 16 z zewnętrznym taktowaniem 16MHz. PD2, PD3 są skonfigurowane jako wejścia z podciągnięciem do 1.
    W obu przerwaniach jedyną czynnością jest inkrementowanie zmiennych zdefiniowanych jako volatile uint32_t.

    ISR(INT0_vect)
    {
    N_T++;
    }
    ISR(INT1_vect)
    {
    N_F++;
    }

    Przerwania są wyzwalane opadającym zboczem:
    MCUCR |= (1 << ISC01) | (1 << ISC11);
    GICR |= (1 << INT0) | (1 << INT1);

    Ponadto:
    ISR(TIMER1_COMPA_vect) //przerwanie co 100ms
    Odmierzanie 100ms dla wyznaczenia czasu pomiarowego

    ISR(TIMER0_COMP_vect) //przerwanie co 625Hz
    Przerwanie do obsługi wyświetlaczy LED

    Program jest napisany bez użycia „_delay_us() - ów”. Poza tym w czasie odczytu częstotliwości nie zajmuje się innymi czynnościami, poza oczywiście obsługą wyświetlaczy.
    Na PD2 (INT0) podawany jest sygnał „x” o stałej f = 16MHz, podzielony przez 256 przez licznik 74F393, czyli o f=62,5kHz. Na PD3 (INT1) podawany jest sygnał ”y” o zmiennej częstotliwości, podzielony przez 256 przez inny licznik 74F393.
    Ilość impulsów jest zliczana w czasie ok 100ms (odmierzane w przerwaniu). Około, dlatego, że dokładny okres, w którym impulsy są podawane na PD2 i PD3 rozpoczyna się z pierwszym narastającym zboczem sygnału „y” który wystąpi po dodatnim zboczu sygnału rozpoczynającego okres 100ms, a kończy pierwszym dodatnim zboczem sygnału „y” po wystąpieniu opadającego zbocza sygnału wyznaczającego okres pomiarowy 100ms.
    W programie głównym, na razie testowym, niewiele się dzieje i testuję po kolei różne jego fragmenty.
    Teraz odczytuję wartość zmiennych inkrementowanych w przerwaniach. Wartość zmiennej N_T jest poprawna i zmienia się w małym zakresie. W praktyce wartość zmiennej N_T oscyluje wokół wartości ok 6 250. Natomiast zmienna N_F jest zliczana poprawnie mniej więcej do wartości ok 16 500, co odpowiada mniej więcej f = ok 42MHz. Nie dysponuję w tej chwili generatorem o takim zakresie, ale na potrzeby testowania tego przerwania podaję sygnał „y” o częstotliwości ok 10MHz, a sygnał na pin PD3 (INT1) pobieram z licznika 74F393 nie podzielony przez 256, a przez 64 czyli 4 razy mniej, czyli de facto przerwanie INT1 przy tej częstotliwości występuje z częstotliwością ok 165kHz.
    Założenie jest takie że powinienem móc odczytać tą zmienną podając sygnał o f < 100MHz, czyli po podziale ok 390kHz. Układy wejściowe są szybkie aby przesłać sygnał o takiej częstotliwości, ale mam problem, bo przy częstotliwościach wyższych niż wyżej opisałem, procesor nie wyrabia i przestaje obsługiwać przerwanie do multipleksowania wyświetlaczy.
    Czy ma ktoś z Was pomysł na rozwiązanie tego problemu?
  • #2 13488123
    BlueDraco
    Specjalista - Mikrokontrolery
    Zliczaj impulsy timerem w trybie licznika. Nie potrzebujesz dwóch przerwań timera - użyj jednego, np. 800 Hz - co 80 przerwań masz odliczony odcinek 100 ms.
  • #3 13488184
    krzysztofh
    Poziom 29  
    Możesz nieco rozwinąć temat?
    Na początku próbowałem w programie zliczać stany na pinach procka, ale to była zupełna klapa, bo gubił kroki niemiłosiernie.
    Rozumiem, że proponujesz aby licznik sprzętowo zliczał zmiany na określonym pinie.
    Nie bardzo rozumiem "użyj jednego, np. 800 Hz - co 80 przerwań masz odliczony odcinek 100 ms"
    Ja muszę dokładnie ustalić, ile było przepełnień licznika 74S393, które następują co 256 takt częstotliwości mierzonej. Z danej nogi tego licznika pobieram stan i zapamiętuję. Potem te dane są obliczane w programie.

    Obecnie wykorzystuję dwa timery wg konfiguracji:
    Kod: C#
    Zaloguj się, aby zobaczyć kod
REKLAMA