| Author |
Message
|
kosmo90 Poziom 8

Joined: 24 May 2006 Posts: 28
|
#1
01 Jun 2006 19:04 Timer0 -> Timer1 (ATmega8) |
|
|
|
Cześć
Jestem bardzo, bardzo początkujący i nie mogę sobie dać rady z licznikami :( Nie rozumiem o co chodzi w tym preskalerze.
Znalazłem w książce program, który zlicza 1s przy wykorzystaniu licznika 8-bitowego Timer0. Czy moglibyście mi zmienić ten kod tak żeby zliczał tą sekundę wykorzystując 16-bitowy timer1? Rezonator kwarcowy w tym układzie ma 8MHz.
| Code: |
$regfile = "m8def.dat"
$crystal = 8000000
Config Pinb.0 = Output
Config Timer0 = Timer , Prescale = 256
On Timer0 Odmierz_1s
Dim Licz_8ms As Byte
Enable Interrupts
Enable Timer0
Load Timer0 = 250
Do
Loop
End
Odmierz_1s:
Load Timer0 = 250
Incr Licz_8ms
If Licz_8ms = 125 Then
Licz_8ms = 0
Toogle Portb.0
End If
Return |
Dla Was ta przeróbka to pewnie 5 minutek, także będę bardzo wdzięczny za pomoc!!
Z góry bardzo dziekuję i pozdrawiam.
Ps. dlaczego zarówno w głównym programie i wewnątrz przerwania jest linijka 'Load Timer0 = 250'?
|
|
| Back to top |
|
 |
M. S. Poziom 22

Joined: 12 Jan 2005 Posts: 1508 Location: Czechowice - Dziedzice
|
#2
01 Jun 2006 19:35 Re: Timer0 -> Timer1 (ATmega8) |
|
|
|
Load Timer 250 pojawił się 2 razy bo pierwszy jest wykonyawny przed wejściem do pętli a następny w pętli.
W tym programie jest dodatkowa zmienna Licz_8ms bo Timer0 nie może odmierzyć całej sekundy w jednym przebiegu. Przy użyciu Timer1 i odpowiedniego kwarcu można osiągnąć przerwania co 1 s. Jest to korzystne bo odmierzanie czasu jest nieco dokładniejsze.
Load Timer0 250 oznacza, że do przerwania timer odliczy 250 natomiast w przypadku Timer0 = 250 bedzie to początkowa wartość timera, czyli do przepełnienia wystarczy tylko 6 impulsów. (256 - 250).
Co do rachunków to polecam program kalkulator do AVR'ów. Napisz na PW swój e-mail to odeślę jako załącznik.
|
|
| Back to top |
|
 |
Google

|
#
01 Jun 2006 19:35 |
|
|
|
|
|
| Back to top |
|
 |
kosmo90 Poziom 8

Joined: 24 May 2006 Posts: 28
|
#3
01 Jun 2006 19:44 Timer0 -> Timer1 (ATmega8) |
|
|
|
Dziękuję za odpowiedź!
Nie wyjaśniłeś mi jednak jak zmienić podany przeze mnie program żeby zliczał sekundę przy kwarcu 8MHz z Timer1 :)
Czytałem trochę, ale nie wiem czy udało mi się to dobrze zrozumieć.
Jeżeli przy 8MHz użyje preskalera 1024 to wyjdą ułamki, więc przypuszam że takiego nie powinienem stosować :) Przy preskalerze 256 wychodzi:
8000000/256 = 31250
Czyli musiałbym wpisać w programie:
Timer1 = 65535 - 31250
Czy dobrze to rozumiem?
|
|
| Back to top |
|
 |
_Robak_ Poziom 22

Joined: 16 Apr 2006 Posts: 2197 Location: Bytom
|
#4
01 Jun 2006 21:32 Timer0 -> Timer1 (ATmega8) |
|
|
|
Jezeli dasz prescaller 256 to musisz zliczyc 31250 impulsow aby odmierzyc sekunde.
|
|
| Back to top |
|
 |
kosmo90 Poziom 8

