Forum: Mikrocontroller und Digitale Elektronik DCF77 Dekodierung liefert falsche Werte


von Ingo M. (daddy)


Lesenswert?

Hallo,
ich vesuche schon seit Tagen ein DCF-Signal zu entschlüsseln.

Prinzipiell habe ich es am laufen,
leider stimmt die Minute und der Tag nicht,
der Rest ist iO.

Die Minuten sind immer 1-2 zuviel,
der Tag ist immer 7 anstatt 8.
Sekunde, Stunde, Wochentag und Jahr stimmen immer.

Jetzt liegt der Schluss nahe,
dass ich die Daten falsch zusammen setze,
würde ich aber verneinen da ich die Bits einzeln behandle.

Im folgenden mein Quellcode,
evtl. kann jemand den Fehler finden.

Da ich gerade beim C Lernen bin bitte ich die etwas umständliche 
Programmierung zu entschuldigen,
Verbesserungsvorschläge nehme ich gerne an.
Allerdings möchte ich nicht irgen einen Code verwenden, ohne ihn zu 
verstehen.

Liebe Grüße daddy

//----------------------------------------
// ISR Aufruf jede Millisekunde
//----------------------------------------
void interrupt ISR(void){
if((TMR1IE)&&(TMR1IF)){  // TMR1IE:Timerüberlauf TMR1IF:Timerinterrupt
  Millisek++;
  // Timer neu starten mit Konfiguration für 1ms
  TMR1H=0xFE;
  TMR1L=0x12; // rechnerisch 0b
  TMR1IF=0;
  // Interne Zeit berechnen
  if(Millisek==1000){Sekunde++;Millisek=0;
    if(Sekunde==60){Minute++;Sekunde=0;}
    if(Minute==60){Stunde++;Minute=0;}
    if(Stunde==24){Stunde=0;}}
  DCF();
}}// Ende ISR


//----------------------------------------
// DCF-Routine (Aufruf alle 1ms)
//----------------------------------------
void DCF(){
DCFPORTNEU=DCFin;    // Signal speichern für ISR
if(DCFSTART==1){    // Telegrammstart ist gefunden, Bits werden 
mitgezählt
  // Auf positive Flanke warten
  if(DCFPORTNEU==1 && DCFPORTALT==0){
    // Nur beim ersten Impuls
    if(DCFSYNC==1){
      Sekunde=0;  // Innere Uhr nullen
      Millisek=0;  // Innere Uhr nullen
      DCFSYNC=0;  // Nullung nicht mehr durchführen
    }
    DCFMILLISEK=0;
    DCFSEKZ++;    // Zählt die Impulse
    goto marke1;
  }
  DCFMILLISEK++;    // Millisekunden weiterzählen bis Signalende
  // Signalende erreicht?
  if(DCFPORTALT==1 && DCFPORTNEU==0){
    // Low empfangen?
    if(DCFMILLISEK>=80 && DCFMILLISEK<=120){
      DCFHIGH=0;
      goto marke1;
    }
    // High empfangen?
    if(DCFMILLISEK>=180 && DCFMILLISEK<=220){
      DCFHIGH=1;
      goto marke1;
    }
    // Dann wars ein Fehler
    DCFFEHLER=1;
    DCFHIGH=0;
    DCFSTART=0;  // Auf nächsten Telegrammstart warten
    goto marke1;
  }
  else{goto marke1;}
}
// Auf Telegrammstart warten
else{
  // Bei High weiter warten
  if(DCFPORTNEU==1){
    DCFMILLISEK=0;
    goto marke1;
  }
  DCFMILLISEK++;
  // Auf den Telegrammstart warten
  if(DCFMILLISEK<=1500){
    goto marke1;
  }
  DCFSTART=1;    // Bitaufzeichnung starten
  DCFFEHLER=0;  // Fehlerbit löschen
  DCFHIGH=0;
  DCFSEKZ=0;    // Schleifenzähler für DCF-Impulse
  DCFSYNC=1;    // DCF-Start, Sekunden 0, Millisekunden 0
  goto marke2;
}
marke1:
NOP();
// Da Schleifenzähler 1 zu groß ist
DCFSEKUNDE=DCFSEKZ;
DCFSEKUNDE--;
goto marke2;
marke2:
NOP();
// Zu lange gewartet? (kein Signal)
if(DCFMILLISEK>=2000){
  DCFMILLISEK=0;
  DCFFEHLER=1;
  }
DCFPORTALT=DCFPORTNEU;
}// Ende DCF


