Timer + Bascom


Witam!

Chciałbym sobie stworzyć taki programik w którym mógłbym ustawiać czas (skok co minutę) za pomocą przycisków jeden dodaję drugi odejmuję. Natomiast za pomocą trzeciego przycisku potwierdzałbym ustawienia i procesor wykonywałby inny podprogram do czasu aż minie określony czas. Wyświetlanie na LCD.
Podpowiedziano mi że do tego projektu musze wykorzystać timer. Ale czytam o tym timerze już drugi dzień i nie mam dalej pojęcia na jakiej zasadzie to działa. Może ktoś z Was potrafi mi to łopatologicznie wytłumaczyć albo przedstawić jakiś przykładowy program. Obsługę wyświetlacza wstępnie pojąłem ale jeszcze ten timer:(

Z góry dziękuję za odpowiedź!
Pozdrawiam!




Portret użytkownika matrix

re: Timer + Bascom

robisz tak:
1 - konfigurujesz timer

config timerx = timer, prescale = y  'gdzie x to numer timera, y to stopień podziału timera

2 - piszesz do jakiej etykiety odeśle Cię wywołane przerwanie
on timer0 etykieta   'przykładowo użyłem timera0

3 - wpisujesz wartość do timera która odpowiadać będzie co jaki czas wywolasz przerwanie
timer0 = xx   'xx to liczba wyliczona do przerwania

4 - uaktywniasz globalne przerwania i przerwania timera0
enable interrupts
enable timer0

ja jeszcze daję komendę
start timer0   'tu akurat startuję timer0

chyba wszystko. ktoś ma coś do dodania?
do wyliczania timerów ja osobiście używam programiku o nazwie Pomocnik AVR by Artur Starz.

Portret użytkownika rafliczek22

Ja tylko dodam że istrukcje

Ja tylko dodam że istrukcje enable timerx i start/stop timerx mogą czasami pożądnie wku..ić bo nie zatrzymują timera czasami.
Może na sam początek troche "polubic notke i być z nią na ty"

Portret użytkownika matrix

Re: Timer + Bascom

rafliczek22 wrote:
Ja tylko dodam że istrukcje enable timerx i start/stop timerx mogą czasami pożądnie wku..ić bo nie zatrzymują timera czasami.

mi się to nie zdarzyło jeszcze. może źle napisałeś soft? jeśli był konflikt timerów to mogłeś mieć taką sytuację i zwaliło Ci cały program.

Portret użytkownika Chester

timer

Super ale dalej nie rozumie:( Pomocnik AVR by Artur Starz już mam ściągnięty i się z nim zakumplowałem :)

Zacznijmy krok po kroku :)

Config Timer0 = Timer, Prescale = 64 'czyli z tego wynika że przerwanie będzie co sekunde przy kwarcu 16MHz i 16 bitach??

no ale skąd mam wiedzieć że to przerwanie ma być co sekundę?? Na co mam zwrócić uwagę??
on timer0 etykieta

O co chodzi z tą etykietą?? Czyli przejdzie do jakiegoś podprogramu??
W jaki sposób timer zmieni ustawiany czas o minutę?? Po naciśnięciu przycisku odwołuję sie timera gdy on się przepełni to wtedy się zmienia?? Czarna magia :(

Przepraszam za tak głupie pytania ale proszę o wyrozumiałość i cierpliwość:)

Portret użytkownika mirley

Re: Timer

To proste. napisałeś konfigurację do timera 0, jest on 8 bitowy i liczy wewnętrznie do 255, kolejny impuls zeruje timer i generuje przerwanie. Po wystapieniu przerwania wykona sie fragment kodu podpisany etykietą "etykieta" zadeklarowaną na początku poleceniem "on timer0 etykieta". poniżej w programie musisz mieć gdzieś wpisane:

etykieta:
 
'jakies polecenia
 
return

Co ile będzie wykonywac sie ta etykieta? Kwarc 16MHz najpierw jest dzielony przez prescaler, czyli przez 64 w tym przypadku. Na timer trafia zatem częstotliwość 16000000/64=250000
Przerwanie zatem wywoła się po doliczeniu 256 impulsów zegara o czestotliwości 250kHz, czyli co 0,001024s. jest to trochę głupia wartość więc proponuję dać Prescale =256 a w pierwszej linijce obsługi timera zrobic tak:

etykieta:
Timer0= 6
 
'jakies polecenia
 
return