Joined: 24 May 2006 Posts: 28
|
#5
01 Jun 2006 22:19 Re: Timer0 -> Timer1 (ATmega8) |
|
|
|
Czy taki program obliczy mi dobrze czas?
| Code: |
$regfile = "m8def.dat"
$crystal = 8000000
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portc.3 , Db5 = Portc.2 , Db6 = Portc.1 , Db7 = Portc.0 , E = Portc.4 , Rs = Portc.5
Cls
Config Timer1 = Timer , Prescale = 256
On Timer1 Odmierz_2s
Dim Licz As Byte
Enable Interrupts
Enable Timer1
Start Timer1
Timer1 = 65535 - 31250
Do
Loop
End
Odmierz_2s:
Timer1 = 65535 - 31250
Stop Timer1
Incr Licz
Lcd "Czas: " ; Licz
Licz = 0
Return |
Jeśli nie to czy ktoś mógłby wprowadzić zmiany w kodzie podanym przeze mnie w pierwszej wiadomości?
|
|
| Back to top |
|
 |
Google

|
#
01 Jun 2006 22:19 |
|
|
|
|
|
| Back to top |
|
 |
M. S. Poziom 22

Joined: 12 Jan 2005 Posts: 1508 Location: Czechowice - Dziedzice
|
#6
01 Jun 2006 22:43 Re: Timer0 -> Timer1 (ATmega8) |
|
|
|
Chciałem Ci dać wędkę, ale wolisz rybę.
| Code: |
$regfile = "m8def.dat"
$crystal = 8000000
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portc.3 , Db5 = Portc.2 , Db6 = Portc.1 , Db7 = Portc.0 , E = Portc.4 , Rs = Portc.5
Cls
Config Timer1 = Timer , Prescale = 256
On Timer1 Odmierz_2s
Dim Licz As Byte
Enable Interrupts
Enable Timer1
Start Timer1
Timer1 = 34285
Do
Loop
End
Odmierz_2s:
Timer1 = Timer1 + 34285
Incr Licz
Lcd "Czas: " ; Licz
Return |
Zaladowałem do timera 65536 - 31250 (bo 0 to też impuls)
W podprogramie obsługi przerwania umieściłem Timer1 = Timer1 + 34285 tak aby uwzględnić stan timera w momencie modyfikacji jego zawartości.
Wyrzuciłem zatrzymanie timera (jeżeli to ma być wielokrotne odmierzanie czasu). Wyrzuciłem zerowanie zmiennej Licz - inaczej cały czas byłaby równa 1, a tak wyświetlane będą kolejne sekundy.
Co do kalkulatora AVR to po dobraniu parametrów timera oblicza czas pojawienia się przerwania od przepełnienia. Można zatem po kilku eksperymentach dobrać potrzebne nastawy.
|
|
| Back to top |
|
 |
kosmo90 Poziom 8

Joined: 24 May 2006 Posts: 28
|
#7
01 Jun 2006 22:48 Timer0 -> Timer1 (ATmega8) |
|
|
|
Znalazłem na internecie program, który ma przerwania co 1s z licznikiem Timer1 (przy 8MHz)
| Code: |
$regfile = "m8def.dat"
$crystal = 8000000
'--------------------Ustawienie LCD------------------
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portc.3 , Db5 = Portc.2 , Db6 = Portc.1 , Db7 = Portc.0 , E = Portc.4 , Rs = Portc.5
Cls
Cursor Off
'----------------------------------------------------
Lcd "Welcome"
Dim I As Word
Config Timer1 = Timer , Prescale = 256
On Timer1 Times
Enable Interrupts
Enable Timer1
Timer1 = 34285
Do
Loop
End
Times:
Timer1 = 34285
I = I + 1
Cls
Lcd I
Return |
Program działa w symulatorze. Nie rozumiem tylko skąd wartość Timer1=34285. Czy ktoś mógłby mi to wyjaśnić?
Dzieki!
Dodano po 4 [minuty]:
Napisaliśmy odpowiedz chyba w tym samym czasie bo Twojej nie widziałem :)
Dzięki, teraz rozumiem skąd wartość 34285.
Przy mojej wiedzy w tej chwili poradzenie sobie z wędką jeszcze jest chyba zbyt trudne :)
M.S. dodałeś w przerwaniu Timer1 = Timer1 + 34285, w programie który ja znalazłem jest tylko Timer1 = 34285. Jaka jest różnica i która wersja jest poprawna? :)
|
|
| Back to top |
|
 |
Google

|
#
01 Jun 2006 22:48 |
|
|
|
|
|
| Back to top |
|
 |
M. S. Poziom 22

