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

Atmega8 timer i przerwanie INT1 - jak wstawić do programu?

as_szeroka 03 Maj 2012 19:27 5617 40
  • #1 10857002
    as_szeroka
    Poziom 13  
    Na początek witam forumowiczów.

    Jako że właśnie zacząłem z mikro kontrolerami (Atmega8), pojawiło się sporo niewiadomych (dla tych wtajemniczonych pewnie śmiesznych);
    staram się napisać (a właściwie nauczyć jak to napisać), tak żeby zagrało jak przewiduję.
    Mianowicie
    Chodzi o sterowanie przekaźnika (na PC0) wraz z LED (na PD2), z tym że przekaźnik ma się załączać na określony czas (ok 200ms) - z tym sobie poradziłem, oto kod; (fuse bity, kontrolowanie stanów wejść/wyjść już poznałem)

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


    Problem polega na wstawieniu w w/w kod programu funkcję która odmierza czas działania pracy przekaźnika (np. układ pracuje 1 minutę (max 10min - w zależności od ustawień DP1 "dipswitcha" ale to inny temat - i w trakcie może się rozwiązać) i czeka na pojawienie się stanu niskiego na INT1 w celu ponownego odliczania czasu pracy przekaźnika)
    po przeglądnięciu wielu stron/opisów/przykładów nadal nie rozumiem jak zastosować timer i przerwanie INT1.
    Proszę o sugestie.

    Napewno pomocny będzie mały schemat do wglądu
    Atmega8 timer i przerwanie INT1 - jak wstawić do programu?


    Proszę pamiętać o używaniu znaczników syntax. Opcja Listing kodu. Proszę to poprawić! - arnoldziq
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Mam nadzieję że o to chodziło. Dziękuję za uwagę.

    Po próbach z timerem i przerwaniem INT1 wyszło tak;
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    ale.. teraz już wogóle nie rozumiem co i jak.
    Proszę o podpowiedzi...

    Dodam jeszcze że sterowanie wejściami wykonane jest na transoptorach z wyjściem tranzystorowym do GND.
    Załączam schematy (będzie jasne)
    Atmega8 timer i przerwanie INT1 - jak wstawić do programu?
    i o ile z elektroniką radzę sobie bez problemu, o tyle z mikrokontrolerem a właściwie programem nie bardzo.
  • #2 10857846
    janbernat
    Poziom 38  
    Po pierwsze- funkcja obsługi przerwania powinna być poza main().
    Po drugie zmienna licznik powinna być volatile.
    Reszta potem.
  • #3 10859653
    as_szeroka
    Poziom 13  
    Dziękuję wszystkim za sugestie/podpowiedzi. Ale widzę, że to jest "głębszy" temat niż mi się wydawało.
    Na razie wstrzymam się od pisania "głupich" pytań, ale nie oznacza to, że przerwałem/poddałem się przy pracy nad tym programem.
    Wręcz przeciwnie, nadal staram się zrozumieć temat z materiałów wyszukanych w sieci.. a jest tego naprawdę mnóstwo (tylko, że nic z tego nie rozumiem) :)
    No cóż.. nie każdy od razu "zaskoczy".
    Poczytam i odezwę się.. (obecnie "studiuję" kurs AVR z pewnej strony której nie chcę robić kryptoreklamy)

    No i... po kolei...
    pierwsza sprawa przerwanie, no i ... Poniżej listing który wypociłem :) do którego zmierzam wstawić timer, który odmierzy czas działania przerwania i wróci do oczekiwania na
    nowy sygnał z wejścia INT1, żeby znów zacząć odliczać, itd..
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    po uwagach dopadłem podstawowy błąd (mea culpa).
  • #4 10860425
    McMonster
    Poziom 32  
    EDIT: Tfu, ślepy jestem. :P Trochę niekonsekwentnie stosujesz wcięcia i nowe linie, zmniejsza to trochę czytelność kodu.

    Zamień też SIGNAL na ISR oraz nazwy przerwań w tych blokach (bierzesz nazwę przerwania z kolumny "Source" tabelki przerwań z karty katalogowej układu z dopisanym _vect).

    Dodatkowo możesz sobie trochę ułatwić życie zamieniając długie ciągi w rodzaju
    Kod: text
    Zaloguj się, aby zobaczyć kod

    na
    Kod: text
    Zaloguj się, aby zobaczyć kod

    Ale to ostatnie to już kwestia estetyki kodu i osobistych preferencji.
  • #5 10860827
    as_szeroka
    Poziom 13  
    Chyba o to chodziło.
    Faktycznie tak to ma działać (instrukcja). Wielkie dziękuję.
    A co do wyglądu, hmm.. trochę poprawiłem, ale tamto było bardziej czytelne (dla mnie) :), nieistotne, już sobie radzę pomału w treści
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Teraz pora na uruchomienie timera (na razie z dowolnym odmierzanym czasem), który po upływie odmierzanego czasu, przerwie pracę przekaźnika i wróci do oczekiwania na sygnał z przerwania INT1.
    To teraz chyba zagmatwałem trochę :)
  • #6 10861186
    mirekk36
    Poziom 42  
    Ale spójrz - zrobiłeś sobie niechcąco mega masakrę :( wstawiłeś nieskończoną pętlę while(1) do przerwania i masz pp tzw ptakach. Pętla główna programu już ci się nigdy nie wykona nie mówiąc już o innych przerwaniach. Niestety kompletnie nie tędy droga....

    taka mała wskazówka - to co masz teraz w tym kodzie powyżej w tej pętli while(1) - przenieś do pętli głównej programu i to od razu - i zapamiętaj też sobie że w procedurach obsługi przerwań nie wolno też używać tych _delay'ów :( ....
  • #7 10861550
    as_szeroka
    Poziom 13  
    Hmm...
    No właśnie - odnośnie tej pętli while
    wydaje mi się że powinno wyglądać tak;
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    ale z tym był problem i nie chciał się program skompilować (nie wiem, może źle ale wstawiłem w "()" 1).
    Teraz wiem, że źle. poprawione i ten sam problem (zakomentowałem na razie).

    No i po zmianie nie bardzo wiem co dalej...
    program po wykryciu zmiany stanu na INT1 przechodzi do obsługi przerwania, i dotąd ok, ale znów wraca do pętli (jakoś kręcę się w kółko - jak i czym z tego wyjść? (jakiś warunek?)
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #8 10861612
    mirekk36
    Poziom 42  
    nie nie nie - pętla nieskończona to właśnie while(1) ;) a nie while() - to się nie ma prawa skompilować

    ale niestety na razie w ogóle nie kojarzysz podstaw - jeśli chodzi o konstrukcję programu a w szczególności tego jak działają pętle....

    teraz dałeś pętlę główną nieskończoną while(1) ....

    a potem jakąś wyrwaną z rzeczywistości dalszą część kodu :( .... oj tak nie może być - ale - hmmm to ciężko tak w 2 słowach wyjaśnić - musisz poczytać o pętlach przede wszystkim, no i o samej konstrukcji programu - chociaż main.c
  • #9 10861653
    as_szeroka
    Poziom 13  
    No to naprawdę nie rozumiem tego, a szkoda :(
    No cóż.. i tak nie podaruję/poddam się.
    Dziękuję z uwagi - słuszne zresztą :)
  • #10 10861659
    McMonster
    Poziom 32  
    Najlepiej narysuj sobie na schemacie blokowym, co chcesz uzyskać, będzie Ci o wiele łatwiej na tej podstawie napisać poprawny kod. Gdybyś się zastanawiał nad tym, jak na schemacie narysować przerwanie, to narysuj jego zawartość jako oddzielny fragment schematu i powiedz sobie "to może się uruchomić w dowolnej chwili po sei()".

    Jeszcze jedna drobna uwaga, #define F_CPU 12000000UL zwykle nie wpisuje się bezpośrednio w kodzie, tylko w ustawieniach projektu (zakładając, że używasz np. Eclipse).
  • #11 10861753
    as_szeroka
    Poziom 13  
    Więc - co chcę uzyskać, można opisać tak;
    układ ma po podaniu zasilania;
    1. zaświecić LED na wyjściu PD2 (sygnalizując oczekiwanie na sygnał z INT1.
    2. po podaniu (zmiany stanu) na wejściu INT1, układ ma pracować w określonym czasie (ustawianym z pomocą przełączników na porcie B) i powrócić do pkt.1
    to tak w super skrócie, ale...
    w czasie pracy za pomocą przycisku podłączonego do PC1 ma sterować przekaźnikiem podłączonym na PC0 (z tym, że przekaźnik nie pracuje tak jak styk).
    Czas uruchomienia przekaźnika to ok.100-200ms.
    To tak ogólnie.

    Co do F_CPU - pracuję na AVR Studio (piszę program) i AVRDude z USBasp (programuję zaprojektowany układ)
    Jak coś więcej to na PW.

    Co do programu (poziomu wiedzy) - fakt prawie wcale, ale własnie zacząłem pierwszy projekt coś ponad tydzień temu od zera. Więc tak to wygląda.
    Elektronikę już mam gotową; (o tym mam wiele większe pojęcie), gorzej z uruchomieniem, a właściwie zaprogramowaniem tego.
    Ale skoro już tyle pracy w to włożyłem więc nie ustąpię.
    A będzie to napewno podstawa do rozwinięcia się trochę i zdobycia nowych doświadczeń, a może i wykonania większej ilości podbnych kontrolerów do sterowania urządzeniami w moim domu. :)
  • #12 10864980
    as_szeroka
    Poziom 13  
    No cóż.. może faktycznie nie jest nikt w stanie mi pomóc.
    Zamierzam zaopatrzyć się w lekturę.
    Na uwadze mam Mikrokontrolery AVR p. M.Kardaś.
    A co do programu, doszedłem jak w pętlach na zmiennych to wykonać, nie wykorzystując przerwania... i na tym stanąłem.
    Odezwę się jak się posunę do przodu...
    Dziękuję wszystkim za sugestie.
  • #13 10865455
    drzasiek
    Specjalista CNC
    Zajrzyj tu:
    http://mikrokontrolery.blogspot.com
    Albo poszukaj, pogoogluj, kursów avr jest całe mnóstwo.
  • #14 10883492
    as_szeroka
    Poziom 13  
    Witam ponownie.
    Pomimo iż posiadam już lekturkę, siedzę nad Timer'em1 w trybie licznika już 2 dni nie bardzo nadal wiem co i jak... nie wspomnę, że z trybem CTC też próbowałem.
    Mianowicie;
    nie wiem dlaczego, nie mogę osiągnąć odmierzania równo 1 sekundy w zmianie stanu LED, gdzie robię błąd ?
    Oto kod;
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Led wyprzedza zauważalnie w stosunku do 1 sekundy... Co jest źle?

    P.S.
    mikrokontroler Atmega8, wewn 8MHz => (mkAVR Calculator)

    Dodano po 9 [minuty]:

    Cytat:
    Jeszcze jedna drobna uwaga, #define F_CPU 12000000UL zwykle nie wpisuje się bezpośrednio w kodzie, tylko w ustawieniach projektu (zakładając, że używasz np. Eclipse).

    Dobra uwaga, doczytałem już w czym rzecz. Dziekuję.
    A poza tematem trochę to używam AVRStudio.
  • #16 10883854
    dondu
    Moderator na urlopie...
    as_szeroka napisał:
    Pomimo iż posiadam już lekturkę, siedzę nad Timer'em1 w trybie licznika już 2 dni nie bardzo nadal wiem co i jak... nie wspomnę, że z trybem CTC też próbowałem.

    Zrób "po bożemu":
    - ustaw tryb CTC
    - ustaw OCR1A na 31250 (dla zegara 8MHz)
    - zmień wektor przerwania na TIMER1_COMPA_vect
    - wyrzuć z przerwania ustawianie TCNT1 i zostaw tylko PORTD ^= (1 << PD2);

    Tak ustawiony licznik + PORTD ^= (1 << PD2) będą zmieniać stan diody na przeciwny z częstotliwością 1Hz.

    A zegar mam nadzieję ustawiasz w opcjach projektu AVR Studio w taki sposób?

    Gdyś nadal miał problem, wstaw zmieniony kod.
  • #17 10883892
    as_szeroka
    Poziom 13  
    Wiec sprobuje tak jak radzicie z Eclipse. Tym bardziej ze mam wraz z otrzymana lektura i to z poradnikiem video. Ale to jak wroce z pracy ;) napewno napisze o postepach. Do admina - brak pl czcionek z powodu pisania na telefonie.
  • #18 10883917
    mirekk36
    Poziom 42  
    as_szeroka napisał:
    Wiec sprobuje tak jak radzicie z Eclipse. Tym bardziej ze mam wraz z otrzymana lektura i to z poradnikiem video.


    A skoro masz taką lekturę to na pewno masz dokładnie wyjaśnione jak korzystać z CTC nie mówiąc już o gotowych przykładowych kodach pod Eclipse właśnie na dołączonej DVD ;) .... i te lekcje video - właśnie właśnie - koniecznie obejrzyj i zacznij wdrażać w życie.
  • #20 10884155
    McMonster
    Poziom 32  
    dondu napisał:
    as_szeroka napisał:
    Wiec sprobuje tak jak radzicie z Eclipse.

    Eclipse choć jest OK, to nie ma nic wspólnego z Twoim problemem.
    To tak jakbyś zmienił jeden młotek na drugi :)


    Ale w tym wypadku sięgając na oślep do skrzynki z narzędziami może ten drugi młotek tak chwycić, że wreszcie zacznie wbijać gwoździe głowicą, a nie trzonkiem. ;)
  • #21 10885745
    as_szeroka
    Poziom 13  
    To ze nie ma zwiazku Eclipse z moim problemem to raczej jest oczywiste. Zsstosuje sie do wczesniejszych rad forumowiczow. I napisze o efektach.[/quote]
  • #22 10885924
    janbernat
    Poziom 38  
    Taka uwaga- bramka Twojego mosfeta wytrzymuje 24V?
    Ja bym jednak dał diodę stabilizacyjną 15V między bramkę a masę.
  • #23 10886049
    as_szeroka
    Poziom 13  
    Jak na razie nie miałem w tym układzie problemów z mosfetem. Ale nie twierdzę, że po dłuższym czasie będzie taka potrzeba zmiany. Na razie nie planuję z powodu już gotowych płytek PCB, na których zamontowane są wszystkie potrzebne podzespoły.
    Jedynie jak na razie jest niewielka temperatura stabilizatora 5V, ale to wiem od czego (nie jest to obciążenie, bo układ w stanie pracy pobiera z 24V 120mA.

    Może wrócę do tematu w innym już dziale bo nie o tym temat był.
  • #24 10886682
    Damian_Max
    Poziom 17  
    Witam,

    ja na początek zareklamuję kolegę _ImPuLs_ z elektrody i jego portal.
    Mnie osobiście przy programowaniu AVR-ków jest przydatny.

    Link główny to:
    http://impuls.elektroda.eu/joomla/

    Kolejne linki to do rejestrów ATMega8 i ich opisów:
    REJESTRY ; OPISY

    Na stronie jest naprawdę bardzo wiele fajnych rzeczy.

    Pozdrawiam Damian.
  • #25 10886937
    as_szeroka
    Poziom 13  
    Cytat:
    Zrób "po bożemu":
    - ustaw tryb CTC
    - ustaw OCR1A na 31250 (dla zegara 8MHz)
    - zmień wektor przerwania na TIMER1_COMPA_vect
    - wyrzuć z przerwania ustawianie TCNT1 i zostaw tylko PORTD ^= (1 << PD2);

    Tak ustawiony licznik + PORTD ^= (1 << PD2) będą zmieniać stan diody na przeciwny z częstotliwością 1Hz.

    A zegar mam nadzieję ustawiasz w opcjach projektu AVR Studio w taki sposób?

    Gdyś nadal miał problem, wstaw zmieniony kod.


    Zrobiłem tak jak przedstawił "dondu" (wcześniej też tak próbowałem) i teraz nie ma wcale efektu (zapalania/włączania) LED, i nie widzę gdzie jest problem. Port działa bez zarzutu, ponieważ wstawienie w kod PORTD |=_BV(PD2) załącza LED, do pracy to zakomentowałem (led działa i port też);
    a oto kod;
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    ale już w ten sposób działa; (tylko że nie o to chodzi);
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    ale, też LED przyśpiesza ok 1sekundy na 50 sekund
  • #27 10887074
    as_szeroka
    Poziom 13  
    Dzięki wielkie. Fakt - zgubiłem to w trakcie.
    Tylko, nadal przerabiam temat i ustawienia, żeby otrzymać 1s. Bo nadal wyprzedza LED :P


    Ale naprzykład;
    Zmieniłem fusebity na 1MHz (zegar wewn), przerobiłem kod (prescaler) i o dziwo, mam 1 sekundę na LED (przez minutę żadnej różnicy), więc co jest nie tak przy 8Mhz?
    zmieniony kod;
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    oczywiście w ustawieniach projektu też zmienione na 1MHz (tym razem już Eclipse)

    Dodano po 48 [minuty]:

    Damian_Max napisał:
    Osobiście albo bym przesuną funkcję przerwania nad funkcję main, albo ja zadeklarował:


    Poprawiłem umiejscowienie, ale z deklaracją funkcji na obecną chwilę się wstrzymam (nie ogarnę tego wszystkiego naraz), nie twierdzę że nie spróbuję tego.

    Dodano po 54 [minuty]:

    Po próbach z kilkoma ustawieniami w MHz pozostaję (na razie) przy 8MHz/wewn.
    Pomimo rozbieżności do faktycznego czasu, nie jest to w tej chwili aż tak istotne.
    Założeniem dalszym jest (nad którym pracuję), uzyskać efekt żeby;
    Za pomocą przerwania INT1 załączać pracę (miganie) LED przez określony czas (np. 1 minuta) i powrót do oczekiwania na następny sygnał z przerwania INT1.
    Z tym, że ponowny sygnał z przerwania INT1 w czasie pracy LED ma nie powodować ponownego odliczania czasu (dopiero po upływie poprzedniego).
  • #28 10887530
    Damian_Max
    Poziom 17  
    Nie jestem pewien, ale może się rozchodzić o różną częstotliwość względem napięcia zasilania. Mam na myśli że jak ustawisz 8MHz to w zależności od Vcc i temperatury możesz mieć np: 3% mniej czyli ~7,75MHz, zaznaczone jest to w dokumentacji na wykresach od strony ~275. Mogło by to powodować kilka sekund różnicy na minucie.

    Deklaracja to tylko ta linijka:
    ISR(TIMER1_COMPA_vect);

    A Całą funkcję umieszczasz pod main:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Jaką masz różnicę przy 8MHz po 60s?
    Jaką masz różnicę przy 1MHz po 60s?
  • #29 10888002
    as_szeroka
    Poziom 13  
    Co do kwestii zasilania, to mam na uC stałe 4,98V zmienia się czasami na 4,97V, co do temperatury to możliwie stała (pokojowa) i niezmieniona w czasie testów z zegarem 1-8MHz, przy 1MHz mam idealnie ze stoperem, jak ustawię 8MHz i oczywiście projekt i kod to różnica jest ok 1 sekundy na 50 sekund na stoperze. Według LED przy 50 sekundach (stoper), LED ma już 51 mignięć. Możliwe że się tak faktycznie rozbiega, no cóż...
    Ale to już zostawiam, ponieważ nie potrzebuję tak naprawdę na ten projekt aż takiej dokładności (nie jest to zegarek) :P
  • #30 10888113
    Damian_Max
    Poziom 17  
    To można tłumaczyć niedokładnością wewnętrznego kwarcu, temperaturą, napięciem zasilania.. .
    51/50 ~ 2% błędu.
    możesz zmienić OCR1A z 31250 na 31875, powinno pomóc.
REKLAMA