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

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

as_szeroka 03 Maj 2012 19:27 4828 40
  • #1 03 Maj 2012 19:27
    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
    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
    Zaloguj się, aby zobaczyć kod
    Kod: 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
    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.

    0 29
  • Semicon
  • #2 03 Maj 2012 22:32
    janbernat
    Poziom 38  

    Po pierwsze- funkcja obsługi przerwania powinna być poza main().
    Po drugie zmienna licznik powinna być volatile.
    Reszta potem.

    0
  • Semicon
  • #3 04 Maj 2012 15:33
    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
    Zaloguj się, aby zobaczyć kod


    po uwagach dopadłem podstawowy błąd (mea culpa).

    0
  • #4 04 Maj 2012 19:17
    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: C
    Zaloguj się, aby zobaczyć kod

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

    Ale to ostatnie to już kwestia estetyki kodu i osobistych preferencji.

    0
  • #5 04 Maj 2012 20:50
    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
    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ę :)

    0
  • #6 04 Maj 2012 21:59
    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 :( ....

    0
  • #7 04 Maj 2012 23:16
    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
    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
    Zaloguj się, aby zobaczyć kod

    0
  • #8 04 Maj 2012 23:34
    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

    0
  • #9 04 Maj 2012 23:45
    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ą :)

    0
  • #10 04 Maj 2012 23:47
    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).

    0
  • #11 05 Maj 2012 00:22
    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. :)

    0
  • #12 05 Maj 2012 23:27
    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.

    0
  • #14 11 Maj 2012 07:13
    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
    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.

    0
  • #15 11 Maj 2012 08:04
    mirekk36
    Poziom 42  

    To zacznij jak najszybciej używać eclipse, zobaczysz że będzie dużo lepiej ;)

    zresztą zobacz tutaj: Link

    0
  • #16 11 Maj 2012 10:37
    dondu
    Moderator Mikrokontrolery Projektowanie

    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.

    0
  • #17 11 Maj 2012 10:52
    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.

    0
  • #18 11 Maj 2012 11:04
    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.

    0
  • #20 11 Maj 2012 12:42
    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. ;)

    0
  • #21 11 Maj 2012 20:33
    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]

    0
  • #22 11 Maj 2012 21:12
    janbernat
    Poziom 38  

    Taka uwaga- bramka Twojego mosfeta wytrzymuje 24V?
    Ja bym jednak dał diodę stabilizacyjną 15V między bramkę a masę.

    0
  • #23 11 Maj 2012 21:43
    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ł.

    0
  • #24 12 Maj 2012 02:25
    Damian_Max
    Poziom 14  

    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.

    0
  • #25 12 Maj 2012 09:39
    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
    Zaloguj się, aby zobaczyć kod

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

    ale, też LED przyśpiesza ok 1sekundy na 50 sekund

    0
  • #26 12 Maj 2012 10:11
    Damian_Max
    Poziom 14  

    Witam,

    brakuje zezwolenia na przerwanie:

    Code:
    TIMSK |= (1<<OCIE1A);


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

    Code:
    ISR(TIMER1_COMPA_vect);


    Pozdrawiam.

    0
  • #27 12 Maj 2012 12:16
    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
    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).

    0
  • #28 12 Maj 2012 13:06
    Damian_Max
    Poziom 14  

    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:

    Code:
    ISR(TIMER1_COMPA_vect);

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

    Jaką masz różnicę przy 8MHz po 60s?
    Jaką masz różnicę przy 1MHz po 60s?

    0
  • #29 12 Maj 2012 14:57
    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

    0
  • #30 12 Maj 2012 15:31
    Damian_Max
    Poziom 14  

    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.

    0