Hallo Zusammen, ich benötige eure fachmännische Hilfe bei einem Problem mit dem DCF77 Signal bei einem Atmel ATMega 328p. Wie ihr euch denken könnt möchte ich das das DCF77 Signal empfangen. Der neg. Ausgang des DCF77-Sensor habe ich an den INT0 Eingang PD2 am Atmel angeschlossen. Mit einem Interrupt möchte ich nun im Sekundentakt ein Array hoch zählen. Die Signalzustandserkennung mache ich mit einem Timerinterrupt Timer0. Je nach Zustand schreibe ich dann die Werte in das Array. Leider habe ich das Problem, dass der INT0- Interrupt nicht zuverlässig die fallende Flanke erkennt -> meistens wird er zweimal ausgelöst. Wie empfohlen habe ich einen Pull-Up Widerstand 5,2k zwischen + und neg. Ausgang geschalten. Hier die Interrupt-Konfig: DDRD &= ~(1 << DDD2); PORTD |= (1 << PORTD2); DDRB |= (1 << 4); DDRB |= (1 << 5); EICRA |= (1 << ISC01); //EICRA |= (1 << ISC00); EIMSK |= (1 << INT0); TCCR0A |= (1 << WGM01); OCR0A = 160; TIMSK0 |= (1 << OCIE0A); TCCR0B |= (1 << CS02); TCCR0B |= (1 << CS00); sei(); Nachfolgend die beiden Interrupts: ISR (TIMER0_COMPA_vect) { if(PIND & (1 << PIND2)) { dcf_interrupt_zaehler = 0; dcf_richtimpuls_zaehler++; if(dcf_richtimpuls_zaehler >= 110) { dcf_richtimpuls = 1; dcf_sekunde = 59; dcf_richtimpuls_startpuls++; } } else { dcf_richtimpuls_zaehler = 0; dcf_interrupt_zaehler++; if(dcf_interrupt_zaehler >= 11) { //char Test_PIN_1[] = "** PIN = 1 **"; //Zum Testen //USART_String_Ausgabe(Test_PIN_1); dcf_signalwert = 1; } else { //char Test_PIN_0[] = "** PIN = 0 **"; //Zum Testen //USART_String_Ausgabe(Test_PIN_0); dcf_signalwert = 0; } } if(dcf_signalwert == 1) { PORTB |= (1 << 5); } if(dcf_signalwert == 0) { PORTB &= ~(1 << 5); } } ISR (INT0_vect) { PORTB ^= (1 << 4); if((dcf_richtimpuls == 0) && (dcf_richtimpuls_startpuls <= 1)) { char wait[] = "."; USART_String_Ausgabe(wait); } else { Wochentag(); char leer[] = " "; USART_String_Ausgabe(leer); Tag(); char punkt[] = "."; USART_String_Ausgabe(punkt); Monat(); USART_String_Ausgabe(punkt); Jahr(); USART_String_Ausgabe(leer); Stunde(); char dpunkt[] = ":"; USART_String_Ausgabe(dpunkt); Minute(); USART_String_Ausgabe(dpunkt); Sekunde(); char breakpoint[] = " *** "; USART_String_Ausgabe(breakpoint); } DCF_Signalwerte[dcf_sekundenzaehler] = dcf_signalwert; dcf_signalwert = 0; dcf_sekundenzaehler++; if (dcf_sekunde < 58) { dcf_sekunde++; } if (dcf_sekunde == 59) { dcf_sekunde = 0; dcf_sekundenzaehler = 0; } } ////// Kann mir bitte jemand weiterhelfen oder hat jemand eine Idee was ich bessermachen sollte. VIELEN DANK FÜR EURE HILFE. Grüße Micha
A. K. schrieb im Beitrag #4522762:
> Mit Timer alle N ms abfragen
N darf dabei gerne gleich 20 sein ...
Die ganzen Berechnungen und USART-Ausgabe sind völlig zeitunkritisch und
haben in der ISR vom INT0 nichts zu suchen.
Manche DCF77 Receiver erzeugen ein instabiles quasi "prellendes" Signal im Übergang. Frag den Pin im Timer-Interrupt alle N msec ab, direkt ohne Pin-Interrupt, dann stört das nicht.
W.A. schrieb: > Die ganzen Berechnungen und USART-Ausgabe sind völlig zeitunkritisch und > haben in der ISR vom INT0 nichts zu suchen. Nicht nur das, die UART-Asugabe ist für die Timer-ISR u.U. zu langsam.
@A.K. Danke für eine Hilfe soll ich dann den Eingang PD2 nur noch mit der _delayms() Funktion von delay.h abfragen. Ich hätte den Pininterrupt auch als Sekundenzähler genommen.
Micha schrieb: > @A.K. Danke für eine Hilfe soll ich dann den Eingang PD2 nur noch mit > der _delayms() Funktion von delay.h abfragen. Nein. Timer auf 20msec programmieren und den Pin in dessen ISR abfragen. Mitzählen wie lang in low/high Zustand und das auswerten. Komplexe Auswertung und Anzeige gehört ins Hauptprogramm. > Ich hätte den Pininterrupt auch als Sekundenzähler genommen. DCF77 taugt nicht als Interrupt-Quelle. Selbst im Idealfall fehlt jede Minute einer, von gestörtem Signal oder den beobachteten Effekten ganz abgesehen. Im gleichen Timer eine Variable zählen, die alle 50x die Sekunde zählt.
:
Bearbeitet durch User
@A.K. danke für deine Hilfe. Das ist eine gute Idee. Wie würdest du dann die Synchronisation machen ich muss ja immer wissen wann ein signal anfängt.
Den Wechsel des Zustands eines Pins gegenüber dem letzten Mal zu erkennnen wirst du hoffentlich selber schaffen. Dann mitzählen, wieviele Timer-Ticks dieser Zustand anhält. Der Rest ergibt sich direkt daraus. Das Hauptprogramm braucht 2 Informationen: - Pin hat den Zustand gewechselt, L=>H / H=>L - Wieviele Ticks sind seit dem letzten Wechsel vergangen.
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.