Dekodierung und Speichern im Hauptprogramm

//----------------------------------------
// DCF-Signal verarbeiten
//----------------------------------------
void DCFDATEN(){
if(DCFSTART==1 && DCFSEKUNDE>=20 && DCFHIGH==1){
  switch(DCFSEKUNDE){
  case 21:DCF21=1;break;
  case 22:DCF22=1;break;
  case 23:DCF23=1;break;
  case 24:DCF24=1;break;
  case 25:DCF25=1;break;
  case 26:DCF26=1;break;
  case 27:DCF27=1;break;
  case 28:DCF28=1;break;
  case 29:DCF29=1;break;
  case 30:DCF30=1;break;
  case 31:DCF31=1;break;
  case 32:DCF32=1;break;
  case 33:DCF33=1;break;
  case 34:DCF34=1;break;
  case 35:DCF35=1;break;
  case 36:DCF36=1;break;
  case 37:DCF37=1;break;
  case 38:DCF38=1;break;
  case 39:DCF39=1;break;
  case 40:DCF40=1;break;
  case 41:DCF41=1;break;
  case 42:DCF42=1;break;
  case 43:DCF43=1;break;
  case 44:DCF44=1;break;
  case 45:DCF45=1;break;
  case 46:DCF46=1;break;
  case 47:DCF47=1;break;
  case 48:DCF48=1;break;
  case 49:DCF49=1;break;
  case 50:DCF50=1;break;
  case 51:DCF51=1;break;
  case 52:DCF52=1;break;
  case 53:DCF53=1;break;
  case 54:DCF54=1;break;
  case 55:DCF55=1;break;
  case 56:DCF56=1;break;
  case 57:DCF57=1;break;
  case 58:DCF58=1;break;
  }
  DCFHIGH=0;
}

if(DCFFEHLER==0 && DCFSEKUNDE==28){
  DCFMINUTE=0;
  Temp=0;
  if(DCF21==1){DCFMINUTE=DCFMINUTE+1;Temp++;}
  if(DCF22==1){DCFMINUTE=DCFMINUTE+2;Temp++;}
  if(DCF23==1){DCFMINUTE=DCFMINUTE+4;Temp++;}
  if(DCF24==1){DCFMINUTE=DCFMINUTE+8;Temp++;}
  if(DCF25==1){DCFMINUTE=DCFMINUTE+10;Temp++;}
  if(DCF26==1){DCFMINUTE=DCFMINUTE+20;Temp++;}
  if(DCF27==1){DCFMINUTE=DCFMINUTE+40;Temp++;}
  if(DCF28==1){Temp++;}
  if(Temp%2==0){Minute=DCFMINUTE;}}
//  Minute=DCFMINUTE;}

if(DCFFEHLER==0 && DCFSEKUNDE==35){
  DCFSTUNDE=0;
  Temp=0;
  if(DCF29==1){DCFSTUNDE=DCFSTUNDE+1;Temp++;}
  if(DCF30==1){DCFSTUNDE=DCFSTUNDE+2;Temp++;}
  if(DCF31==1){DCFSTUNDE=DCFSTUNDE+4;Temp++;}
  if(DCF32==1){DCFSTUNDE=DCFSTUNDE+8;Temp++;}
  if(DCF33==1){DCFSTUNDE=DCFSTUNDE+10;Temp++;}
  if(DCF34==1){DCFSTUNDE=DCFSTUNDE+20;Temp++;}
  if(DCF35==1){Temp++;}
  if(Temp%2==0){Stunde=DCFSTUNDE;}}
//  Stunde=DCFSTUNDE;}

if(DCFFEHLER==0 && DCFSEKUNDE==58){
  DCFTAG=0;
  Temp=0;
  if(DCF36==1){DCFTAG=DCFTAG+1;Temp++;}
  if(DCF37==1){DCFTAG=DCFTAG+2;Temp++;}
  if(DCF38==1){DCFTAG=DCFTAG+4;Temp++;}
  if(DCF39==1){DCFTAG=DCFTAG+8;Temp++;}
  if(DCF40==1){DCFTAG=DCFTAG+10;Temp++;}
  if(DCF41==1){DCFTAG=DCFTAG+12;Temp++;}
  DCFWOCHENTAG=0;
  if(DCF42==1){DCFWOCHENTAG=DCFWOCHENTAG+1;Temp++;}
  if(DCF43==1){DCFWOCHENTAG=DCFWOCHENTAG+2;Temp++;}
  if(DCF44==1){DCFWOCHENTAG=DCFWOCHENTAG+4;Temp++;}
  DCFMONAT=0;
  if(DCF45==1){DCFMONAT=DCFMONAT+1;Temp++;}
  if(DCF46==1){DCFMONAT=DCFMONAT+2;Temp++;}
  if(DCF47==1){DCFMONAT=DCFMONAT+4;Temp++;}
  if(DCF48==1){DCFMONAT=DCFMONAT+8;Temp++;}
  if(DCF49==1){DCFMONAT=DCFMONAT+10;Temp++;}
  DCFJAHR=0;
  if(DCF50==1){DCFJAHR=DCFJAHR+1;Temp++;}
  if(DCF51==1){DCFJAHR=DCFJAHR+2;Temp++;}
  if(DCF52==1){DCFJAHR=DCFJAHR+4;Temp++;}
  if(DCF53==1){DCFJAHR=DCFJAHR+8;Temp++;}
  if(DCF54==1){DCFJAHR=DCFJAHR+10;Temp++;}
  if(DCF55==1){DCFJAHR=DCFJAHR+20;Temp++;}
  if(DCF56==1){DCFJAHR=DCFJAHR+40;Temp++;}
  if(DCF57==1){DCFJAHR=DCFJAHR+80;Temp++;}
  if(DCF58==1){Temp++;}
// 
if(Temp%2==0){Tag=DCFTAG;Wochentag=DCFWOCHENTAG;Monat=DCFMONAT;Jahr=DCFJ 
AHR;}
  Tag=DCFTAG;Wochentag=DCFWOCHENTAG;Monat=DCFMONAT;Jahr=DCFJAHR;
  DCF21=0;
  DCF22=0;
  DCF23=0;
  DCF24=0;
  DCF25=0;
  DCF26=0;
  DCF27=0;
  DCF28=0;
  DCF29=0;
  DCF30=0;
  DCF31=0;
  DCF32=0;
  DCF33=0;
  DCF34=0;
  DCF35=0;
  DCF36=0;
  DCF37=0;
  DCF38=0;
  DCF39=0;
  DCF40=0;
  DCF41=0;
  DCF42=0;
  DCF43=0;
  DCF44=0;
  DCF45=0;
  DCF46=0;
  DCF47=0;
  DCF48=0;
  DCF49=0;
  DCF50=0;
  DCF51=0;
  DCF52=0;
  DCF53=0;
  DCF54=0;
  DCF55=0;
  DCF56=0;
  DCF57=0;
  DCF58=0;
  DCFSTART=0;
  DCFFEHLER=1;
}
}