Joined: 12 Jan 2005 Posts: 1508 Location: Czechowice - Dziedzice
|
#8
01 Jun 2006 23:49 Re: Timer0 -> Timer1 (ATmega8) |
|
|
|
Moja uwzględnia czas, który upłynął od przerwania do załadowania timera. Może to mieć wpływ gdy wystąpi w tym samym czasie obsługa innego przerwania.
|
|
| Back to top |
|
 |
GienekS Poziom 22

Joined: 12 Oct 2003 Posts: 1964 Location: Tarnowskie Góry
|
#9
02 Jun 2006 00:13 Re: Timer0 -> Timer1 (ATmega8) |
|
|
|
| M. S. wrote: |
| Moja uwzględnia czas, który upłynął od przerwania do załadowania timera. Może to mieć wpływ gdy wystąpi w tym samym czasie obsługa innego przerwania. |
Pod warunkiem że to przerwanie zabierze więcej czasu niż potrzebne będzie preskalerowi na 256 cykli. W przeciwnym przypadku nic nie trzeba korygować właśnie dzięki preskalerowi, który daje te 256 cykli na załadowanie licznika właściwą wartości a nie jakąś tam korygowaną o niewiadomo o co.
|
|
| Back to top |
|
 |
M. S. Poziom 22

Joined: 12 Jan 2005 Posts: 1508 Location: Czechowice - Dziedzice
|
#10
02 Jun 2006 06:56 Re: Timer0 -> Timer1 (ATmega8) |
|
|
|
Zatem zapisy sa równoważne. Istotne to może być przy preskalerze = 1.
|
|
| Back to top |
|
 |
greg_matrix Poziom 14

Joined: 27 Jan 2006 Posts: 163 Location: Rzeszów
|
#11
02 Jun 2006 12:37 Re: Timer0 -> Timer1 (ATmega8) |
|
|
|
Jedna uwaga tak na marginesie.
Chyba wiem z jakiej książki korzystał kosmo90 i niestety jest tam błąd. Instrukcja Load Timer ma odrobinę inną składnię. Powinno być:
czyli przecinek a nie znak =. Można ewentualnie napisać
co da taki sam efekt.
A co do sposobu ładowania Timera to w pełni podzielam zdanie M.S. Taki trick poprawi dokładność kiedy program oparty jest na przerwaniach. Jeśli używamy licznika 16-bit i większego prescalera to nie ma to rzeczywiście znaczenia. Gorzej kiedy licznik byłby 8-bit i liczyłby szybko- błedy wynikające z opóźnień na obsługę przerwań mogą być większe niż się wydaje.
|
|
| Back to top |
|
 |
bishop Poziom 15

Joined: 24 Apr 2003 Posts: 227 Location: Kraków
|
#12
03 Jun 2006 16:58 Re: Timer0 -> Timer1 (ATmega8) |
|
|
|
Kosmo Timer1=34285 wyszło z prostej kalkulacj. przy zegarze 8000000 i preskalerze 256, timer uP'a zliczy 8000000/256= 31250 "impulsów". Czyli aby licznik sie przepelnil nalezy zaczasc zliczanie od 65535-31250=34285.
|
|
| Back to top |
|
 |
kosmo90 Poziom 8

Joined: 24 May 2006 Posts: 28
|
#13
03 Jun 2006 19:40 Re: Timer0 -> Timer1 (ATmega8) |
|
|
|
| bishop wrote: |
| Kosmo Timer1=34285 wyszło z prostej kalkulacj. przy zegarze 8000000 i preskalerze 256, timer uP'a zliczy 8000000/256= 31250 "impulsów". Czyli aby licznik sie przepelnil nalezy zaczasc zliczanie od 65535-31250=34285. |
Ok dziekuje, to już rozumiem. Proszę jeszcze tylko o wyjaśnienie skąd mam wiedzieć, że akurat ta wartość (31250) oznacza zliczanie jednej sekundy?
Co jeśli dałbym preskaler 64? Wtedy 8000000/64 = 125000.
Pozdrawiam!
|
|
| Back to top |
|
 |
Holy Poziom 13

Joined: 01 Jan 2005 Posts: 145 Location: Białystok
|
#14
03 Jun 2006 20:25 Timer0 -> Timer1 (ATmega8) |
|
|
|
Jak masz zegar 8MHz to oznacza, że w ciągu jednej sekundy masz 8000000 taktów. Jeśli masz preskaler, to częstotliwość jest dzielona przez 256. Czyli daje to 31250 taktów na wejściu timera na sekundę. A Twoje przypuszczenie co do preskalera 64 jest całkiem słuszne. :) Trzeba tylko pamiętać, że licznik 16-bitowy ma pojemność 65535, a 8-bitowy 256.
|
|
| Back to top |
|
 |
