PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : DCF77 Dekodieren, Probleme mit Timer0



elayne
02.01.2008, 16:31
Hey,
Ich hab schon einige Erfolge in Assembler erziehlt und will nun in C einstegen. Ich habe schon einige Tutorials durch und wollte mit meinem ersten Projekt beginnen. Wie so oft: Ein Funkwecker mittles DCF 77 Modul. Ich habe mir die Grundschaltung mit einem ATmega16 aufgebaut. Vorerst wollte ich das Signal nur einlesen und per UART an meinen PC senden. Dazu habe ich mir gedacht:

- Timer0 löst alle 10ms einen Interrupt aus
- In dem Interrupt wird das DCF 77 Signal abgefragt
- Wenn es low ist wird eine Variable um 1 erhöht
- Wenn es high ist wird die Variable per UART ausgegeben und auf 0 gesetzt

Somit bekomme ich die Pausenzeiten im Hyperterminal und kann mir vorerst manuell die Uhrzeit berechnen.

Mein Problem liegt am Timer. Ich benuze einen Oszillator mit der Frequenz 16Mhz. Um die 10ms zu realisieren habe ich Timer0 mit einem Vorteiler von 64 laufen. Eine Zählschleife wird auf 2500 hochgezählt bis eine Aktion startet.

Meine Rechnung war 16M / 64 / 2500 = 100
davon der Kehrwert ist 0,01 so wie ich es will. Nur funktioniert das ganze nicht. Es läuft viel zu langsam und ich weiss nicht was ich falsch gemacht habe. Ich hoffe einer von euch kann mal kurz über den Code schauen weil ich denke ich habe etwas total offensichtliches falsch gemacht und übersehe es.

Der Code ist nur vorläufig, weil ich erstmal sehen will wie das klappt. Im moment läuft alles in der Interruptroutine ab. Das man das nicht machen sollte weiß ich und sobald es geht werde ich es auch ändern.

Hier sind die deklerationen der Variablen
volatile int32_t t,x,zahl,foo;
volatile char c;
Hier ist die Initialisierung der Timer:

TCCR0 |= (1 << CS01 ) | (1 << CS00) ; // Timer0 initialisierung
TCCR0 &= ~(1 <<CS02 ); // Vorteiler ist 64
TIMSK |= (1<<TOIE0); // Interrupt aktivieren


Hier ist die Interruptfunktion:

ISR(TIMER0_OVF_vect)
{

if (t==2500) //Wenn Timer0 2500 mal übergelaufen ist
{
t = 0; //Zählvariable zurücksetzen

if ( !(PINB & (1<<PINB1)) ) //Wenn signaleingang low ist
{
zahl++; //incrementiere Variable zahl
}

else //Wenn signaleingan high ist
{
while (!(UCSRA & (1<<UDRE))) // warten bis Senden moeglich
{
}
UDR = 'x' ; // sende Kontrollzeichen x


c = zahl + '0'; //Wandle Variable Zahl in ASCII um
while (!(UCSRA & (1<<UDRE))) // warten bis Senden moeglich
{
}
UDR = c ; //Sende Pausenzeit
zahl = 0; //setze Zahl auf 0 zurück
}
}




else //Wenn Timer0 noch läuft
{
t++ ; //incrementiere t

}


}

Danke schonmal im Voraus!

Gruß
elayne

Hubert.G
02.01.2008, 17:24
Ich nehme mal an du hast die 256 übersehen die es braucht bis der ISR(TIMER0_OVF_vect) ausgelöst wird. Rechnung 16000000 / 64 / 256 /2500

elayne
02.01.2008, 17:29
Kopf -> Wand!
Arghs ich wusste die ganze Zeit das mich was stört, das ich da nich draufgekommen bin...

Danke!!!