teraz etykieta będzie wywoływana równo co 4ms bo prescaler dzieli 16MHz przez 256 a potem w każdym doliczeniu timera do końca wpisywana jest od razu wartość 6 co skraca cykl liczenia do 250 a nie do 256 jak jest normalnie. Robi sie tym samym podział przez 256 a potem równo przez 250 i przerwanie będzie wystepowało co 4ms.

Dalej robisz sobie zmienną np D as byte i w przerwaniu:

etykieta:
Timer0= 6
 
'tutaj polecenia sie wykonują co 4ms
 
incr D
if D=250 then
  D=0
 
  'tutaj polecenia się wykonują co 1 s
 
end if
 
return

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika Chester

timer czy licznik

mam jeszcze jedno małe pytanie:

Czy nie lepsze by było wykorzystanie do tego licznika zamiast timer'a??

Pozdrawiam!

Portret użytkownika mirley

Re: timer

Jakiego licznika zamiast timera?

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika drowning_man

odp

Jeśli nie zależy Ci na dokładności odmierzanego czasu to użyj Wait'a...

Portret użytkownika Chester

timer

Wait odpada na pewno :)

Trochę pomieszałem timer może być także jako licznik. Trochę zacząłem kumać tego timera. Postaram się napisać jakiś program i zobaczymy czy dobrze to rozumie :)

Portret użytkownika matrix

Re: timer

timer to nie problem, weź odpal UART.

Portret użytkownika Chester

timer

Dla mnie jak na razie jest problemem :P

Portret użytkownika rafliczek22

Do matrixa: no włąsnie

Do matrixa:

no włąsnie mialem kiedys juz napisany troche powazniejszy program i wszystkie start stop musiałem napisac rejestrem tccr1 na poczatku myslalem ze to wina programu i napisale ktory co sekunde odpalal/wylaczal timer no i timer raz uruchomiony pykal do momentu odlaczenia zasilania,

Do chestera:

2 dni temu sie kupilem w 2 attiny 2313 oraz od kolegi dostalem 7 attiny26(oraz pare innych atmeg) który juz 3 lata temu przerwal zabawe z elekteronika i na 1 2313 i 1 26 przetestowałem progi ktore koledze nie działały i każdy działał 100% (poza 1, źle zadeklarowane porty) więc wydaje mi się że ta tina 2313 coś się popsuła.

P.s. Timer w trybie licznik ( a dokłądniej capture mode) służy do liczenia zewnetrznych impulsów, często wykorzystywany do odbierania danych kodowanych manchesterem

Portret użytkownika Jacek

Obliczanie określonej częstotiwości

Witam - wiem stary temat mam pytanie jak obliczyć określoną częstotliwość dla wyjścia "Test_rigol" w tym programiku jaki powinien być prescaler i jaka liczba powinna znaleźć się w timer0 aby sygnał na wyjściu "test_rigol" miał częstotliwość 1600 Hz. częstotliwość kwarcu 16MHz - pozdrawiam Jacek.
część programu:

Prztimer0:
  Timer0 = 5                                                '0=2512Hz  'Predkosc
  Set Flaga_256us
  Incr Dzielnik(1)
  If Dzielnik(1) = 10 Then
    Dzielnik(1) = 0
    Toggle Step_
    Toggle Test_rigol
    If Dzielnik(2) = 25 Then
    Dzielnik(2) = 0
    Set Flaga_500ms
    Incr Dzielnik(2)
    If Dzielnik(3) = 2 Then
      Dzielnik(3) = 0
      Set Flaga_1s
      'Incr Licz_4ms
      'If Licz_4ms = 25 Then
      'Licz_4ms = 0
      'Toggle Step_
      'Toggle Test_rigol
      End If
    End If
  End If
Return

Portret użytkownika mirley

Re: timer

Dla kwarcu 16MHz nie uzyskasz 160Mhz a np 1602,5641025641 przy preskalarze 64 i gdy w timerze dasz timer0=100, dzielnk przez 10 trzeba wywalić

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika gosc

Witam serdecznie mam pewien

Witam serdecznie

mam pewien dylemat, chciałbym napisać program którego działanie wyglądałoby tak:

po podaniu na licznik 2 impulsów na wejście int0 o zboczu narastającym zapala się dioda na wyjściu Portb.2
jeśli zaś zostanie podany kolejny sygnał to dioda gaśnie i licznik się zeruje i tak w kółko, wszystko miałoby działać na tiny13. Napisałem coś takiego, jednak są pewne problemy, jeśli nie uwzględnię aby zmienna się wyzerowała to dioda czasem zapali się poprawnie a czasem tylko szybko mignie i nic więcej się nie dzieje, natomiast jeśli uwzględnię to zupełnie nic się nie dzieje... Proszę o pomoc

