PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Atmega: Sekunden in Takt umrechnen



Wombatz
02.01.2012, 17:10
Hallo zusammen,

ich bin da erneut auf ein kleines Problem gestoßen. Vielleicht kann mir einer Erleutung bringen.
Zu meinem Problem:
Ich versuche mit einem Timer genaue Sekunden zu zählen (z.B. für eine einfache Uhr).
Wenn ich also einen Takt von 1Mhz habe, sollte es nach meinem Verständnis um 1 000 000 Takte die Sekunde handeln.
Wenn ich nun den Timer0 nehme und den Timercounter auf 56 setze, zählt der Timer von 56-256, was 200 Takte entspricht.
Also nach Adamriese:
1000000 : 200 = 5000
Wenn ich einen Timer0-Overflow-Interrupt einschalte, führt das zu 5000 Interrupts die Sekunde.
=> allerdings entspricht die Rechnung keine Sekunde!!!
Was habe ich hier nicht richtig verstanden???

Danke für eure Hilfe

Bernd_Stein
02.01.2012, 17:19
Hallo,

soweit für mich alles richtig. Zeig doch mal dein Programm. Und schreib doch mal wieso das nicht stimmen soll.
Wenn das Programm allerdings nicht in Assembler ist, kann ich nicht weiter helfen.

Bernd_Stein

radbruch
02.01.2012, 17:36
Wenn ich nun den Timer0 nehme und den Timercounter auf 56 setze......, dann unterschlage ich die durch den Aufruf der ISR und das Setzen des TCNT0-Register verlorenen Takte:

SIGNAL (SIG_OVERFLOW0)
{
TCNT0 += 56+3; // +drei Takte für das Lesen und erneute Setzen von TCNT0 berücksichtigen.
...

Nach dem Überlauf wird TCNT0 weitergezählt. In der ISR werden der aktuelle Zählerstand und die Registerladetakte berücksichtigt.

Plan B: Timer läuft im CTC-Mode mit 200 als OCR0...

Kampi
02.01.2012, 17:51
Welchen Mega benutzt du den? Wenn du einen Mega32 benutzt kannst du mit dem Timer1 (16-Bit Timer) 1 Sekunde generieren.
Ansonsten nimm ein 32kHz Quarz damit kannst du besser 1 Sekunde realisieren als mit 1MHz

Wombatz
02.01.2012, 18:10
Ich benutze den Atmega8 und hier ist der code. Den Printbefehl habe ich nur zur Kontrolle eingefügt.


$regfile = "m8def.dat"
$crystal = 1000000
$baud = 57600

Tccr0 = &B00000001
Timsk.toie0 = 1

Ddrb = &B00000001

On Timer0 Zaehler

Dim Count As Word
Dim Sekunde As Byte
Dim Minute As Byte
Dim Stunde As Byte

Count = 0
Sekunde = 0
Minute = 0
Stunde = 0

Tcnt0 = 55

Sreg.7 = 1

Do

If Count = 5000 Then
Sekunde = Sekunde + 1
Count = 0
Portb.0 = Not Portb.0

If Sekunde = 60 Then
Sekunde = 0
Minute = Minute + 1
If Minute = 60 Then
Minute = 0
Stunde = Stunde + 1
If Stunde = 24 Then
Stunde = 0
End If
End If
End If
End If

'Print Stunde ; ":" ; Minute ; ":" ; Sekunde
Loop

Zaehler:

Count = Count + 1
Tcnt0 = 55

Return

Danke für die schnellen Antworten...

radbruch
02.01.2012, 19:19
Lass mich raten: Deine Uhr läuft zu langsam.

Hier ein Beispiel für die Frequenzkorrektur in der Overflow-ISR mit 36kHz und Timer2:
https://www.roboternetz.de/community/threads/46233-nibobee-IR-Abstandsmessung?p=444004&viewfull=1#post444004
https://www.roboternetz.de/community/threads/45487-NIBOBee-mit-BASCOM-Programmieren?p=444260&viewfull=1#post444260

Wombatz
02.01.2012, 19:37
ja die Uhr läuft zu langsam.

Verstehe ich das richtig??? Durch den Aufruf der ISR verstreichen Takte die man mit += ausgleichen kann??

Danke für deine Antwort...bist echt super!!!

radbruch
02.01.2012, 19:51
Jepp, wenn die ISR aufgerufen wird verstreichen einige Zähltakte. Und zwar nicht nur durch das Ermitteln der Sprungadresse, speichern der Rücksprungadresse auf dem Stack und dem Sprung und Rücksprung zur ISR sondern auch durch das Speichern und Zurückladen der wichtigsten Register. (Stichwort: nosave). Dadurch ist zu Beginn der ISR der Zähler schon deutlich größer als 0 und diese Zähltakte verlängern letztlich deine Sekunden...

P.S.:

Danke für deine Antwort...bist echt super!!!Danke für's Lob :)