www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik DCF77 Signal: in Dec umwandeln


Autor: Rene K. (draconix)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich wandle gerade mein DCF Signal Welches in einem 58fach Array liegt 
(0-1) folgendermaßen um:


void dcf_calc(void) {
     char *TestCRCOut;
     is_dcf_ok = 0;
     dcf_calc_v  = 0;
     
     if(dcf_bitmask[20] == 1) {

             // Calc Stunde
             dcf_Stunde = 0;
             if(dcf_bitmask[29] == 1) dcf_Stunde = dcf_Stunde + 1;
             if(dcf_bitmask[30] == 1) dcf_Stunde = dcf_Stunde + 2;
             if(dcf_bitmask[31] == 1) dcf_Stunde = dcf_Stunde + 4;
             if(dcf_bitmask[32] == 1) dcf_Stunde = dcf_Stunde + 8;
             if(dcf_bitmask[33] == 1) dcf_Stunde = dcf_Stunde + 10;
             if(dcf_bitmask[34] == 1) dcf_Stunde = dcf_Stunde + 20;

             // Calc Minuten
             dcf_Minute = 0;
             if(dcf_bitmask[21] == 1) dcf_Minute = dcf_Minute + 1;
             if(dcf_bitmask[22] == 1) dcf_Minute = dcf_Minute + 2;
             if(dcf_bitmask[23] == 1) dcf_Minute = dcf_Minute + 4;
             if(dcf_bitmask[24] == 1) dcf_Minute = dcf_Minute + 8;
             if(dcf_bitmask[25] == 1) dcf_Minute = dcf_Minute + 10;
             if(dcf_bitmask[26] == 1) dcf_Minute = dcf_Minute + 20;
             if(dcf_bitmask[27] == 1) dcf_Minute = dcf_Minute + 40;
             
             // Calc Datum Tag
             dcf_Tag     = 0;
             if(dcf_bitmask[36] == 1) dcf_Tag = dcf_Tag + 1;
             if(dcf_bitmask[37] == 1) dcf_Tag = dcf_Tag + 2;
             if(dcf_bitmask[38] == 1) dcf_Tag = dcf_Tag + 4;
             if(dcf_bitmask[39] == 1) dcf_Tag = dcf_Tag + 8;
             if(dcf_bitmask[40] == 1) dcf_Tag = dcf_Tag + 10;
             if(dcf_bitmask[41] == 1) dcf_Tag = dcf_Tag + 20;

             // Calc Datum Monat
             dcf_Monat = 0;
             if(dcf_bitmask[45] == 1) dcf_Monat = dcf_Monat + 1;
             if(dcf_bitmask[46] == 1) dcf_Monat = dcf_Monat + 2;
             if(dcf_bitmask[47] == 1) dcf_Monat = dcf_Monat + 4;
             if(dcf_bitmask[48] == 1) dcf_Monat = dcf_Monat + 8;
             if(dcf_bitmask[49] == 1) dcf_Monat = dcf_Monat + 10;

             // Calc Datum Jahr
             dcf_Jahr = 0;
             if(dcf_bitmask[50] == 1) dcf_Jahr = dcf_Jahr + 1;
             if(dcf_bitmask[51] == 1) dcf_Jahr = dcf_Jahr + 2;
             if(dcf_bitmask[52] == 1) dcf_Jahr = dcf_Jahr + 4;
             if(dcf_bitmask[53] == 1) dcf_Jahr = dcf_Jahr + 8;
             if(dcf_bitmask[54] == 1) dcf_Jahr = dcf_Jahr + 10;
             if(dcf_bitmask[55] == 1) dcf_Jahr = dcf_Jahr + 20;
             if(dcf_bitmask[56] == 1) dcf_Jahr = dcf_Jahr + 40;
             if(dcf_bitmask[57] == 1) dcf_Jahr = dcf_Jahr + 80;
             
             crc_read = 0;
             if(crc_old_minute[0] == dcf_Minute + 4) {crc_read++;}
             if(crc_old_minute[1] == dcf_Minute + 3) {crc_read++;}
             if(crc_old_minute[2] == dcf_Minute + 2) {crc_read++;}
             if(crc_old_minute[3] == dcf_Minute + 1) {crc_read++;}

             crc_old_minute[3] = crc_old_minute[2];
             crc_old_minute[2] = crc_old_minute[1];
             crc_old_minute[1] = crc_old_minute[0];
             crc_old_minute[0] = dcf_Minute + 5;

//             itoa(TestCRCOut,crc_read);
//             UART1_Write_text(TestCRCOut);


             if(crc_read >= 3)
             {
                  Tag = dcf_Tag;
                  Monat = dcf_Monat;
                  Jahr = dcf_Jahr;
                  
                  Stunde = dcf_Stunde;
                  Minute = dcf_Minute;
                  sekunde = 0;
                  is_dcf_ok = 1;
             }
     }
}

Da selbstverständlich die Abfragen mit IF jede Menge speicher kostet, 
würde ich dies sehr gerne etwas "anders" machen.

Hat jemand einen kleinen Tipp parat?!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rene K. schrieb:

> Hat jemand einen kleinen Tipp parat?!

Finde die Gemeinsamkeit, die all den Codesequenzen gemeinsam ist.