von Matthias L. (matze88)


Angehängte Dateien:

Lesenswert?

Da hat jetzt sicherlich jeder Lust, sich diesen irren Code anzuschauen.

Warum liest du die wichtigen Regeln die über dem 
Post-Erstell-Eingabefenster stehen nicht?
Längeren Sourcecode NICHT im Text einfügen sondern als Dateianhang!

Und auch bei kürzerem Code bitte die Formatierungen die das Forum bietet 
nutzen! Syntaxhighlighting!

Habe mich mal erbarmt, den Code in den Anhang zu packen

von Ingo M. (daddy)


Lesenswert?

Hallo Matthias,
danke für deinen Hinweis, war mein erster Post im Forum...

Das heißt ich muss den C-Code so posten wenn nicht im Anhang?
1
C-Code
// C-Code
1
C-Code

Gruß daddy

von Thilo M. (Gast)


Lesenswert?

Achte auch darauf, dass die Antenne nicht in direkter Nähe (< 1.5m) von 
Elektrogeräten ist, sowie die Masse der Antenne (und evtl. der Schirm 
des Kabels) sauber geerdet ist.
Ich hatte auf die Weise auch schon die lustigsten Daten gekriegt.

von Ingo M. (daddy)


Lesenswert?

Hallo,
das Signal kommt sauber an, das kann ich beobachten.

