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


von Rene K. (draconix)


Lesenswert?

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


1
void dcf_calc(void) {
2
     char *TestCRCOut;
3
     is_dcf_ok = 0;
4
     dcf_calc_v  = 0;
5
     
6
     if(dcf_bitmask[20] == 1) {
7
8
             // Calc Stunde
9
             dcf_Stunde = 0;
10
             if(dcf_bitmask[29] == 1) dcf_Stunde = dcf_Stunde + 1;
11
             if(dcf_bitmask[30] == 1) dcf_Stunde = dcf_Stunde + 2;
12
             if(dcf_bitmask[31] == 1) dcf_Stunde = dcf_Stunde + 4;
13
             if(dcf_bitmask[32] == 1) dcf_Stunde = dcf_Stunde + 8;
14
             if(dcf_bitmask[33] == 1) dcf_Stunde = dcf_Stunde + 10;
15
             if(dcf_bitmask[34] == 1) dcf_Stunde = dcf_Stunde + 20;
16
17
             // Calc Minuten
18
             dcf_Minute = 0;
19
             if(dcf_bitmask[21] == 1) dcf_Minute = dcf_Minute + 1;
20
             if(dcf_bitmask[22] == 1) dcf_Minute = dcf_Minute + 2;
21
             if(dcf_bitmask[23] == 1) dcf_Minute = dcf_Minute + 4;
22
             if(dcf_bitmask[24] == 1) dcf_Minute = dcf_Minute + 8;
23
             if(dcf_bitmask[25] == 1) dcf_Minute = dcf_Minute + 10;
24
             if(dcf_bitmask[26] == 1) dcf_Minute = dcf_Minute + 20;
25
             if(dcf_bitmask[27] == 1) dcf_Minute = dcf_Minute + 40;
26
             
27
             // Calc Datum Tag
28
             dcf_Tag     = 0;
29
             if(dcf_bitmask[36] == 1) dcf_Tag = dcf_Tag + 1;
30
             if(dcf_bitmask[37] == 1) dcf_Tag = dcf_Tag + 2;
31
             if(dcf_bitmask[38] == 1) dcf_Tag = dcf_Tag + 4;
32
             if(dcf_bitmask[39] == 1) dcf_Tag = dcf_Tag + 8;
33
             if(dcf_bitmask[40] == 1) dcf_Tag = dcf_Tag + 10;
34
             if(dcf_bitmask[41] == 1) dcf_Tag = dcf_Tag + 20;
35
36
             // Calc Datum Monat
37
             dcf_Monat = 0;
38
             if(dcf_bitmask[45] == 1) dcf_Monat = dcf_Monat + 1;
39
             if(dcf_bitmask[46] == 1) dcf_Monat = dcf_Monat + 2;
40
             if(dcf_bitmask[47] == 1) dcf_Monat = dcf_Monat + 4;
41
             if(dcf_bitmask[48] == 1) dcf_Monat = dcf_Monat + 8;
42
             if(dcf_bitmask[49] == 1) dcf_Monat = dcf_Monat + 10;
43
44
             // Calc Datum Jahr
45
             dcf_Jahr = 0;
46
             if(dcf_bitmask[50] == 1) dcf_Jahr = dcf_Jahr + 1;
47
             if(dcf_bitmask[51] == 1) dcf_Jahr = dcf_Jahr + 2;
48
             if(dcf_bitmask[52] == 1) dcf_Jahr = dcf_Jahr + 4;
49
             if(dcf_bitmask[53] == 1) dcf_Jahr = dcf_Jahr + 8;
50
             if(dcf_bitmask[54] == 1) dcf_Jahr = dcf_Jahr + 10;
51
             if(dcf_bitmask[55] == 1) dcf_Jahr = dcf_Jahr + 20;
52
             if(dcf_bitmask[56] == 1) dcf_Jahr = dcf_Jahr + 40;
53
             if(dcf_bitmask[57] == 1) dcf_Jahr = dcf_Jahr + 80;
54
             
55
             crc_read = 0;
56
             if(crc_old_minute[0] == dcf_Minute + 4) {crc_read++;}
57
             if(crc_old_minute[1] == dcf_Minute + 3) {crc_read++;}
58
             if(crc_old_minute[2] == dcf_Minute + 2) {crc_read++;}
59
             if(crc_old_minute[3] == dcf_Minute + 1) {crc_read++;}
60
61
             crc_old_minute[3] = crc_old_minute[2];
62
             crc_old_minute[2] = crc_old_minute[1];
63
             crc_old_minute[1] = crc_old_minute[0];
64
             crc_old_minute[0] = dcf_Minute + 5;
65
66
//             itoa(TestCRCOut,crc_read);
67
//             UART1_Write_text(TestCRCOut);
68
69
70
             if(crc_read >= 3)
71
             {
72
                  Tag = dcf_Tag;
73
                  Monat = dcf_Monat;
74
                  Jahr = dcf_Jahr;
75
                  
76
                  Stunde = dcf_Stunde;
77
                  Minute = dcf_Minute;
78
                  sekunde = 0;
79
                  is_dcf_ok = 1;
80
             }
81
     }
82
}

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?!

