PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Interrupt jede Millisekunde



Torrentula
20.10.2011, 18:05
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:




#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;
}
}
}


MfG

Torrentula

TheDarkRose
20.10.2011, 18:17
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.

radbruch
20.10.2011, 18:27
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:


In CTC mode the counter is cleared to zero when the counter value (TCNT0) matches the OCR0.Hier ist atmel scheinbar etwas ungenau, den zu folgender Beschreibung für den "Normal Mode" finde ich keine Entsprechung beim "CTC":

(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

damfino
20.10.2011, 18:28
probiers mal mit Prescaler 64 und OCR0A=230, damit komme ich ungefähr auf diese Zeit.

LG!

Torrentula
20.10.2011, 18:38
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.

sternst
20.10.2011, 21:17
Ich glaube, das -1 ist falsch.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.



Die Uhr läuft auch mit berichtigtem Wert für OCR0A = 1999 zu schnellNatürlich. Wie soll denn auch ein 8-Bit-Zähler bis 1999 zählen können?