DCF77 Signalerfassung mit ATMega 328p in C

Gast #4522754
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
Gast #4522773
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.
Gast #4522780
@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.
#4522784
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.
Gast #4522797
@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.
#4522801
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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 10 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.