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

on timer odmierzanie czasu

Sław1980 01 Maj 2009 14:58 4050 17
  • #1 01 Maj 2009 14:58
    Sław1980
    Poziom 17  

    Hej!
    Czy ktoś wie jak wykorzystać timer atmegi 8, który w danym momencie programu zacznie odmierzać czas powiedzmy 3minuty (bez wpływu na program główny) i po upływie tego czasu skoczy do jakiegoś podprogramu?
    Szukam i szukam w necie i próbuję i nic z tego. Wydaje mi się, że można wykorzystać w Bascomie polecenie ON TIMER (liczba sekund) GOSUB (procedura do zrobienia) ale nie potrafię tego uruchomić.
    Proszę o pomoc
    Z góry dzieki

    0 17
  • #3 01 Maj 2009 15:49
    dawid512
    Poziom 32  

    Tyle że kolega chciał w Bascomie :). Polecam help do bascoma. Konfigurujesz timer, uruchamiasz go i gdy zliczy pewną ilość impulsów wywołuje przerwanie.

    0
  • #5 01 Maj 2009 17:24
    dawid512
    Poziom 32  

    Code:
    Config Timer0 = Timer , Prescale = 64
    
    On Timer0 Odmierz_1s                                        'podprogram wykonywany podczas wystapienia przerwania
    Dim Licz_8ms As Byte                                        'deklaracja zmiennej

    Enable Interrupts                                           'aktywacja globalnego systemu przerwan

    Enable Timer0                                               'aktywacja timera0

    Counter0 = 131                                              'wpisanie wartosci początkowej do timera0

    Dim Sek As Byte                                             'deklaracja zmienna zawierajaca wartosc sekund oraz jej wartosc poczatkowa



    ......


    '*********** podprogram wykonywany w czasie przerwania ********************************
    Odmierz_1s:

    Counter0 = 131

    Incr Licz_8ms

    If Licz_8ms = 125 Then

    Licz_8ms = 0

    Incr Sek

    End If

    Return

    0
  • #6 01 Maj 2009 18:02
    emarcus
    Poziom 35  

    Beeker napisał:
    A czy mógłbym prosić o jakiś konkretny przykład? Albo poprawić ten:

    Config Timer0 = Timer , Prescale = 1024
    On Timer(15) Gosub procedura 'czekaj 15sec.
    Timer On
    Do
    Loop
    End
    Procedura:
    Cls
    Lcd "ok"
    Waitms 500
    Return


    Nie wiele tu mozna poprawic bo od poczatku do konca masz bledny koncept pracy z timerami.
    Po pierwsze: w konfiguracji wartosc 'Prescale' dobierasz w zaleznosci od taktowania processora w ten sposob aby okreslone interwaly casowe byly rownymi (bez reszty) podzielnikami, ktorymi bedziemy operowac w prostych rachunkach.
    Po drugie: brak informacji/impulsu kiedy ten okreslony przedzial ma byc liczony. Mimo ze timer/counter pracuje niezaleznie od programu, to jednak w twoim pytaniu moment startu 'odliczania' przedzialu czasowego (3 min) powinien byc generowany przez jakis sygnal/zdarzenie w programie, wtedy po prostu zerujesz timer, ktory liczy impulsy od momentu jego konfiguracji i zeruje sie sam ale tylko w momencie przepelnienia, wystawiajac na moment flage ze jest pelny. Ta flaga jest twoim "ON TIMER".
    Po trzecie: "ON TIMER(15)" nie jest to zrozumiala dyrektywa dla Bascom
    U ciebie ew. powinno byc 'On Timer0 procedura' - (skok do etykiety 'procedura')
    Po czwarte: 'procedura' powinna zawierac proces naliczania tych powiedzmy 15 sec, a dopiero po tym (sprawdzenie warunku: jezeli uplynelo 15sec) display "OK" , lub cokolwiek innego do zrobienia.

    popatrz tu:
    http://www.atmel.com/dyn/resources/prod_documents/doc2505.pdf


    e marcus

    0
  • #7 01 Maj 2009 19:24
    Sław1980
    Poziom 17  

    No właśnie nie mogę skumać zasady działania timerów. W programie który napisał "dawid512" odmierzana jest 1s co zrobić żeby odmierzane było 180s a program główny działał normalnie, może counter0=counter0*(jakaś wartość) albo wykorzystać polecenie LOAD?? W moim programie chodzi mi tylko o wygenerowanie na wyświetlaczu napisu co 180Sekund Nic więcej. Skoro timery można wyłączyć i włączyć można to zarobić funkcją Timer on, Timer off w danym miejscu programu głównego?

    0
  • #8 01 Maj 2009 20:47
    Wojtek75
    Poziom 23  

    W kodzie który wrzucił david512 zwróć uwagę na tą linie:

    Code:
    If Licz_8ms = 125 Then

    Chodzi mniej więcej o to, że jeżeli zmienna Licz_8ms osiągnie wartość 125 to znaczy że została odmierzona 1s (125 x 0.008 = 1). I teraz dla przykładu jeżeli chcesz osiągnąć odcinek czasu o długości 180s to wystarczy że pomnożysz 180 x 125 = 22500 i osiągniesz wartość 180sek.
    Czyli dla twoich potrzeb powinno to wyglądać mniej więcej tak:
    Code:
    Dim Licz_8ms as Word
    
    ......
    ......
    If Licz_8ms = 22500 Then

    Oczywiście dobierając odpowiednio wartość prescalera i wartości ładowanej do licznika można tą liczbę zmniejszyć do jakiegoś bardziej optymalnego (czyt. mniejszego) rozmiaru.
    W kodzie davida brakuje mi jeszcze bardzo istotnej wartości oscylatora (rezonatora) dla jakiego obliczana jest wartość 0,008s

    pozdr.

    #edit Dodam jeszcze że sam jestem na etapie nauki więc jeżeli popełniam gdzieś błąd to niech mnie bardziej doświadczeni koledzy wyprostują :)

    0
  • #10 01 Maj 2009 21:59
    _Robak_
    Poziom 33  

    Cytat:
    P.S. używam kwarcu 4MHz

    W takim razie na pewno sie nie uda. Chyba ze bedziesz zliacz przerwania i co ktores wykona sie porgram. Oczywiscie musisz wtedy uwzglednic czas potrzebny na obsluge przerwan i odpowienio zmodyfikowac ilosc zliczanych impulsow. Tylko nie wiem na ile mozna w bascomie liczyc na powtarzalnosc czasu wykonywania kodu.

    0
  • #11 01 Maj 2009 23:49
    dawid512
    Poziom 32  

    Małe sprostowanie obliczenia były dla zegara 8MHz.
    Do autora tematu: nie ma możliwości abyś uzyskał przerwanie co 180s ! Chyba że użyjesz kwarcu 32.768kHz co jednak znacznie spowolni procka. Proponuję abyś zrobił tak jak radzi kolega Wojtek75.

    0
  • #12 02 Maj 2009 08:47
    emarcus
    Poziom 35  

    Beeker napisał:
    O wielkie dzieki! Fajnie to wyjaśniłeś teraz kumam :) Będę próbował na pewno się uda.
    P.S. używam kwarcu 4MHz


    Gdyby jednak nie udalo sie to popr. ten:
    Code:

    $regfile = "m8def.dat"
     $crystal = 4000000

    Config Portb = Output               'lcd display
    Const Timer1reload = 62500      ' tyle tikow zegara potrzeba dla 1 sec.
    Config Timer1 = Timer , Prescale = 64
    Dim Czas As Byte
    load timer1 , Timer1Reload
    on ovf1 Timer1_isr
    enable timer1
    start timer1
    Enable Interrupts
    Cls
    Lcd "start"
    Do
    Loop

    Timer1_ISR:
       load timer1, Timer1Reload
       Incr Czas
       If Czas = 180 Then
       Cls
       Lcd "TIME OUT- 3 min"
       End If

      return


    e marcus

    0
  • #13 04 Maj 2009 20:32
    Sław1980
    Poziom 17  

    Dzięki "emarcus" działa wyśmienicie :) teraz muszę to połączyć z moim programem JESZCZE RAZ DZIĘKI! POZDR!

    Dodano po 4 [godziny] 4 [minuty]:

    No i kolejna przeszkoda.... Chcę ten programik dodać do mojego głównego programu i chcę żeby dzałał on w pętli tylko wtedy gdy powiedzmy pind.0=0 niestety nie udaje mi się przerobić go tak aby odliczał czas i pokazał komunikat nie raz, ale za każdym razem w konkretym miejscu. Nie ogarniam czy trzeba za każdym razem wyłaczać timer i przerwania żeby powtórzyć operację odliczania??

    0
  • #15 09 Maj 2009 04:00
    emarcus
    Poziom 35  

    Beeker napisał:
    emarcus da się wogóle zastosować Twój pomysł w pętli? Próbuję i za każdym razem inne efekty :(


    Raz skonfigurowany i zastartowany timer1 lub inny, liczy impulsy lub przedzialy czasowe wg tej zadanej konfiguracji w kolko; nikomu to nie przeszkadza. Nie musisz go zatrzymywac lub startowac znow.
    Jesli zachodzi potrzeba wykorzystania jego uslug, wystarczy przywolac jego subrutyne np.

    if (cos tam) then ' If PORTD.0 = 0 Then
    gosub Timer1_ISR
    end if

    nie musisz go nawet zerowac; (niezaleznie od aktualnego stanu licznika w Timer1, zostanie on nadpisany do okreslonej wartosci).
    Natomiast w warunku naliczenia odpowiedniej ilosci zliczanych przedzialow czasowych wskazac co ma byc wykonane.
    Konkretnie, zamiast :

    Code:

     load timer1, Timer1Reload
       Incr Czas
       If Czas = 180 Then
       Cls
       Lcd "TIME OUT- 3 min"
       End If


    ---------
    Code:


     load timer1, Timer1Reload
    Incr Czas
    If czas =  ??? then          ' ??? - podajesz czas w sec.
    ' tu wpisz co ma robic
    end if
    return



    Zamiast 'gosub' mozesz dac 'call'
    Patrz [Bascom Help]
    Nie wiem jak moze byc prosciej.....(!)

    e marcus

    0
  • #16 10 Maj 2009 20:16
    Sław1980
    Poziom 17  

    ok czyli taki programik powinien działać?

    Code:

    $regfile = "m8def.dat"
     $crystal = 4000000
     
    Config portd = input
    Config Portb = Output               'lcd display
    Const Timer1reload = 62500      ' tyle tikow zegara potrzeba dla 1 sec.
    Config Timer1 = Timer , Prescale = 64
    Dim Czas As Byte
    load timer1 , Timer1Reload
    on ovf1 Timer1_isr
    enable timer1
    start timer1
    Enable Interrupts

    Cls
    Do
    lcd "czekaj na pind..."
    waitms 200
    If pind.0 = 0 then
    gosub Timer1_ISR
    else
    end if 
    Loop
    end

    Timer1_ISR:
       load timer1, Timer1Reload
       Incr Czas
       If Czas = 180 Then
       Cls
       Lcd "TIME OUT- 3 min"
       waitms 200
       Cls
       End If
       return

    niestety nie działa poprawnie poniważ odlicza czas 3 minut ale tylko raz. Później niby skacze do "Timer1_ISR" ale nie odlicza ponownie czasu 3 minut i nie wyświetla na lcd info TIME OUT. Gdzie twki błąd?

    Kod umieszczamy w znacznikach [code] - proszę o tym pamiętać.
    [zumek]

    0
  • #17 10 Maj 2009 22:35
    emarcus
    Poziom 35  

    Beeker napisał:
    ok czyli taki programik powinien działać?
    niestety nie działa poprawnie poniważ odlicza czas 3 minut ale tylko raz. Później niby skacze do "Timer1_ISR" ale nie odlicza ponownie czasu 3 minut i nie wyświetla na lcd info TIME OUT. Gdzie twki błąd?



    Procedure odmierzenia czsu, ktora ci podalem to tylko jedna z wielu metod odmierzenia okreslonego na wstepie przedzialu czasowego.
    Istotnie w jej org. formie jest to praktycznie "ONE SHOT", czyli odmierzyc czas, zrobic cos i stop.
    Wydaje mi sie ze trzeba na koncu wyzerowc zmienna czasu\ albo cos jeszcze zmienic w zaleznosci czy PIND.0 jest zwarty na stale do zera czy tylko puls na start.

    e marcus

    Zmienilem troche twoj code

    Code:


    $regfile = "m8def.dat"
     $crystal = 4000000
      Config Portd.0 = Input                                    'przykladowe wejscie
      ' do wejscia dolaczono  przycisk (momentary push ON/OFF)
      Config Portd.1 = Output                                   'przykadowe wyjscie
      Portd.0 = 1
      Portd.1 = 0
    Config Portb = Output                                       'lcd display

    Const T_max = 10                                            ' preset zmiennej 'czas'
    Const Timer1reload = 62500      ' tyle tikow zegara potrzeba dla 1 sec.
    Config Timer1 = Timer , Prescale = 64
    Dim Czas As Byte

    Dim Z As Bit
    Z = 0
    load timer1 , Timer1Reload
    On Ovf1 Timer1_isr
    Enable Timer1
    Enable Interrupts
    Cls
    Lcd "START"
    Waitms 500
    Cls

    Do
    If Portd.0 = 1 And Z = 0 Then
      Locate 1 , 1
      Lcd "czekaj na pind"
       End If
    If Portd.0 = 0 And Z = 0 Then
     Set Z
     Czas = 0
      Load Timer1 , Timer1reload
    End If
    If Z = 1 Then
     Locate 1 , 1
     Lcd "UPLYW CZASU:" ; Czas ; "sec"
     Locate 2 , 1
     Lcd "TIMER1: " ; Timer1
       End If

    If Z = 1 And Czas = T_max Then                              'dla potrzeb testowych  czas przyjeto 10 sec. (zakres czasu jest: 0 do 255)
    Portd.1 = 1
    Gosub Upd_displ

     Portd.1 = 0
     End If
    Loop

      Timer1_isr:
     Load Timer1 , Timer1reload
        Incr Czas
      Return

      Upd_displ:
         Cls
         Lcd "TIME OUT"
         Locate 2 , 1
         Lcd "CZAS:" ; Czas ; "sec."
         Czas = 0
         Z = 0
         Waitms 500
         Cls
      Return


    Umiescilem w display timer1 dla zobrazowania przebiegow czasowych .
    Usuniesz co nie potrzebne.

    e marcus

    0
  • #18 11 Maj 2009 23:09
    Sław1980
    Poziom 17  

    Fajniście to pokazałeś "e marcus"! Dzieki! Przerobiłem co nieco jeszcze i teraz w końcu śmiga tak jak chciałem. Gdybym miał jeszcze jakieś wątpliwości to na pewno zapytam. Szkoda że w ksiażkach jest to napisane zawile i niezrozumiale a tu proszę jak ktoś wytłumaczy to od razu inaczej ;D

    0