Für solche Sachen solltest du einen speziellen Uhrenquarz verwenden. Der hat ne ganz krumme MHz Zahl, aber mit dieser kann sich dann genau die Zeit berechnen lassen.
Hallo RNler!
Ich habe vor eine Uhr zu bauen mithilfe meines RN-Control (nur testweise). Der Mega644 läuft mit 16MHz und ich verwende Timer0 im CTC modus mit Prescaler 8. Berechnet habe ich den Wert für das Compare-Register OCR0A folgendermaßen:
((16000000 / 8 ) / 1000) - 1 = 199
Ist da etwas falsch? In der ISR lasse ich nur millisekunden, sekunden, minuten und stunden inkrementieren / zurücksetzen. Trotzdem dauert für den Controller 1 Minute nur ungefähr 6 Sekunden^^. Mein Code sieht so aus:
MfGCode:#define F_CPU 16000000UL #include <avr/io.h> #include <avr/interrupt.h> #include <stdlib.h> #include "standards.h" volatile unsigned int milliseconds; volatile unsigned int seconds; volatile unsigned int minutes; volatile unsigned int hours; char buffer[10]; int main(void) { init_USART(); senchar('v'); TCCR0A = (1<<WGM01); // CTC Mode of Timer 0 TCCR0B |= (1<<CS01); // Prescaler 8 // ((16000000 / 8) / 1000) = 200 OCR0A = 200-1; // to get 200 steps TIMSK0 |= (1<<OCIE0A); // Enable compare interrupt // global interrupt enable sei(); DDRC |= 0x01; PORTC |= 0x01; while(1) { itoa(minutes, buffer, 10); sendUSART(buffer); } } // The compare match handler is called every time // TCNT0 = OCR0A = 200 - 1 (200 steps) which gives us // exactly 1ms ISR (TIMER0_COMPA_vect){ milliseconds++; if(milliseconds == 1000){ seconds++; milliseconds = 0; if(seconds == 60){ minutes++; seconds = 0; } if(minutes == 60){ hours++; minutes = 0; } if(hours == 24){ hours = 0; } } }
Torrentula
Geändert von Torrentula (20.10.2011 um 18:16 Uhr)
MfG Torrentula
Für solche Sachen solltest du einen speziellen Uhrenquarz verwenden. Der hat ne ganz krumme MHz Zahl, aber mit dieser kann sich dann genau die Zeit berechnen lassen.
Kultuverein Metal Resurrection, für mehr Bands und Konzerte in Österreich (:
Hallo
Die Werte sind nicht initialisiert.
Zu: OCR0A = 200-1; // to get 200 steps
Ich glaube, das -1 ist falsch. Bei 200 wird das Zählregister mit 0 beschrieben und dann der Interrupt ausgeführt. Beim Zählen der ms schreibst du ja auch bei 1000 die 0 rein und nicht schon bei 999:
Hier ist atmel scheinbar etwas ungenau, den zu folgender Beschreibung für den "Normal Mode" finde ich keine Entsprechung beim "CTC":In CTC mode the counter is cleared to zero when the counter value (TCNT0) matches the OCR0.
(In normal operation) the Timer/Counter Overflow Flag (TOV0) will be set in the same timer clock cycle as the TCNT0 becomes zero.
Was ist daran "krumm"?
32768 kHz
http://www.google.de/search?q=frequenz+uhrenquarz
Gruß
mic
Bild hier
Atmel’s products are not intended, authorized, or warranted for use
as components in applications intended to support or sustain life!
probiers mal mit Prescaler 64 und OCR0A=230, damit komme ich ungefähr auf diese Zeit.
LG!
alles über meinen Rasenmäherroboter (wer Tippfehler findet darf sie gedanklich ausbessern, nur für besonders kreative Fehler behalte ich mir ein Copyright vor.)
Die Uhr läuft auch mit berichtigtem Wert für OCR0A = 1999 zu schnell und laut allgemeiner Formel für den CTC Modus sollte dieser Wert bei einem Prescaler von 8 und einer Quartzfrequenz von 16MHz eine Interrupt-Frequenz von 1000Hz also jede Millisekunde ergeben.
MfG
Torrentula
EDIT: Damfino bringt die Lösung einfach mal Prescaler 64 probieren... macht für OCR0A dann 249.
Kann ich die Ausgaben mehrerer itoa() in einen String kombinieren den ich dann an das 7 Segment display sende, so dass mir Stunden + Minuten angezeigt werden? wenn ich die Daten nämlich nicht an einem Stück sende kommt Mist raus.
Geändert von Torrentula (20.10.2011 um 18:46 Uhr)
MfG Torrentula
Nein, das ist richtig. Die Beschreibung im Datenblatt ist zwar etwas missverständlich, aber die Formel ein Stück weiter ist dafür absolut eindeutig.Zitat von radbruch
Natürlich. Wie soll denn auch ein 8-Bit-Zähler bis 1999 zählen können?Zitat von Torrentula
MfG
Stefan
Lesezeichen