Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Atmega16A - prawdopodobnie błędna obsługa przerwań

10 Lut 2011 13:58 1473 25
  • Poziom 8  
    Witam, pracuję na atmedze16A i wewnętrznym clocku 4Mhz. Próbuję wygenerować przerwanie z częstotliwością 80kHz, które spowoduje negacje jednego z bitów portu B(PORTB 0). Rozumiem, że dzięki takiej operacji wygeneruję sygnał o częstotliwości 40kHz, który pozwoli mi generować ultradźwięki w nadajniku. Napisałem taka obsługę przerwania, ale coś mi nie działa:
    Code:
       TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode 
    
       OCR1A   = 50;
       TCCR1B |= ((1 << CS10));
       TIMSK |= (1 << OCIE1A);


    Code:
    ISR(TIMER1_COMPA_vect)
    
    {

       PORTB ^= (1<<0);

       ilosc++;
    }

    Dodam, że układ wygląda tak:
    Atmega16A - prawdopodobnie błędna obsługa przerwań

    Dziękuję za pomoc w rozwiązaniu problemu[/code]
  • Poziom 27  
    Czy masz sei()?
    Czy masz PORTB 0 jako wyjście zadeklarowane?
  • Poziom 8  
    tak mam,
    Code:
       DDRB |= (1<<0);
    
       PORTB &= ~(1<<0);


    Code:

    int Odbierz()
    {
       ilosc = 0;   
       nadawaj = 1;
       sei();
       
    //wyslanie sygnalu   
       while(ilosc < 70);   


       ilosc = 0;
       nadawaj = 0;
    //wlaczenie odbierania   
       DDRB &= ~(1<<2);
       //odebranie sygnalu
       while(ilosc < 60)
       {
          if(bit_is_set(ACSR,ACO))
             return 1;
       }
       cli();
    //wylaczenie odbierania
       DDRB |= (1<<2);
       PORTB &= ~(1<<2);
       return 0;

    }
  • Poziom 32  
    Dlaczego wszyscy upierają sie na przerwanie od COMPARE i do tego jeszcze A
    Nie lepiej wykorzystac przerwanie od przepełnienia?
    To nawet na 8 bitowy pojdzie a w przerwaniu można dokładnie wyregulowac czestotliwosc wpisując nową wartość do licznika.
  • Poziom 8  
    to podaj rozwiązanie, ponieważ ja nie umiem tego napisać. byłbym wdzięczny
  • Moderator na urlopie...
    wykorzystanie compare to bardzo dobry nawyk
    może odblokuj globalnie system przerwań, a nie tylko w jednej konkretnej funkcji?
  • Poziom 32  
    piotrva napisał:
    wykorzystanie compare to bardzo dobry nawyk
    może odblokuj globalnie system przerwań, a nie tylko w jednej konkretnej funkcji?

    To wytłumacz mi jak to działa bo sie zamuliłem chyba.
    Przerwanie przyjdzie raz na 65536 czyli de facto dziala jak dzielnik przez tą liczbe.
    Gdzie tu w powyższym przykładzie mozliwosc ustawienia żadanej czestotliwości., Gdzyz to samo osiagniemy przy przerwaniu od przepelnienia a COMPARE mozna wykorzystać do innych bardziej wymagających celów.
  • Poziom 8  
    jest problem przy Takiej częstotliwości generować przerwanie o tak dużej częstotliwości. Niewiele rozkazów wykonam pomiędzy każdym przerwaniem, a mój projekt to samochodzik oparty na dwóch silnikach krokowych sterowanych z procesora...
  • Poziom 32  
    To zwiększ do 16Mhz a bedziesz mial do dyspozycjie 3200 taktów na przerwanie o ile sie nie myle a to masa rozkazów.

    Dodano po 5 [minuty]:

    Wszystko jasne sprawdz czy nie masz przebiegu na innej nóżce.
    I skasuj obsługe przerwania oraz zezwalanie na przerwanie bo z jedejstrony ty chcesz sprzetowo generować a z drugiej strony programowo wiec zdecyduj sie.
    Sygnał jak juz poprawnie napiszesz powinien pojawic sie na B1 a nie na B0
  • Poziom 8  
    nie rozumiem co mam zrobić. możesz dogłębniej wytłumaczyć?
  • Poziom 32  
    Ja sie nie znam ale bym wywalil linijke z TIMSK oraz obsługę przerwania CAŁĄ a sygnału szukał na nodze B1 .
  • Poziom 8  
    na nodze B1 zobaczę przebieg TIMERA, ale jak to wykorzystam do nadajnika skoro muszę krótkie paczki wysyłać?
  • Poziom 32  
    No cóż dalej to sobie radź całego programu nie da sie napisać nei wiedząc czego oczekujesz. Ty chyba wiesz prawda?
    Ponieważ umiesz już włączyc nośną 80kHz to prwadopodobnie też dasz radę wyłączyć. Odpowiednie włącz/wyłącz bedziesz mogł nadawać co chcesz nawet paczki polecone.
  • Poziom 8  
    wiem, ale nadal nie wiem czy dobrze generowane jest to przerwanie...
  • Poziom 32  
    A do czego ci to przerwanie skoro sprzetowo otrzymujesz sygnał?
  • Poziom 8  
    hmm musze wygenerować paczkę ultradźwieków czyli sygnału o częstotliwości 40kHz, rozumiem, że dzięki takiemu przerwaniu będę mógł na jednym z bitów portu wygenerować sygnał 101010101... właśnie o takiej częstotliwości. Paczka nie może być długa, bo w przeciwnym wypadku odbiornik zgłupieje i ciągle będzie otrzymywał jakieś ultradźwieki...
  • Poziom 32  
    Oczywiscie te 10101010 to jest sygnał i nie ma sygnał jak rozumiem o f 40kHz
    Jaka długosc (szerokośc) tego sygnału w takim razie.
  • Poziom 8  
    wyliczyłem, że 880us czyli 35 powtórzen przebiegu 10
  • Poziom 32  
    No to teraz rozumiem o co ci chodzi. Zagmatwałes z tym portem B0 pewnie jakbys podesłał schemat to by sie wyjaśniło ale tu standard pytac o program bez schematu co niestety jedno z drugim jest ścisle związane.
    Oczywiscie mozesz liczyc ilosc impulsów i na tej podstawie okreslicz czas trwania impulsu i przerwy i jedyna droga to przerwanie.
  • Poziom 8  
    jakbyś spojrzał dokładnie to schemat jest w pierwszym poście : )

    Dodano po 1 [minuty]:

    teraz wpadłem na pomysł czy nie dałoby sie zrobić tak że puszczam TIMER1 który będzie liczył sobie te 80kHz i do niego podłączyć nadajnik i w razie potrzeby go załączać albo nie i w ten sposób generować paczkę ultradźwięków?
  • Poziom 32  
    Faktycznie jest ale nie odzierciedla tego czego ja sie domyslam co chcesz zrobic.
    Uzywasz B0 a na schemacie nic.

    Dodano po 1 [minuty]:

    Najlepiej to przenies na 8 bitowy, A z portu B0 możesz kluczować tranzystorkiem paczki używając przerwania.

    Dodano po 1 [minuty]:

    ja bym odliczał czasy impulsów w paczka za pomocą innego timera i w odpowiednich momentach wyłączał generacje 40kHz, wtedy nie tracimy portu na kluczowanie.
  • Poziom 27  
    Timer 1 potrafi działać w trybie CTC tak, że przy zauważeniu równej wartości licznika z rejestrem OCRA może sam zmienić ci stan jednej końcówki procka zwanej OCR na przeciwny. Włącz sobie taki tryb - to wtedy będzie ci to działać automatycznie - czyli bez procedury obsługi przerwania , w pełni sprzętowo.

    Aby to zrobić zaprogramuj bit COM1A0 czyli TCCR1A|=(1<<6) a następnie ustaw końcówkę OC1A na wyjście czyli DDR|=(1<<PD5).
    Potem sprzawdź czy na końcówce OC1A czyli PD5 będziesz mieć przebieg.

    No i wtedy też zlikwidować możesz procedurę obsługi przerwania i całę to przerwanie. To bo będzie ci niepotrzebne.
    Wszystko będzie się dziać sprzętowo.

    A odnośnie to Twojego rozwiązania to :
    Zauważ że masz b.małą częstotliwość kwarcu , a chcesz uzyskać dużą częstotliwość przebiegu w przerwaniu. Spróbuj wywalić tę inkrementację Ilosc++ z procedury obsługi przerwania - może ona za długo trwa jeśli jest np long.
    Spróbuj też jak zachowa sie układ gdy włączysz preskaler. Jeśli będzie przebieg przy preskalerze np przez 16 to wiadome będzie że problem jest ze zbyt małą częstotliwością kwarcu.
  • Moderator na urlopie...
    asembler napisał:
    piotrva napisał:
    wykorzystanie compare to bardzo dobry nawyk
    może odblokuj globalnie system przerwań, a nie tylko w jednej konkretnej funkcji?

    To wytłumacz mi jak to działa bo sie zamuliłem chyba.
    Przerwanie przyjdzie raz na 65536 czyli de facto dziala jak dzielnik przez tą liczbe.
    Gdzie tu w powyższym przykładzie mozliwosc ustawienia żadanej czestotliwości., Gdzyz to samo osiagniemy przy przerwaniu od przepelnienia a COMPARE mozna wykorzystać do innych bardziej wymagających celów.

    cóż, dzięki stosowaniu compare można w banalny sposób określić częstotliwość wystąpienia przerwania, bez konieczności ciągłego aktualizowania zawartości licznika przy każdym przerwaniu przepełnienia (overflow)
  • Poziom 32  
    Nie zauważyłem ze on ustawia sprzetowa generacje, gdyz obsługa przerwania sugerowała na realizacje programową. teraz to wszystko jasne.

    Dodano po 2 [minuty]:

    Do konca nie wiadomo jak ma projekt wyglądac wiec trudno sugerowac ostateczne rozwiazanie. A dla samego sprawdzenia to mozna nawet w programie main odpowiednimi opoznieniami wygenerowac dowolny przebieg i nie wiem czy w tym wypadku nie byłaby najlepsza droga choć podniosą sie głosy ze niejedynie słuszna.
  • Poziom 43  
    To taki mały offtop.
    asembler napisał:
    piotrva napisał:
    wykorzystanie compare to bardzo dobry nawyk
    może odblokuj globalnie system przerwań, a nie tylko w jednej konkretnej funkcji?

    To wytłumacz mi jak to działa bo sie zamuliłem chyba.
    Przerwanie przyjdzie raz na 65536 czyli de facto dziala jak dzielnik przez tą liczbe.
    Gdzie tu w powyższym przykładzie mozliwosc ustawienia żadanej czestotliwości.

    No ta możliwość to wpisanie czegoś do rejestru OCR1A?

    asembler napisał:
    Gdzyz to samo osiagniemy przy przerwaniu od przepelnienia a COMPARE mozna wykorzystać do innych bardziej wymagających celów.

    A jakim cudem wykorzystasz compare jeżeli programowo będziesz wpisywał do Timera jakieś swoje wartości?
  • Poziom 32  
    Nie wykorzystam wpisując do liczników dlatego np tez puszczam timer1 wolno a aktualizuje wartosci ocra/b.
    Zresztą te wypowiedzi nieaktualne i mozna miedzy bajki włozyć.