DCF77 Signalerfassung mit ATMega 328p in C

Gast #4522754
Lesenswert?
• ▲
▼
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
Lesenswert?
• ▲
▼
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.
#4522784
Lesenswert?
• ▲
▼
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.
#4522801
Lesenswert?
• ▲
▼
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren