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

Nie działa TIMER0... dlaczego?

hanibal0 04 Mar 2010 17:36 2203 25
  • #1 7783099
    hanibal0
    Poziom 11  
    zamierzeniem programu, jest możliwość wyłączenia działania programu w dowolnym momencie przez naciśnięcie przycisku na porcie D2. Jest to mój pierwszy program z użyciem TIMER0 i nie wiem gdzie jest błąd, program po wgraniu do atmega8 kompletnie nie działa, tzn nawet dioda się nie zaświeci. Może mi ktoś wytłumaczyć o co chodzi z tym TIMER0?

    $regfile = "m8def.dat"
    $crystal = 1000000
    
    Config Portb = Output
               Portb = &B00000000
    Config Portd = Input
               Portd = &B11111111
    
    Config Timer0 = Timer , Prescale = 256
    Enable Interrupts
    Enable Timer0
    On Timer0 Co_25ms
    
    Do
    Pr:
       Debounce Portd.0 , 0 , Pr_1
    
       Debounce Portd.1 , 0 , Pr_2
    
    Loop
    
    Pr_1:
       Portb.1 = 1
       Wait 1
       Portb.5 = 0
       Return
    
    Pr_2:
       Portb.4 = 1
       Wait 2
       Portb.4 = 0
       Return
    
    Co_25ms:
    
       If Portd.2 = 0 Then
       Waitms 25
       If Portd.2 = 0 Then Gosub Pr_stop
       End If
    
    Pr_stop:
    
       Portb.5 = 0
       Portb.4 = 0
       Goto Pr
       Return
    
  • #2 7783201
    rpal
    Poziom 27  
    Jak dotąd "gardziłem" Bascom-em i nie zamierzam się wgłebiać w jego składnię ale nie widzę tam obsługi przerwania które sobie uaktywniłeś.
    poprawiam, chyba jednak jest ale o ile sie nie mylę instrukcji wait nie powinno się używać w przerwaniach bo inne jest zadanie dla przerwania niż zwłoka czasowa typu wait.
  • #3 7783209
    zbychmg
    Poziom 31  
    Procedura wykonywana od przewania Timer0
    powinna być jak najkrótsza
    co najwyżej zmieniać flagi
    a w głównym programie (Do loop)
    zrobić obsługę ustawionych w przerwaniu flag
    Dlatego w procedurze przerwania Co_25ms
    nie dawaj Waitms 25

    Ona prawdopodobnie nie kończy działania
    przed jej ponownym wykonaniem

    I dałeś w niej

    Jeden If zakończony endif a drugi nie

    Wyrzuć Pr_Stop

    Goto Pr

    Błąd stosu murowany.
  • #4 7783227
    rpal
    Poziom 27  
    kolega był szybszy i napisał to co ja własnie poprawiałem :)
  • #5 7783247
    zbychmg
    Poziom 31  
    Nie bardzo widzę sens stosowania przerwania

    dopisz

    Debounce Portd.2 , 0 , Pr_Stop

    i masz to co chciałeś

    timer raczej wykorzystuje się do wykonywania procedury
    w jednakowych odstępach czasu
    np. licznik sekund itp.
    ewentualnie do wymuszenia testowania wejścia (wejść)
    częściej niż czas obiegu głównej pętli programu.
    Przerwanie może być wykonywane kilka (kilkanaście) razy w czasie jednej pętli programu (zależy to od jego długości i użytych f-kcji)
    No ale zbyt długa procedura wywoływana w przerwaniu tym bardzie wydłuża się czas wykonywania jednej pętli programu
  • #6 7783252
    Wojtek75
    Poziom 24  
    Poza tym w podprogramie obsługi przerwania zjadło "Return" na końcu.
  • #8 7783279
    zbychmg
    Poziom 31  
    Dziwne, że kompilator nie wyrzucił błędu....
    Zastanawiam się jak wygląda skompilowany wynik,
    którym zaprogramowałeś kostkę, może wrzuć na debuger,
    masz szansę na zapoznanie się z tym co dzieje się
    w procku....

    Dodano po 6 [minuty]:

    W helpie jest opis przerwania Timer0, a w Bascom-ie jest sporo przykładów użycia przerwania Timer0 poszperaj w sieci i popatrz jak robią to inni, to najlepszy sposób na to aby nie wywarzać otwartych drzwi.
    pozdrawiam...
  • #9 7783331
    hanibal0
    Poziom 11  
    zbychmg teoretycznie mógłbym dopisać tak jak wspomniałeś ale to nie rozwiąże problemu kiedy np. uruchomię Pr1 (np zaświecę diodę), ustawię ją na powiedzmy wait 50 i będę chciał ją wyłączyć przed czasem. Ogólnie to jest prosty programik po to abym mógł nauczyć się obsługi TIMERA aby móc później zastosować go w bardziej rozbudowanych programach. Kod zmodyfikowałem ale nie wiem czy wciąż coś jest nie tak czy moja atmega8 ma dziś kiepski dzień.

    $regfile = "m8def.dat"
    $crystal = 1000000
    
    Config Portb = Output
               Portb = &B00000000
    Config Portd = Input
               Portd = &B11111111
    
    Config Timer0 = Timer , Prescale = 256
    Enable Interrupts
    Enable Timer0
    On Timer0 Co_25ms
    
    Do
    Pr:
       Debounce Portd.0 , 0 , Pr_1
    
       Debounce Portd.1 , 0 , Pr_2
    
    Loop
    
    Pr_1:
       Portb.1 = 1
       Wait 1
       Portb.5 = 0
       Return
    
    Pr_2:
       Portb.4 = 1
       Wait 2
       Portb.4 = 0
       Return
    
    Co_25ms:
    
       Debounce Portd.2 , 0 , Pr_stop
       Return
    
    Pr_stop:
    
       Portb.5 = 0
       Portb.4 = 0
       Goto Pr
       Return
    


    zaczynam się już powoli gubić, jeśli ustawię początkowo stan 0 to dioda nie powinna świecić, a po zmianie na stan 1 powinna świecić???

    kompiluję wszystko w bascomie, wcześniej wszystko było ok.
  • #11 7783380
    hanibal0
    Poziom 11  
    więc jeśli nie za pomocą polecenia wait to jak mam ustawić żeby po wciśnięciu sw1 dioda świeciła przez 5 sek a po wciśnięciu sw2 przez 35 sek, tak aby w każdym momencie można było wyłączyć diodę?
  • #13 7783405
    hanibal0
    Poziom 11  
    zapomniałem zmienić, próbowałem różne porty, ale wciąż program nie działa

    
    $regfile = "m8def.dat"
    $crystal = 1000000
    
    Config Portb = Output
               Portb = &B00000000
    Config Portd = Input
               Portd = &B11111111
    
    Config Timer0 = Timer , Prescale = 256
    Enable Interrupts
    Enable Timer0
    On Timer0 Co_25ms
    
    Do
    Pr:
       Debounce Portd.0 , 0 , Pr_1
    
       Debounce Portd.1 , 0 , Pr_2
    
    Loop
    
    Pr_1:
       Portb.0 = 1
       Wait 1
       Portb.0 = 0
       Return
    
    Pr_2:
       Portb.1 = 1
       Wait 2
       Portb.1 = 0
       Return
    
    Co_25ms:
    
       Debounce Portd.2 , 0 , Pr_stop
       Return
    
    Pr_stop:
    
       Portb.0 = 0
       Portb.1 = 0
       Goto Pr
       Return
    
  • #14 7783408
    zbychmg
    Poziom 31  
    To właśnie możesz zrobić w Timer0.
    Procedura przerwania jest wywoływana co określony czas
    wystarczy tak ustalić parametry przerwania, aby to było powiedzmy 10ms
    {zobacz opis ustawień Timer0)
    wtedy po naciśnięciu przycisku ustawiasz zmienną np.m na liczbę 500
    i w każdym przerwaniu zmniejszasz o 1 jeśli > 0
    Gdy równa zero gasisz diodę

    Dodano po 9 [minuty]:

    Popraw składnie, bo ja nie mam bascoma

    
    $regfile = "m8def.dat"
    $crystal = 1000000
    
    Config Portb = Output
               Portb = &B00000000
    Config Portd = Input
               Portd = &B11111111
    
    Config Timer0 = Timer , Prescale = 256
    Enable Interrupts
    Enable Timer0
    On Timer0 Co_25ms
    
    Do
    Debounce Portd.2 , 0 , Pr_stop 
    If n=0 then Portb.0=0
         Debounce Portd.0 , 0 , Pr_1
    elseif port Portb.0=1
    endif
    Loop
    Pr_1:
       n=500
       Return
    Co_25ms:
       In n>0 then n=n-1
       Return
    Pr_stop:
       Portb.0 = 0
       n = 0
       Return
    
    [/quote]
  • #15 7783484
    hanibal0
    Poziom 11  
    cały problem w tym że w helpie bascoma mam tylko schemat z bramkami logicznymi i prawie żadnego opisu, natomiast w helpie polskim nie mam w ogóle polecenia TIMER0 ani TIMER1. W necie nie bardzo mogę coś znaleźć a w skanach książki Marka Wiązania, brakuje mi kilku stron właśnie o TIMER.

    zaczynam powoli się denerwować, nie mam pojęcia co się dzieje ale nawet proste programy bez TIMERA nie chcą mi działać, skompilowałem program bez TIMERA i diody się nie zapalają po wciśnięciu przycisku. O co chodzi, wcześniej nie miałem takich prblemów?

    Dodano po 7 [minuty]:

    zbychmg napisał:
    To właśnie możesz zrobić w Timer0.
    Procedura przerwania jest wywoływana co określony czas
    wystarczy tak ustalić parametry przerwania, aby to było powiedzmy 10ms
    {zobacz opis ustawień Timer0)
    wtedy po naciśnięciu przycisku ustawiasz zmienną np.m na liczbę 500
    i w każdym przerwaniu zmniejszasz o 1 jeśli > 0
    Gdy równa zero gasisz diodę

    Dodano po 9 [minuty]:

    Popraw składnie, bo ja nie mam bascoma

    
    $regfile = "m8def.dat"
    $crystal = 1000000
    
    Config Portb = Output
               Portb = &B00000000
    Config Portd = Input
               Portd = &B11111111
    
    Config Timer0 = Timer , Prescale = 256
    Enable Interrupts
    Enable Timer0
    On Timer0 Co_25ms
    
    Do
    Debounce Portd.2 , 0 , Pr_stop 
    If n=0 then Portb.0=0
         Debounce Portd.0 , 0 , Pr_1
    elseif port Portb.0=1
    endif
    Loop
    Pr_1:
       n=500
       Return
    Co_25ms:
       In n>0 then n=n-1
       Return
    Pr_stop:
       Portb.0 = 0
       n = 0
       Return
    

    niestety program się nie kompiluje, problem ze zmienną n, ale kiedy dopiszę: dim n as byte, kompilator wyrzuca problem z end if, tego też nie rozumiem, zawsze kiedy kończę end in mam błędy, dlatego w pierwszym poście zakończyłem tylko jednym end if
  • #16 7783534
    ZbeeGin
    Poziom 39  
    hanibal0 napisał:
    natomiast w helpie polskim nie mam w ogóle polecenia TIMER0 ani TIMER1.

    CONFIG TIMER0 - jest.
    CONFIG TIMER1 - jest.
    TIMER0 (zmienna) - jest.
    TIMER1 (zmienna) - jest.
    ON interrupt - jest.
    RETURN - jest
    Więc o co koledze chodzi? A sięgnijmy nawet do źródeł:
    Nie działa TIMER0... dlaczego?Nie działa TIMER0... dlaczego?Nie działa TIMER0... dlaczego?

    hanibal0 napisał:
    W necie nie bardzo mogę coś znaleźć a w skanach książki Marka Wiązania, brakuje mi kilku stron właśnie o TIMER.

    No to z kolegi niezłe ziółko. Skanowane książki?
  • #17 7783612
    hanibal0
    Poziom 11  
    faktycznie wszystko jest, szukałem przez index wpisując timer i dlatego myślałem że nie ma. Tak czy inaczej skompilowałem najprostszy program i nie działa, dlaczego?
    $regfile = "m8def.dat"
    $crystal = 1000000
    
    Config Portb = Output
               Portb = &B00000000
    Config Portd = Input
               Portd = &B11111111
    
    Do
       Debounce Portd.0 , 0 , Pr
    Loop
    
    Pr:
       Portb.0 = 1
       Wait 10
       Portb.0 = 0
       return
  • #19 7783657
    hanibal0
    Poziom 11  
    ok juz wiem w czym problem, powinno być debounce pind.0,0,Pr

    dzięki

    Dodano po 2 [minuty]:

    kolego ZbeeGin, mógł byś mi przesłać na maila tego helpa, z którego zamieściłeś zdjęcia? albo jakiś link do niego?

    Dodano po 30 [minuty]:

    poprawiłem błędy, teraz zatrzymanie wykonywania programu działa ale tylko czasami, tzn nie przy każdym wciśnięciu SW na porcie PD2
  • #20 7783886
    zbychmg
    Poziom 31  
    Tylko jeszcze napisz, który program tak działa jak opisujesz


    Dodano po 53 [sekundy]:

    Bo nie bardzo jest się do czego odnieś....
    Jeśli zaczynasz zabawę z Atmega8
    Spróbuj FASTAVR, jest darmowa wersja w sieci z ograniczeniem wielkości kodu, ale do takich programików zupełnie wystarczy, a kompiluje lepiej i daje w wyniku szybciej wykonujący się kod binarny
  • #21 7783913
    ZbeeGin
    Poziom 39  
    hanibal0 napisał:
    kolego ZbeeGin, mógł byś mi przesłać na maila tego helpa, z którego zamieściłeś zdjęcia?

    Nie. Nie wyślę Tobie tego helpa.

    hanibal0 napisał:
    albo jakiś link do niego?

    Helpy są na stronie MCS Electronics.
  • #22 7784049
    hanibal0
    Poziom 11  
    ZbeeGin napisał:
    hanibal0 napisał:
    kolego ZbeeGin, mógł byś mi przesłać na maila tego helpa, z którego zamieściłeś zdjęcia?

    Nie. Nie wyślę Tobie tego helpa.

    hanibal0 napisał:
    albo jakiś link do niego?

    Helpy są na stronie MCS Electronics.


    miałem na myśli polskiego helpa (tego z którego były screeny) ale skoro to takie ważne dla ciebie to nie ma sprawy, poradzę sobie bez nich. Gdzieś na forum przeczytałem że sam tłumaczyłeś tego helpa więc jeśli tak było to masz prawo nim dysponować w/g własnego uznania.

    program, który działa ale nie do końca to:

    $regfile = "m8def.dat"
    $crystal = 1000000
    
    Config Portb = Output
               Portb = &B00000000
    Config Portd = Input
               Portd = &B11111111
    
    Config Timer0 = Timer , Prescale = 256
    Enable Interrupts
    Enable Timer0
    On Timer0 Co_25ms
    
    Do
    Pr:
       Debounce Pind.0 , 0 , Pr_1
    
       Debounce Pind.1 , 0 , Pr_2
    
    Loop
    
    Pr_1:
       Portb.0 = 1
       Wait 1
       Portb.0 = 0
       Return
    
    Pr_2:
       Portb.1 = 1
       Wait 2
       Portb.1 = 0
       Return
    
    Co_25ms:
    
       Debounce Pind.2 , 0 , Pr_stop
       Return
    
    Pr_stop:
       Portb.0 = 0
       Portb.1 = 0
       Goto Pr
       Return


    jak na razie nie mogę sobie poradzić z tymi przerwaniami, flagami itd. Niestety nigdy nie miałem doczynienia z programowaniem, nie mam nikogo znajomego, kto mógłby mi pomóc, więc muszę liczyć na siebie i ewentualnie na pomoc z forum.
    Programowanie uC traktuję jako hobby więc mam również ograniczone możliwości czasowe.
  • #23 7784316
    janbernat
    Poziom 38  
    Polski help napisany przez Z.B. jest na stronie MCS Electronics.
    Napisany po polsku.
    Możesz to ściągnąć.
    MCS Electronics jest w Holandii, strona jest po angielsku a różne helpy, programy, opisane książki bywają w różnych językach.
    Help to jest help- nie do nauki programowania ale do pomocy przy wątpliwościach.
    A i tak warto cały przejrzeć.
    Kup sobie książkę "Mikrokontrolery dla początkujących".
    Hobby wymaga poświęcenia czasu i pieniędzy.
    Gdybyś hobbystycznie grał w golfa- to dopiero wymagało by poświęceń.
    P.S.
    A na początek- Twoje przerwanie wywoływne jest nie co 25ms ale co 65ms.
    Poszukaj jakiegoś AVR kalkulatora- ułatwia obliczenia.
    Z przerwania wychodzisz przez goto- co jest złym zwyczajem- i nie wchodzisz do return- co pozwala wrócić ze stosu.
  • #24 7784461
    zbychmg
    Poziom 31  
    Kolega janbernard ma rację już Ci pisałem wywal Goto pr
    z procedury:
    Pr_stop:

    A najlepiej to co jest w Pr_stop
    wpisz bezpośrednio do procedury obsługującej przerwanie
    i zmień jej nazwę Co_65ms bo będzie wywoływana co 65ms
    Gdybyś dał kwarc 6Mhz to wywołanie byłoby co 10ms (około)

    Napisałem Ci jak uniknąć wait, bo to niepotrzebne zatrzymywanie procesora i korzystanie z przerwania, po to, żeby jednak coś zrobił

    Dodano po 1 [godziny] 11 [minuty]:

    Sciągnąłem FASTAVR i poniżej program realizujący twoje wymagania
    Niestety kopiowanie zlikwidowało tabulacje (wcięcia)
    No to proszę umieszczać kod, w odpowiednich znacznikach - poprawiłem.
    [zumek]

    'FAST AVR zapalenie led1,2 na czas 10 i 20s po naciśnięciu S1 i S2 S3 reset
             
    $Device= m8	' used device
    $Stack = 32     ' stack size
    $Clock = 8		' used clock in MHz
    $Source= On     
    $Key Rows= PORTB &h38		' Keys are on PortB in line bit 5,4,3  &B111000 H38
    $Timer0=Timer , Prescale=256 'Async,Compare=Set|Reset|Toggle|DisConnected] 
    $Source=On                'konfig Timer1 jako timer z podziałem preskalera przez256
    
    Dim sek_Led1 As Byte , sek_Led2 As Byte 'odliczany czas zapalewnia  led1 i 2
    Dim setL1 As Byte, setL2 As Byte       'ustawione czas zapalenia Led1 i 2  w tym progr 10 i 20 sek.
    
    Declare Interrupt Ovf1()        'On Timer1 Odmierz_1s IRQ od przepełnienia Timer1 o etykiecie Odmierz_1s
    
    Declare Sub Led1():Declare Sub Led2():Declare Sub Reset()    'proced.obs klawisza S1,2,3
    
    Enable Interrupts   'odblokowanie globalnego systemu przerwań
    
    $Def Led2 = PORTB.2 :
    $Def Led1 = PORTB.1
    
    $Def S1 = PINB.3 
    $Def S2 = PINB.4
    $Def S3 = PINB.5         'przypis nazw
    
    Set S1:Set S2:Set S3	'  ustawia na stan wysoki
    Const Cntt = 34286		'aby uzyskać przerwanie dokładnie co 1s
    setL1 = 10				'dla 8MHz wart.pocz.wpisywana do Timer1 (65536-31250=34286)
    setL2 = 20				'		1.8432 -2MHz	4Mhz  7.3728  8 	10MHz	11.0592	12MHz 16MHz
    						'  64 	49911	36736  	34286  3036		 		-			-
    						' 256	58336			49906 36736  34286			 22336	18661 3036
    Enable Ovf1     		'1024	63736						 55770  54736		-	49911
    Counter1 = Cntt
    Do
       On S1 Led1()	    'zapalenie Led1	na czas setL1
       On S2 Led2()     'zapalenie Led2 na czas setL2
       On S3 Reset()    'reset
    Loop                     
    
    Sub Led1()
      	If  sek_Led1=0 Then   Set Led1      'obsluga przyc.S1
    End Sub
    
    Sub Led2()
      	If  sek_Led2=0  Then Set Led2       'obsluga przyc.S2 
    End Sub
    
    Sub Reset()						 'obsluga przyc.reset
      	Reset Led1:	Reset Led2
      	sek_Led1=0:sek_Led2=0	
    End Sub
    
    Interrupt Ovf1()           ' obsługa przerwania timer1 co 1 s
    Counter1 = Cntt        'wpis.ponownie wart.początkowejlicznika 
     If Led1 Then
      	If setL1>sek_Led1 Then
      		Incr sek_Led1
     	Else
      		Reset Led1:	sek_Led1=0
     	End If	
     End If
     If Led2 Then
     	If setL2>sek_Led2 Then
      		Incr sek_Led2
     	Else
      		Reset Led2:	sek_Led2=0
     	End If	
     End If
    End Interrupt
  • #25 7786027
    hanibal0
    Poziom 11  
    próbowałem skompilować następujący kod:
    $regfile = "m8def.dat"
    $crystal = 1000000
    
    Config Portb = Output
               Portb = &B00000000
    Config Portd = Input
               Portd = &B11111111
    
    Dim N As Integer
    Config Timer0 = Timer , Prescale = 64
    Enable Interrupts
    Enable Timer0
    On Timer0 Co_16ms
    
    
    
    Do
       Debounce Pind.2 , 0 , Pr_stop
       If N = 0 Then Portb.0 = 0
          Debounce Pind.0 , 0 , Pr_1
       Elseif Portb.0 = 1
       End If
    Loop
    
    Pr_1:
       N = 500
       Return
    Co_16ms:
       If N > 0 Then N = N - 1
       Return
    Pr_stop:
       Portb.0 = 0
       N = 0
       Return


    niestety bascom wyrzuca błędy w linii 21 i 22, dotyczące elseif i endif. Co jest nie tak w zapisie kodu, już zaczynałem łapać o co chodzi z tymi przerwaniami i przeanalizowałem w głowie ten kod, wydaje mi się ok, dioda powinna świecić jakieś 31 sek (jeśli nie wcisnę PD2). Tylko dlaczego nie mogę tego skompilować?
  • #26 7786761
    zumek
    Poziom 39  
    hanibal0 napisał:
    Tylko dlaczego nie mogę tego skompilować?

    Nie możesz tego skompilować, ponieważ:
    Nie umiesz, nie możesz, nie chcesz, zajrzeć do pliku pomocy.
    Już przy kłopotach z funkcją Debounce, wystarczyło sprawdzić w "Helpie", ale Tobie widocznie się nie chce :|
    Temat zamykam - regulamin p.14, 16
REKLAMA