$regfile = "attiny13.dat"
$crystal = 1000000
$hwstack = 32
$swstack = 18
$framesize = 8
 
Config Int0 = Rising
 
Config Pinb.1 = Input
Config Portb.2 = Output
Reset Pinb.1
 
 
Dim A As Byte
Enable Interrupts
Enable Int0
 
On Int0 Przerwanie
 
Do
 
 
Loop
End
 
Przerwanie:
Waitms 70
Incr A
If A = 2 Then
Portb.2 = 1
Else
Portb.2 = 0
A = 0
End If
 
Return

Portret użytkownika matrix

Re: zmienna

Inaczej napisz przerwanie.

Przerwanie:
Waitms 100
Incr A
  If A > 2 then A = 0
    If A = 2 Then
       Portb.2 = 1
     Else
       Portb.2 = 0
    End If
Return

Portret użytkownika airman

Niestety po modyfikacji

Niestety po modyfikacji zachowanie wygląda tak, iż po podaniu pierwszego stanu wysokiego dioda się zapala, po 2 sygnale dioda gaśnie a po 3 tylko mignie, i tak w kółko. Słyszałem, że bascom z tiny13 się gryzie, może to z tego powodu ? jak zrealizować opcję przycisku szyfrowego, który zawiera jeden przycisk ? rozumiem, że potrzebne będzie użycie timera0 ? tak aby dioda się zapaliła po podaniu 2 sygnałów w ciągu ~2sek oraz jednego w ciągu kolejnych ~2sek, jeśli warunek nie zostanie spełniony to dioda się nie zapali, bardzo proszę o pomoc i jednocześnie bardzo dziękuję Ci Matrix za odpowiedź. Posiadam książkę Marcina Wiązani, jednak bez waszej pomocy chyba się nie obejdzie. Pozdrawiam !

Portret użytkownika matrix

Re: zmienna

Nie mówię że oszukujesz, ale to co piszezz jest mało prawdopodobne. Może masz kłopot gdzieś indziej?
Prześledźmy moim tokiem rozumowanie to przerwanie.

Przerwanie:
Waitms 100               'czekamy 100ms
Incr A                   'zwiększamy wartość zmiennej A
  If A > 2 then A = 0    'jeśli A>2 to zerujemy wartość A
    If A = 2 Then        'jeśli A=2 to
       Portb.2 = 1       'włączamy diodę
     Else                'w przeciwnym razie
       Portb.2 = 0       'wyłączamy ją czyli gdy wartość = 0 lub 1
    End If         
Return

Więc nie ma opcji by dioda mignęła jeśli wszystko gdzie indziej masz dobrze.

Portret użytkownika airman

sprawdzę na attiny2313 i dam

sprawdzę na attiny2313 i dam odpowiedź

Edit:

Witam ponownie, po dłuższych próbach na innym attiny13 oraz 2313 działo się to samo... po prostu inteligentny ja fizycznie nie zabezpieczyłem sygnały przed "drganiami", wstawiłem mały kondensator elektrolityczny i problem jak ręką odjął, dlatego w tym miejscy chciałem bardzo przeprosić matrixa i jednocześnie podziękować za trop :). Jeśli to nie problem, to czy ktoś może mi wytłumaczyć w jaki sposób zabrać się za timer0 aby utworzyć niejaki "klucz szyfrowy" ?

Portret użytkownika matrix

Wyjaśnij

Wyjaśnij dokładniej założenia, jakiś link, więcj info co chcesz uzyskać.

Portret użytkownika airman

chciałbym stworzyć programową

chciałbym stworzyć programową filtracje, mianowicie klikam przycisk 2 razy w ciągu jednej sekundy i raz w ciągu kolejnej sekundy, jeśli program wykryje więcej lub mniej wciśnięć niż 2 w ciągu pierwszej sekundy to wszystko się kasuje i zaczyna zliczać od nowa, tak samo jak i w kolejnej sekundzie. Myślę o tym, że w momencie gdy program dostaje pierwszy sygnał zaczyna liczyć, jeśli warunek zostanie spełniony liczy wciśnięcia w kolejnej sekundzie i jeśli po odliczeniu drugiej sekundy zmienna będzie miała 1 to wtedy zapala się dioda, zaś gdy dioda jest zapalona, to ta sama sekwencja gasiłaby ją. Mam nadzieje, że nie zagmatwałem za bardzo założenia. w przyszłości sekwencja miałaby być trudniejsza jednak to tylko na początek aby pojąć timer0 bo wydaje mi się iż jest on niezbędny do tego typu działania. Dziękuję za zaangażowanie, jestem bardzo wdzięczny.