Du hast

  beginnend ab einem bestimmten Arrayindex eine Anzahl x an 'Bits'.
  Jedes darauffolgende Bit hat die doppelte Wertigkeit des
  vorhergehenden, wobei es noch zwischen Einern und Zehnern zu
  unterscheiden gilt.

dieses Wissen kann man in eine/zwei Funktionen zusammenfassen, so dass 
sich zb folgende Auswertung ergibt
             dcf_Stunde = DecodeZehner( dcf_bitmask, 33, 2 ) +
                          DecodeEiner(  dcf_bitmask, 29, 4 );

             dcf_Minute = DecodeZehner( dcf_bitmask, 25, 3 ) +
                          DecodeEiner(  dcf_bitmask, 21, 4 );
             
             dcf_Tag    = DecodeZehner( dcf_bitmask, 40, 2 ) +
                          DecodeEiner(  dcf_bitmask, 36, 4 );

             dcf_Monat  = DecodeZehner( dcf_bitmask, 49, 1 ) +
                          DecodeEiner(  dcf_bitmask, 45, 4 );

             dcf_Jahr   = DecodeZehner( dcf_bitmask, 54, 4 ) +
                          DecodeEiner(  dcf_bitmask, 50, 4 );

Sieht doch schon viel besser aus :-)

Sieht man sich die Zahlen beim Aufruf etwas genauer an, dann findet man 
noch mehr Gemeinsamkeiten. Zb hat man in allen Fällen immer 4 Stellen 
für die Einer (also die volle Dröhnung), d.h. die einzelnen Fälle 
unterscheiden sich nur in der Anzahl der Bits für dir Zehner.
Auch gibt es (natrülich) einen Zusammenhang, wo die Zehner-Bits 
anfangen, wenn man den Index der Einer Bits kennt.

All das kann man ausnutzen, um eine einzige Funktion zu schreiben.
             dcf_Stunde = Decode( dcf_bitmask, 29, 6 );
             dcf_Minute = Decode( dcf_bitmask, 21, 7 );             
             dcf_Tag    = Decode( dcf_bitmask, 36, 6 );
             dcf_Monat  = Decode( dcf_bitmask, 45, 5 );
             dcf_Jahr   = Decode( dcf_bitmask, 50, 8 );

und jetzt siehst das doch schon richtig gut aus :-)

Und die Funktion Decode. Jetzt da wir wissen was sie machen muss, ist 
sie ziemlich trivial.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das wäre mir deutlich zuviel Schreibaufwand.

Schau dochmal die einzelnen Fälle an, sie machen doch immer das gleiche: 
Abhängig vom Index (Sekunde) wird auf eine SRAM-Adresse ein Wert 
addiert.
Also einfach ne Tabelle erstellen mit der Adresse und dem Wert, fertig.

Beitrag "DCF77 Uhr in C mit ATtiny26"

Und man muß nicht die Bits erst speichern, das Auswerten kann man in 
"harter Echtzeit" machen.
Pro Bit hast Du eine volle Sekunde Zeit, da langweilt sich die CPU 
entsetzlich.


Peter

Autor: redyszhrtjk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ob das besser ist?
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <stdint.h>
#include <inttypes.h>
#include <strings.h>
#include <math.h>
#include <time.h>

int main()
{
  uint8_t i;
  const uint8_t mult[]={1,2,4,8,10,20,40};
  uint8_t dcf_bitmask[60];
  uint8_t dcf_stunde, dcf_minute;

  /* irgendwelche Werte erzeugen */
  srand(0);
  for(i=0;i<60;i++)
    dcf_bitmask[i]=rand()&1;
  for(i=0;i<60;i++)
    printf("%c",dcf_bitmask[i]+'0');
  printf("\n");

  /* hier gehts los */
  for(dcf_stunde=0,i=0;i<6;i++)
    dcf_stunde+=mult[i]*dcf_bitmask[i+29];
  for(dcf_minute=0,i=0;i<7;i++)
    dcf_minute+=mult[i]*dcf_bitmask[i+21];
  /* usw */
  printf("%"PRIu8":%"PRIu8"\n",dcf_stunde,dcf_minute);
  return EXIT_SUCCESS;
}

Autor: redyszhrtjk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab grad gesehen: Dem mult[] fehlt ein Wert (80).

Autor: Rene K. (draconix)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
redyszhrtjk schrieb:
> Ob das besser ist?

Vielen Dank! Funktioniert wunderbar, der Code ist um einen enormen 
Faktor zurückgegangen.

Peter Dannegger schrieb:
> Und man muß nicht die Bits erst speichern, das Auswerten kann man in
> "harter Echtzeit" machen.
> Pro Bit hast Du eine volle Sekunde Zeit, da langweilt sich die CPU
> entsetzlich.

Ist im Grunde richtig, aber wie du oben erkennen kannst, benötige ich 
die Werte auch um eine 5fache logische Prüfung zu machen, ich hatte 
einige ELV / Reichelt DCF Module, welche enorm gesaut haben auf der 
Leitung.

Übrigens kann ich da die DCF Module von Pollin sehr empfehlen... die von 
Pollin sind, man mag es kaum glauben, die stabilsten und 
störunempfindlichsten DCF Modul die ich bekommen konnte, dicht gefolgt 
von den ELV Dingern.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.