Das mit dem Tag habe ich gefunden,
hab mir den Wochentag angesehen =7 anstatt 8 :-(

Nur das mit den Minuten macht mir noch kopfzerbrechen,
habs im Moment so gelöst, dass ich immer eine abziehe, weiß aber nicht 
warum das sein muss...
1
C-Code
if(Temp%2==0){Minute=DCFMINUTE;Minute--}}
1
C-Code

Wenn ich das mache stimmen immer alle Daten,
ein Auslassen beim Umbruch brauche ich um nicht auf 255 Min zu kommen.
Aber die innere Uhr zählt ja weiter :-)

Habe jetzt quasi ein Workaround,
würde aber gerne meinen Fehler finden und den Mist wieder beseitigen...

Ich wünsche eine gute Nacht und danke euch allen.

Da ich mich jetzt intensiver mit der uP-Programmierung befassen möchte,
denke ich wir lesen öfter voneinander.

Gruß daddy

von hans (Gast)


Lesenswert?

Ich habe deinen Code nicht angesehen, aber ich vermute, daß du das
DCF77 falsch verstehst. Übertragen wird immer die Zeitinformation der
nächsten Minute. Diese begint dann mit dem Startbit!

Um 21:09 empfängst du also die Werte für 21:10 !

Das könnte dein Minutenproblem sein.

gruß hans

von gast (Gast)


Lesenswert?

hier musst du bestimmt die 12 gegen eine 20 ersetzen:

  if(DCF41==1){DCFTAG=DCFTAG+12;Temp++;}

Gruß

Rolf

von Gast (Gast)


Lesenswert?

Du hast das mit der Formatierung noch nicht so ganz drauf.
So musst du das machen:

[d]
// DEIN CODE
if (a==b) //bsp
[/d]

Die d in den eckigen Klammern durch c ersetzen dann gehts.
Ergebnis:
1
// DEIN CODE
2
if (a==b) //bsp

von Ingo M. (daddy)


Lesenswert?

hans wrote:
> Ich habe deinen Code nicht angesehen, aber ich vermute, daß du das
> DCF77 falsch verstehst. Übertragen wird immer die Zeitinformation der
> nächsten Minute. Diese begint dann mit dem Startbit!
>
> Um 21:09 empfängst du also die Werte für 21:10 !
>
> Das könnte dein Minutenproblem sein.
>
> gruß hans

Hallo,
das war mein Fehler.

Ich danke für die Hilfe,
wede mich nun daran machen den Code zu verkürzen.

Hast mir geholfen,

Gruß daddy

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
Noch kein Account? Hier anmelden.