Portret użytkownika matrix

Re: klucz szyfrowy

Wykorzystaj watchdog'a.
Ustaw go na 1 sek. I zeruj go jeśli zmienna osiągnie wartość pożądanych naciśnięć przycisku.

Portret użytkownika airman

Czy możesz podać przykład

Czy możesz podać przykład zerowania watchdog'a ? przyznam, że nigdy dotąd tego nie uzywałem

Portret użytkownika matrix

Re: przykład zerowania watchdog'a

CONFIG WATCHDOG = czas
 
gdzie:
 
czas	czas w milisekundach po jakim układ WATCHDOG uaktywni sygnał reset procesora. Możliwe są wartości: 16, 32, 64, 128, 256, 512, 1024 oraz 2048.

Ustawiasz sobie rządany czas i dalej piszesz sobie warunki. Taki przykład:

do
 
  'główna pętla
  if przycisk = 0 then gosub pierwsza_cyfra_kodu
 
loop
end
 
pierwsza_cyfra_kodu:
start watchdog
do
  'procedura obsługi przycisku itp
 
 If zmienna = 2 then       'jeśli naciśniesz 2x przycisk to
   zmienna = 0             'wyzeruj zmienną dla następnego numeru kodu
   reset watchdog          'resetuj watchdoga i masz kolejny czas na podanie ilości kliknięć przyciskiem
   gosub druga_cyfra_kodu  'skaczesz do podprogramu drugiej cyfry kodu
 end if
loop
return
 
druga_cyfra_kodu:
do
  'procedura obsługi przycisku itp
 
 If zmienna = 1 then       'jeśli naciśniesz 1x przycisk to
   zmienna = 0             'wyzeruj zmienną
   reset zamek             'włączasz zamek otwierający co tam chcesz otworzyć
   stop watchdog           'resetuj watchdoga i masz kolejny czas na podanie ilości kliknięć przyciskiem
   gosub druga_cyfra_kodu  'skaczesz do podprogramu drugiej cyfry kodu
 end if
loop
return

To jest tylko zarys, trzeba przemyśleć wychodzenie z pętli i ogólną obsługę. Nie chce mi się pisać bo było by to napisaanie programu za Ciebie.
Musisz się zabezpieczyć przed zbyt dużą ilością naciśnięć, przed trzymaniem cały czas przycisku.
To nie takie proste jakby się mogło na pierwszy rzut oka wydawać.

Portret użytkownika gosc

Próbuję pojąć działanie i mam

Próbuję pojąć działanie i mam z tym problem, otóż połowicznie działa tak jak było to w założeniu, czyli po podaniu 2 sygnałów w ciągu pierwszej sekundy, oraz po podaniu 1 sygnału podczas drugiej sekundy dioda się zapala, lecz problemem jest to, iż po każdym kolejnym sygnale dioda gaśnie i się zapala. Chciałbym też zrozumieć dlaczego podczas podania 3 szybkich sygnałów dioda również się zapala i kolejno tak jak wcześniej, po każdym sygnale zgaśnie oraz zaświeci(dioda tak jak w założeniu po wolnym wciśnięciu 3 razy przycisku w ogóle się nie zapala). ta sama sekwencja ma uruchamiać oraz gasić diodę, dlatego użyłem toggle.

oto program:

$regfile = "attiny13.dat"
$crystal = 1000000
$hwstack = 32
$swstack = 18
$framesize = 8
 
Config Watchdog = 1024
 
Config Int0 = Rising
 
Config Pinb.1 = Input
Config Portb.2 = Output
Reset Pinb.1
 
 
Dim Zmienna As Byte
Enable Interrupts
Enable Int0
 
On Int0 Przerwanie
 
Do
  If Zmienna = 0 Then Gosub Pierwsza_cyfra_kodu
 
loop
end
 
 
 
Przerwanie:
Waitms 100
Incr Zmienna
Return
 
 
 
pierwsza_cyfra_kodu:
 
start watchdog
 
Do
 If Zmienna = 2 Then
   Zmienna = 0
   Reset Watchdog
   Gosub Druga_cyfra_kodu
 end if
Loop
return
 
 
 
druga_cyfra_kodu:
 
Do
 If Zmienna = 1 Then
   Zmienna = 0
   Toggle Portb.2
   Stop Watchdog
 end if