bishop Poziom 15

Joined: 24 Apr 2003 Posts: 227 Location: Kraków
|
#15
03 Jun 2006 21:26 Re: Timer0 -> Timer1 (ATmega8) |
|
|
|
Jesli dasz prescaler 64 to okolo 2 razy przepelni ci sie timer czyli 2 razy na sekunde wywali ci przerwanie.... dlasz szybszego oliczania wrzucam programik.
|
|
| Back to top |
|
 |
Google

|
#
03 Jun 2006 21:26 |
|
|
|
|
|
| Back to top |
|
 |
Meridian_ Poziom 1

Joined: 07 Aug 2008 Posts: 1
|
#16
20 Sep 2008 17:55 Re: Timer0 -> Timer1 (ATmega8) |
|
|
|
Zdravim muzu mit prosbu....jsem tak trochu amater a nejde mi zkompilovat jeden zdrojacek v BascomAVR a hlasi mi to chybu na "Enable Timer1" jako "Unknown interrupt source[COUNT <>3]" a pak mi to vyhodi i TIMER1.....poradi mi prosim nekdo????mam neco spatne nastavene v kompilatoru????
| Code: |
$regfile = "m8def.dat"
$crystal = 16000000
'----------------------KONFIGURACJA--------------------
Const Falloff = 1
Const Lcd_offset = 1
Const Czulosc = 20
'----------------------STAŁE---------------------------
Const Timer1_h = _xtal / 44000
Const Timer1_l = _xtal / 2000
Reset Watchdog
Config Watchdog = 256
Stop Watchdog
Const Poziom_a = 8 -(czulosc * 0.4)
'------------------------ZMIENNE--------------------------
Dim Div As Iram Integer At 16
Dim K As Byte
Dim I As Byte
Dim Tmp_s As Integer
Dim Tmp_c As Integer
Dim Beta As Iram Byte
Dim Suma As Word
Dim Sam As Byte
Dim Sampling As Bit
Dim Rex_t As Integer , Imx_t As Integer
Dim Dane(32) As Integer
Dim Sample_h(32) As Integer
Dim Sample_l(32) As Integer
Dim Okno(32) As Byte
Dim Rex(16) As Integer
Dim Sinus(40) As Integer
Dim Wynik(20) As Byte , Wynik_o(20) As Byte
Dim Sing As Single
Dim Poziom As Integer
Dim Line1 As String * 20 , Line1d(20) As Byte At Line1 Overlay
Dim Line2 As String * 20 , Line2d(20) As Byte At Line2 Overlay
Dim Line3 As String * 20 , Line3d(20) As Byte At Line3 Overlay
Dim Line4 As String * 20 , Line4d(20) As Byte At Line4 Overlay
Dim Falloff_count(20) As Byte
$lib "lcd4busy.lbx"
Const _lcdport = Portd
Const _lcdddr = Ddrd
Const _lcdin = Pind
Const _lcd_e = 3
Const _lcd_rw = 2
Const _lcd_rs = 1
Config Lcd = 20 * 4
Initlcd
Waitms 10
Initlcd
Cls
Deflcdchar 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 31
Deflcdchar 2 , 0 , 0 , 0 , 0 , 0 , 0 , 31 , 31
Deflcdchar 3 , 0 , 0 , 0 , 0 , 0 , 31 , 31 , 31
Deflcdchar 4 , 0 , 0 , 0 , 0 , 31 , 31 , 31 , 31
Deflcdchar 5 , 0 , 0 , 0 , 31 , 31 , 31 , 31 , 31
Deflcdchar 6 , 0 , 0 , 31 , 31 , 31 , 31 , 31 , 31
Deflcdchar 7 , 0 , 31 , 31 , 31 , 31 , 31 , 31 , 31
Cls
Cursor Off
Config Adc = Single , Prescaler = 4 , Reference = Avcc
Start Adc
Config Timer1 = Timer , Prescale = 1
On Compare1a Sampleh
On Compare1b Samplel
Compare1a = Timer1_h
Compare1b = Timer1_l
Enable Timer1 <<<<<------
Start Timer1
Enable Interrupts
Disable Int0
Disable Int1
|
|
|
| Back to top |
|
 |