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

[C][Atmega8] przerwania, PWM, klawiatura

15 Paź 2010 10:00 2561 11
  • Poziom 16  
    Napisałem program do sterowania serwami z wykorzystaniem PWM oraz wszystkim ma sterować klawiatura podpięta tylko do przerwania INT0 (wciśnięcie klawisza na klawiaturze powoduje odpalenie przerwania oraz zmienia stan jednego portu. Poniżej zamieszczam kod.

    Code:
    #include <avr/io.h>
    
    //#include <avr/signal.h>
    #include <avr/interrupt.h>
    #define F_CPU 1000000UL

    void close()
    {   
       TCCR2 = (1<<WGM20)|(0<<WGM21)|(1<<CS22)|(0<<CS21)|(0<<CS20)|(0<<COM20)|(1<<COM21);
       OCR2 = 8;
       for(int j=0; j<36; j++)
       {
        TCNT2 = 0x00;
        for(long int i=0; i<873; i++)
        asm("nop");
       }
       TCCR2 = (1<<WGM20)|(0<<WGM21)|(1<<CS22)|(0<<CS21)|(0<<CS20)|(0<<COM20)|(0<<COM21);
    }

    void open()
    {   
       TCCR2 = (1<<WGM20)|(0<<WGM21)|(1<<CS22)|(0<<CS21)|(0<<CS20)|(0<<COM20)|(1<<COM21);
       OCR2 = 16;
       for(int j=0; j<37; j++)
       {
        TCNT2 = 0x00;
        for(long int i=0; i<886; i++)
        asm("nop");
       }
       TCCR2 = (1<<WGM20)|(0<<WGM21)|(1<<CS22)|(0<<CS21)|(0<<CS20)|(0<<COM20)|(0<<COM21);
    }
    --------------------------- PROBLEM
    SIGNAL (_VECTOR(1))
       {
       if(!(PIND&0x01))
       {close();}
          while(!(PIND & 0x01)) {}
              for(int i=0; i < 1000;i++);
       //if(!(PIND&0x02))
       {open();}
       }

    SIGNAL (_VECTOR(2))
       {
       open();
       }

    int main()
    {
       PORTD =(1<<PD2)|(1<<PD3)|(1<<PD0)|(1<<PD1);
       DDRD = 0x00;

       DDRB = (1<<PB3);
       PORTB = 0x00;
       
       MCUCR = (1<<ISC11)|(0<<ISC10)|(1<<ISC01)|(0<<ISC00);
       GICR = (1<<INT1)|(1<<INT0);

       sei();

       while(1)
       {
          asm("nop");
       }
    }


    Problem tkwi w tym, że w przerwani od INT0 jak wywołuje operacje odrazu po wejściu do przerwania - funkcja open działa dłużej (widać to na serwie - 3,5 obrotu) a funkcja close (uzależniona od przycisku) mimo, że ma podobny czas wykonuje się tylko chwilkę (1,25 obrotu) :( jak daje dwa razy wywołanie operacje close w funkcji if to wykonują się w sumie 3,2 obrotu serwa :/
    Przyciski reagują na zbocze opadające.

    Różnica w funkcjach to szczegół dopasowałem to do układu wykonawczego.

    nie mam pojęcia o co chodzi :/ jakieś pomysły ?

    PS.
    Program jest dedykowany pod konkretne przerobione serwa, oraz układ w jakim mają działać, nastawy "i" i "j" to pomocnicze by wygenerować różne impulsy to działa, bo śmiga na dwóch przerwaniach jedno close a drugie open.

    pozdrawiam
  • IGE-XAO
  • Poziom 42  
    No a jak ma być dobrze? jeśli w taki karkołomny sposób robisz obsługę klawiszy. U ciebie cały program mieści się w przerwaniu. W zasadzie NICZYM się to nie różni od tego gdybyś całość umieścił w pętli głównej i nie używał żadnego przerwania.
  • IGE-XAO
  • Poziom 16  
    chce mieć wszystko w przerwaniach ponieważ układ będzie "spał" jak nie będzie miał sygnału z klawiatury a nie "młócił" ciągle sprawdzanie portów. I po to chcę wszystko w przerwania władować. Wiem że można to zrobić w głównej pętli ale to mi nie jest potrzebne.
    A po za tym robienie obsługi i wszelkich działań w głównej pętli według mnie jest mało praktyczne i leniwe, po to są przerwania i inne rzeczy zawarte w uP by z nich korzystać.

    chce by się odpaliło przerwanie a w nim było sprawdzenie jaki klawisz - port był aktywny i zostały podjęte odpowiednie działania.

    Ps. to jest tylko fragment kodu całego układu.
  • Poziom 35  
    To ustaw jeden z timerów na przerwanie co 10ms.
    W przerwaniu sprawdzaj stan portu pod który masz wpiętą klawiaturę. Jak jest zmiana to ustaw odpowiednią flagę.
    W pętli głównej sprawdzaj czy ustawiona jest flaga klawiszy.
    Po obsłudze funkcji dla danego klawisza zeruj flagę.
  • Poziom 16  
    po co kładzie się procka spać ? po by zmniejszyć pobór mocy tak przynajmniej ja to rozumiem.

    Samuraj nie widzę w tym sensu jak bym kład procka spać i co 10ms go budził :/ to prościej by było cały program do whlie(1) władować i niech się muli :/ ale mam ciągle procka włączonego i pobiera więcej prądu niż w uśpieniu.

    cały układ: procek, serwa i inne elementy będą jechać na akumulatorach, klawiatura będzie używana czasem tylko jak będzie potrzeba wykonania operacji, dlatego potrzebne są same przerwania, w których będą wykonywane sprawdzenia stany portów. Każdy klawisz wywołuje zmianę stanu na wejściu INT0 oraz na swoim porcie, do którego jest przypisany.

    problem nie jest typu jak to zrobić tylko gdzie jest błąd bo idea według mnie jest ok.
  • Specjalista - Mikrokontrolery
    Primo, budzenie procka co 10ms na mikrosekundę potrzebną do sprawdzenia klawiszy nie zwiększy jakoś drastycznie poboru prądu.
    Po drugie, mam wrażenie, że przy lakonicznym i chaotycznym opisie jaki dałeś i bez schematu, nikt nie ma pojęcia co chcesz uzyskać i właściwie co jest, wg Ciebie, nie tak. Przynajmniej ja nie mam pojęcia...
    Po trzecie - mechaniczne styki są niestabilne (tzw. drgania styków) - natychmiastowe czytanie stanu klawisza w przerwaniu wywołanym zmianą stanu tegoż klawisza niekoniecznie zwróci stan, który wywołał przerwanie.
    Po czwarte, taka pętla opóźniająca
    Code:

    for(int i=0; i < 1000;i++);

    nie zadziała przy włączonej optymalizacji. Kompilator ją zignoruje.
  • Poziom 16  
    szelus przeczytaj dokładnie o co chodzi układ działa ale czasy się nie zgadzają :/ opisałem dokładnie wadliwe czasy pracy

    optymalizacja jest wyłączona a ta pętla wytłumia drgania związane z przyciskiem, w przerwaniach nie mogę stosować makra _delay_ms(), a po za tym jedna iteracja wykonuje się w 4us jak dobrze pamiętam wiec spokojnie tak szybko nie klikam by procek tego nie wyłapał :/ - nie o to chodzi

    schemat proszę, pominąłem zasilanie układu itp użyłem bramek 74HC08 (schemat ideowy tłumaczący zasadę działania i podpięcia się do procka)
    [C][Atmega8] przerwania, PWM, klawiatura

    schemat jest ok procek reaguje na klawisze ale źle interpretuje funkcje i o to chodzi.

    chcę uzyskać układ procka, serw innych elementów zewnętrznych spiętych ze sobą zasilanych z akumulatorków. Procek ma spać i nie katować akumulatorków i tak jak serwa się włączą będą obciążać akumulatory. Procek śpi i czeka na wciśnięcie klawisza. Jak jakiś klawisz się włączy następuje wywołanie przerwania, które obudzi procek a on sprawdzi jaki klawisz został wciśnięty i wykona mu przypisaną akcje. Po wykonaniu wraca do głównej pętli i idzie spać dalej. Może się zdarzyć że np. dziennie tylko może 5 razy zostanie wciśnięty przycisk, po to są te przerwania. Układ działa ale nie tak jak powinien a mianowicie funkcje open i close trwają tyle samo czasu, i dokonują włączenia serw, serwa powinny robić 3,5 obrotu, Przerwanie INT1 je robi a przerwanie od INT0 tam gdzie sprawdza klawisz i wykonuje się tylko te 1,2 obrotu !! pytanie czemu ??
  • Poziom 42  
    Ty się pytasz jak rozwiązać jakiś problem ??? czy przekonujesz wszystkich, że powinno się w tak dramtyczny sposób pisać program ??? i jeszcze do tego żeby ktoś wymyślał ci jak taki program naprawić stosując twoje jeszcze bardziej dramatyczne sugestie??? No masakra ;) .... Zastanów się przede wszystkim po co założyłeś ten wątek żeby dopytać jak coś zrobić czy komuś wytłumaczyć swoje teorie?
  • Specjalista - Mikrokontrolery
    Skoro wszystko wiesz lepiej, to po co w ogóle pytałeś na forum?

    Prawda jest taka, że w przerwaniach nie powinno być NIC poza ustawieniem flagi (przerwania w zasadzie jedynie budzą układ), a w pętli głównej obsługa flag ustawionych w przerwaniu, a po skończonej obsłudze (jeśli zrobiono wszystko co było do zrobienia) usypiasz układ. Ale tą poradę też moszesz olać - jest głupia, a Ty wiesz lepiej co i jak zrobić.

    Code:
    while (1)
    
    {
    if (flaga1 || flaga2 || flaga3)
    {
    if (flaga1)
    {
    flaga1 = 0;
    // obsluga
    }
    if (flaga2)
    {
    flaga2 = 0;
    // obsluga
    }
    if (flaga3)
    {
    flaga3 = 0;
    // obsluga
    }
    }
    else
    sleep();
    }


    4\/3!!
  • Poziom 16  
    Pytanie stawiane było czemu źle działa a nie na zasadzie jak to zrobić. Odpowiedz w stylu "ładuj wszystko do while i będzie działać" to sorry wiem, że pójdzie ale nie o taką odpowiedz chodziło. A najlepiej jechać po innych zwłaszcza po tych co się uczą.

    Freddie Chopin dzięki jakiś konkret co do przerwań, powiedz mi jeszcze czy będę mógł modyfikować wypełnienie w przerwaniu czy tego też nie mogę wrzucać tam ? oraz te słowo flaga_ to znaczy jakaś zmienna ustawiana w przerwaniu a w while będzie interpretowana i potem kasowana. Dobrze to zrozumiałem?
  • Pomocny post
    Specjalista - Mikrokontrolery
    ppawel12 napisał:
    Pytanie stawiane było czemu źle działa

    Bo jest źle napisane.

    Cytat:
    A najlepiej jechać po innych zwłaszcza po tych co się uczą.

    Po takich co się uczą nikt nie jeździ. Po takich którzy "chcą" odpowiedzi, ale wiedzą lepiej od odpowiadających - już tak.

    Cytat:
    Freddie Chopin dzięki jakiś konkret co do przerwań, powiedz mi jeszcze czy będę mógł modyfikować wypełnienie w przerwaniu czy tego też nie mogę wrzucać tam ?

    Zależy... Nie ma przecież żadnej recepty na wszystko, a "modyfikowanie wypełnienia" może w sumie znaczyć wszystko. Lepiej jednak ograniczyć się do ustawiania flagi typu "zwiększ wypełnienie" i zinterpretowania jej w main, chyba że operacja ta jest krótka i treściwa (nie koliduje z innymi, nie wymaga czekania, itp.) to można zrobić ją tylko w przerwaniu.

    Cytat:
    oraz te słowo flaga_ to znaczy jakaś zmienna ustawiana w przerwaniu a w while będzie interpretowana i potem kasowana. Dobrze to zrozumiałem?

    Dobrze.

    4\/3!!
  • Poziom 16  
    ok to jakoś sobie poradzę z tym co mi napisał Freddie Chopin, bo jakiś konkret się pokazał jeden :/

    W przerwaniu chodzi o to chyba by zawiesić obecnie wykonującą się instrukcje na rzecz innej o wyższym priorytecie.

    Cytat:
    W zasadzie NICZYM się to nie różni od tego gdybyś całość umieścił w pętli głównej i nie używał żadnego przerwania.

    Pytałem się o te przerwanie bo chciałem je wykorzystać w programie (dałem tylko dwa klawisze, a jak by było ich z 10 to co też do while) ale widać panuje zasada i przekonanie po co komplikować sprawę ładuj wszystko do głównej pętli i koniec :/ to po co są inne peryferia :/ po co timery i PWM prościej pisać _delay_ms() :/ i jakoś zadziała :/

    Cytat:
    Po takich co się uczą nikt nie jeździ. Po takich którzy "chcą" odpowiedzi, ale wiedzą lepiej od odpowiadających - już tak.

    tak chcę odpowiedzi co jest źle, a nie odpowiedzi w stylu jest źle napisany - bo może jest gdzieś błąd w kodzie i tego nie zaprzeczam, albo ładuj do while i jakoś to będzie :/ takie odpowiedzi nie rozwiążą mojego problemu

    nikogo do niczego nie przekonuje poproszono o schemat to dałem schemat o wyjaśnienie to wyjaśniłem bardziej.

    Dodano po 23 [minuty]:

    już prztetestowałem sprawę z flagami
    Freddie Chopin wielkie dzięki za drobne objaśnienie i wykorzystałem flagi tak jak napisałeś układ działa na przerwaniach tak jak chciałem :)

    dzięki pozdrawiam