Loop
return

Dziękuję za pomoc

Portret użytkownika matrix

Re: Próbuję pojąć działanie...

Przecież pisałem że to nie będzie takie proste, że musisz się zabezpieczyć przed zbyt dużą ilością naciśnięć, przed trzymaniem cały czas przycisku.

To trzeba przemyśleć i testować.

Portret użytkownika airman

możesz podpowiedzieć w jaki

możesz podpowiedzieć w jaki sposób napisać program używając do tego odmierzania czasu poprzez timer ? albo będzie to zdecydowanie trudniejsze ?

Portret użytkownika matrix

Re: Próbuję pojąć działanie...

Najpierw napisz sobie założenia i konspekt blokowy, dawniej nosiło to nazwę algorytmu.
Ja napisałbym to pi razy oko w ten sposób:

możesz zaprząc timer1.

- pierwsze wciśnięcie przycisku uruchamia timer odliczający dwie sekundy
- w pętli zwiększasz wartość zmiennej właściwej za każdym naciśnięciem przycisku
- po skoku do przerwania sprawdzasz czy naciśnięto odpowiednią ilość razy przycisk i odpowiednio działasz

Coś tam na szybko powstało, ale nie chce mi się myśleć bo to napisanie programu za Ciebie. pokombinuj, może wpadniesz na lepszy pomysł niż ja. Opatrzyłem ten program masą komentów żebyś wiedział co gdzie i jak.

do 'tu masz pętlę głóną
 
 if przycisk = 0 then  'jeśli naciśnięto przycisk to
   start timer1  'włącz timer 1
   ktora_cyfra = 1  'tu zezwolisz na sprawdzanie za pomocą select case
 end if
 
   select case ktora_cyfra  'wybierz którą cyfrę z kolei naciskamy
    case 1: gosub pierwsza_cyfra  ' i skacz do odpowiedniego podprogramu
    case 2: gosub druga_cyfra
    case n: gosub n_cyfra
   end select
 
loop
end
 
pierwsza_cyfra:
  incr zmienna  'po to zwiększamy zmienną na początku żeby już pierwsze naciśnięcie przycisku zliczyło odpowiednią wartość
   do
     if przycisk = 0 then incr pierwsza_liczba
	 'tu masz dwie sekundy na wciśnięcie odpowiednią ilośc razy przycisk
     if zmienna_pozwalajaca_wyjsc_z_petli = 1 then exit do
   loop
return
 
druga_cyfra:
  incr zmienna
   do
     if przycisk = 0 then incr druga_liczba
     'tu masz dwie sekundy na wciśnięcie odpowiednią ilośc razy przycisk
     if zmienna_pozwalajaca_wyjsc_z_petli = 1 then exit do
 
   loop
return
 
przerwanie:
  stop timer1
  if pierwsza_liczba = pierwsza_wlasciwa then  'jeśli pierwsza liczba zgadza się z zapisaną to
     ktora_cyfra = 2  'ustawiamy zmienną ktora_liczba na 2 żeby móc przejść do podprogramu drugiej liczby
     timer1 = 3036  'to powinno wywoływać timer co 2sek.
     zmienna_pozwalajaca_wyjsc_z_petli = 1
     start timer1
   else
     zmienna_pozwalajaca_wyjsc_z_petli = 0
     start watchdog  'jeśli się nie zgadza to startujemy watchdog'a ustawionego na najmniejszy możliwy czas i on zresetuje nam procek
  end if
  if druga_liczba = druga_wlasciwa then
     ktora_cyfra = n  'jeśli masz więcej niż dwie cyfry w kodzie to piszesz kolejen bloki
     timer1 = 3036  'to powinno wywoływać timer co 2sek.
     zmienna_pozwalajaca_wyjsc_z_petli = 1
     start timer1
   else
     zmienna_pozwalajaca_wyjsc_z_petli = 0
     start watchdog  'jeśli się nie zgadza to startujemy watchdog'a ustawionego na najmniejszy możliwy czas i on zresetuje nam procek
  end if
 
  if ostatnia_liczba = ostatnia_wlasciwa then
     stop timer1
     ktora_cyfra = 0
     set dioda  'włącz diodę
     set zamek  'włącz zamek
     waitms 500  'włączasz diodę i zamek na określony czas, tu już nie ma znaczenia używanie wait bo wyłaczyłeś timery itp
     reset dioda
     reset zamek
     start watchdog  'włączasz watchdog'a który zresetuje Ci procek i zaczniesz wszystko od początku
  end if
 
 
return