von Karl H. (kbuchegg)


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
1
             dcf_Stunde = DecodeZehner( dcf_bitmask, 33, 2 ) +
2
                          DecodeEiner(  dcf_bitmask, 29, 4 );
3
4
             dcf_Minute = DecodeZehner( dcf_bitmask, 25, 3 ) +
5
                          DecodeEiner(  dcf_bitmask, 21, 4 );
6
             
7
             dcf_Tag    = DecodeZehner( dcf_bitmask, 40, 2 ) +
8
                          DecodeEiner(  dcf_bitmask, 36, 4 );
9
10
             dcf_Monat  = DecodeZehner( dcf_bitmask, 49, 1 ) +
11
                          DecodeEiner(  dcf_bitmask, 45, 4 );
12
13
             dcf_Jahr   = DecodeZehner( dcf_bitmask, 54, 4 ) +
14
                          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.
1
             dcf_Stunde = Decode( dcf_bitmask, 29, 6 );
2
             dcf_Minute = Decode( dcf_bitmask, 21, 7 );             
3
             dcf_Tag    = Decode( dcf_bitmask, 36, 6 );
4
             dcf_Monat  = Decode( dcf_bitmask, 45, 5 );
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.

von Peter D. (peda)


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

von redyszhrtjk (Gast)


Lesenswert?

Ob das besser ist?
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <conio.h>
4
#include <stdint.h>
5
#include <inttypes.h>
6
#include <strings.h>
7
#include <math.h>
8
#include <time.h>
9
10
int main()
11
{
12
  uint8_t i;
13
  const uint8_t mult[]={1,2,4,8,10,20,40};
14
  uint8_t dcf_bitmask[60];
15
  uint8_t dcf_stunde, dcf_minute;
16
17
  /* irgendwelche Werte erzeugen */
18
  srand(0);
19
  for(i=0;i<60;i++)
20
    dcf_bitmask[i]=rand()&1;
21
  for(i=0;i<60;i++)
22
    printf("%c",dcf_bitmask[i]+'0');
23
  printf("\n");
24
25
  /* hier gehts los */
26
  for(dcf_stunde=0,i=0;i<6;i++)
27
    dcf_stunde+=mult[i]*dcf_bitmask[i+29];
28
  for(dcf_minute=0,i=0;i<7;i++)
29
    dcf_minute+=mult[i]*dcf_bitmask[i+21];
30
  /* usw */
31
  printf("%"PRIu8":%"PRIu8"\n",dcf_stunde,dcf_minute);
32
  return EXIT_SUCCESS;
33
}

von redyszhrtjk (Gast)


Lesenswert?

Hab grad gesehen: Dem mult[] fehlt ein Wert (80).

von Rene K. (draconix)


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.

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.