Forum: Mikrocontroller und Digitale Elektronik DCF-Signal richtig auswerten


von Peter (Gast)


Lesenswert?

Guten morgen,
nachdem ich die Signale von einem DCF-Empfänger richtig bekomme, habe 
ich probleme bei der Auswertung. Ich bekomme leider nicht die Richtigen 
Daten heraus, obwohl ich der Meinung bin, dass meine Berechnung so 
passt. Wenn eine 1 erkannt wurde, wird diese in einem Struct gespeichert
1
struct  DCF77_Bits {
2
/*  1 */  unsigned char M          :1  ; // Start einer neuen Minute (immer 0)
3
/*  2 */  unsigned char O1      :1  ; // MeteoTime / Katastropehnschutz
4
/*  3 */  unsigned char O2      :1  ; // MeteoTime / Katastropehnschutz
5
/*  4 */  unsigned char O3      :1  ; // MeteoTime / Katastropehnschutz
6
/*  5 */  unsigned char O4      :1  ; // MeteoTime / Katastropehnschutz
7
/*  6 */  unsigned char O5      :1  ; // MeteoTime / Katastropehnschutz
8
/*  7 */  unsigned char O6      :1  ; // MeteoTime / Katastropehnschut
9
/*  8 */  unsigned char O7      :1  ; // MeteoTime / Katastropehnschutz
10
/*  9 */  unsigned char O8      :1  ; // MeteoTime / Katastropehnschutz
11
/* 10 */  unsigned char O9      :1  ; // MeteoTime / Katastropehnschutz
12
/* 11 */  unsigned char O10      :1  ; // MeteoTime / Katastropehnschutz
13
/* 12 */  unsigned char O11      :1  ; // MeteoTime / Katastropehnschutz
14
/* 13 */  unsigned char O12      :1  ; // MeteoTime / Katastropehnschutz
15
/* 14 */  unsigned char O13      :1  ; // MeteoTime / Katastropehnschutz
16
/* 15 */  unsigned char O14      :1  ; // MeteoTime / Katastropehnschutz
17
/* 16 */  unsigned char R          :1  ; // Rufbit PTB
18
/* 17 */  unsigned char A1      :1  ; // A1 = Umstellung MESZ/MEZ am Ende dieser Stunde
19
/* 18 */  unsigned char Z1      :1  ; // Zeitzonenbit 0=MEZ, 1=MESZ
20
/* 19 */  unsigned char Z2      :1  ; // Zeitzonenbit 0=MESZ, 1=MEZ
21
/* 20 */  unsigned char A2      :1  ; // Einfügen einer Schaltsekunde am Ende dieser Stunde
22
/* 21 */  unsigned char S          :1  ; // Startbit der codierten Zeitinformation (immer 1)
23
/* 22 */  unsigned char Min      :7  ; // 7 Bits für die Minuten: 21-24 Minuten-Einer; 25-27 Minuten-Zehner
24
/* 29 */  unsigned char P1      :1  ; // Parität Minute
25
/* 30 */  unsigned char Hour      :6  ; // 6 Bits für die Stunden: 29-32 Stunden-einer; 33-34 Stunden-Zehner
26
/* 36 */  unsigned char P2      :1  ; // Parität Stunden
27
/* 37 */  unsigned char Day      :6  ; // 6 Bits für den Tag: 36-39 Kalendertag-einer; 40-41 Kalendertag-Zehner
28
/* 43 */  unsigned char Weekday    :3  ; // 3 Bits für den Wochentag
29
/* 46 */  unsigned char Month        :5  ; // 3 Bits für den Monat: 45-48 Monat-Einer; 49 Monat-Zehner
30
/* 51 */  unsigned char Year        :8  ; // 8 Bits für das Jahr: 50-53 Jahr-Einer; 54-57 Jahr-Zehner
31
/* 59 */  unsigned char P3      :1  ; // Parität Datum
32
};

Ausgewertet wird alle in einer Timerroutine, welche alle 20 ms ausgelöst 
wird
1
[ISR (TIMER1_COMPA_vect)
2
{
3
  static char tempChar[8];
4
  static uint16_t timerInterruptTicks = 0;  // Anzahl der Aufrufe der ISR
5
  static uint8_t timerInterruptTime = 20;    // Alle 20 ms wird der Interrupt ausgelöst
6
  static uint8_t dcfHighTicks = 0;
7
  static uint16_t dcfLowTicks = 0;
8
  
9
  timerInterruptTicks++;
10
  
11
  // DCF Zeit wurde Synchronisiert
12
  if(flags.dcfSync)
13
  {
14
    PORTB &= ~(1<<PINB5);
15
    flags.dcfSync = 0; 
16
  }
17
  
18
  // Eine Sekune vorbei
19
  if(timerInterruptTicks>=1000/timerInterruptTime)
20
  {
21
    timerInterruptTicks = 0;
22
  }
23
  
24
  if(!(PIND & (1<<DDD2))) // low-Pegel an INT0
25
  {
26
    dcfLowTicks++;
27
    if(dcfLowTicks*timerInterruptTime >= 60) flags.dcfRx = 1; // kein Prellen des Signals
28
    
29
  }
30
  else // high-Pegel on INT0
31
  {
32
    dcfHighTicks++;
33
    if(flags.dcfRx == 1)  // Ein Valides Signal
34
    {
35
      
36
      //Überprüfen ob eine 0 oder eine 1 empfangen wurde
37
      //0 = 100ms; 1 = 200ms
38
      //Abfrage größer als 150ms (15% von 1Sekund also 150ms)
39
      if(dcfLowTicks * timerInterruptTime > 150)
40
      {
41
        dcfRxBuffer = dcfRxBuffer | ((unsigned long long) 1 << dcfBitCounter);
42
      }
43
      flags.dcfRx = 0;
44
      dcfBitCounter++;
45
      dcfLowTicks = 0;
46
      dcfHighTicks = 0;
47
    }
48
    else if(dcfHighTicks*timerInterruptTime >= 1700 )  // Fehlendes Signal 59. Sekunde
49
    {
50
      rxBuffer = (struct DCF77_Bits*)(char*)&dcfRxBuffer;
51
      // wurden alle 59 Bits empfangen 
52
      if(dcfBitCounter == 59)
53
      // alle 59Bis empfangen, stellen der Uhr nach DCF77
54
      {
55
        // Berechnung der Minuten in DEC
56
        mm = lookupRotate[rxBuffer->Min >> 3] + 10*(lookupRotate[rxBuffer->Min & 0x07]);
57
58
        // Berechnung der Stunden in DEC
59
        hh = lookupRotate[rxBuffer->Hour >> 2] + 10*(lookupRotate[rxBuffer->Hour & 0x03]);
60
        
61
        // Berechnung des Tages in DEC
62
        day = lookupRotate[rxBuffer->Day >> 2] + 10*(lookupRotate[rxBuffer->Day & 0x03]);
63
        
64
        // Berechnung des Monats in DEC
65
        month = lookupRotate[rxBuffer->Month >> 2] + 10*(lookupRotate[rxBuffer->Month & 0x03]);
66
        
67
        // Berechnung des Jahres in DEC
68
        year = lookupRotate[rxBuffer->Year >> 4] + 10*(lookupRotate[rxBuffer->Year & 0x0F]);
69
        
70
        
71
        itoa(year, tempChar, 10);
72
        uart_sendString("year:"); uart_sendString(tempChar); uart_transmit(' ');
73
        itoa(month, tempChar, 10);
74
        uart_sendString("month:"); uart_sendString(tempChar); uart_transmit(' ');
75
        itoa(day, tempChar, 10);
76
        uart_sendString("day:"); uart_sendString(tempChar); uart_transmit(' ');
77
        itoa(hh, tempChar, 10);
78
        uart_sendString("hour:"); uart_sendString(tempChar); uart_transmit(' ');
79
        itoa(mm, tempChar, 10);
80
        uart_sendString("min:"); uart_sendString(tempChar); uart_transmit(' '); uart_sendString("\n\r");
81
        flags.dcfSync = 1;
82
        PORTB |= (1<<PINB5);
83
      }
84
      else
85
      // es wurden nicht alle 59Bits empfangen, bzw. kein DCF77 Signal.
86
      {
87
        uart_sendString("keine DCF-Synchronisation\n\r");
88
        flags.dcfSync = 0;
89
      }
90
      
91
      dcfBitCounter = 0;
92
      dcfRxBuffer = 0;
93
      dcfHighTicks = 0;
94
    }
95
  }
96
}

Für die Ermittlung des wertes gehe ich wie folgt vor (bsp an Minunte):
Alle Signale für Minuten stehen in einem wert im Struct. Die 
Minuten-Einer stehen in den Bits 21 bis 24. Diese hole ich mir mit einer 
Bitverschiebung. Die Minuten-Zehner stehen in den Bits 25 bis 27. Diese 
hole ich mir mit Bitvergleich. Um an den Wert zu kommen, habe ich eine 
kleine Lookup-Tabelle erstellt, wo die werte gespiegelt drinn stehen. 
Für die Zehner-Minuten nehme ich den ermittelten wert mal 10.
1
mm = lookupRotate[rxBuffer->Min >> 3] + 10*(lookupRotate[rxBuffer->Min & 0x07]);
1
const uint8_t lookupRotate[16] = {0b0000, 0b1000, 0b0100, 0b1100, 0b0010, 0b1010, 0b0110, 0b1110, 0b0001, 0b1001, 0b0101, 0b1101, 0b0011, 0b1011, 0b0111, 0b1111};

Z.B. Minute 34 sollte im Struct stehen 0b1000110
Einer: Drei bits nach rechts, kommt raus: 0b1000. lookupRotate: 0b0001 
-> dec 1
Zehner: Bitvergleich mit 0x07 kommt raus: 0b110, lookupRotate: 0b011 -> 
dec 3. Mal 10 = 30.#
30+1=31.

Aber bei der Ausgabe kommen überall ganz andere werte raus.
Gestartet habe ich es heute morgen noch einmal (18.11.2018 07:23 UHR)
Das Ergebnis ist folgendes
keine DCF-Synchronisation
year:18 month:82 day:6 hour:128 min:102
year:18 month:82 day:6 hour:128 min:62
keine DCF-Synchronisation
year:18 month:82 day:6 hour:128 min:10
year:18 month:82 day:6 hour:128 min:90
year:18 month:82 day:6 hour:128 min:6
year:38 month:82 day:6 hour:128 min:86
year:18 month:82 day:6 hour:128 min:46
year:18 month:82 day:6 hour:128 min:134
year:18 month:82 day:6 hour:128 min:26
year:18 month:82 day:6 hour:128 min:106
year:18 month:82 day:6 hour:128 min:66
year:18 month:82 day:6 hour:128 min:146
year:18 month:82 day:6 hour:128 min:14
year:18 month:82 day:6 hour:128 min:94
year:18 month:82 day:6 hour:128 min:1
year:18 month:82 day:6 hour:128 min:81
year:18 month:82 day:6 hour:128 min:41
year:18 month:82 day:6 hour:128 min:121
year:18 month:82 day:6 hour:128 min:21
year:18 month:82 day:6 hour:128 min:101
year:18 month:82 day:6 hour:128 min:61
year:18 month:82 day:6 hour:128 min:141
year:18 month:82 day:6 hour:128 min:9
year:18 month:82 day:6 hour:128 min:89
year:18 month:82 day:6 hour:128 min:5
year:18 month:82 day:6 hour:128 min:85
year:18 month:82 day:6 hour:128 min:45
year:18 month:82 day:6 hour:128 min:125
year:18 month:82 day:6 hour:128 min:25
year:18 month:82 day:6 hour:128 min:105
year:18 month:82 day:6 hour:128 min:65
year:18 month:82 day:6 hour:128 min:145
year:18 month:82 day:6 hour:128 min:13
year:18 month:82 day:6 hour:128 min:93
year:18 month:82 day:6 hour:4 min:0
 year:18 month:82 day:6 hour:4 min:88
year:18 month:82 day:6 hour:4 min:40
year:18 month:82 day:6 hour:4 min:120
keine DCF-Synchronisation
year:18 month:82 day:6 hour:4 min:100
keine DCF-Synchronisation
keine DCF-Synchronisation
year:18 month:82 day:6 hour:4 min:8
year:18 month:82 day:6 hour:4 min:88
year:18 month:82 day:6 hour:4 min:4
year:18 month:82 day:6 hour:4 min:84
year:18 month:82 day:6 hour:4 min:44
year:18 month:82 day:6 hour:12 min:124
year:18 month:82 day:6 hour:4 min:24
year:18 month:82 day:6 hour:4 min:104
keine DCF-Synchronisation

Es scheint sich irgendwie was falsches eingeschlichen zu haben. Bei den 
stunden kann man es auch gut sehen. Alles was 7 Uhr sein sollte, ist 
128. Ab 8 Uhr kommt dann der Wert 4.
Hat hier jemand eine Idee, woher diese falschen Ergebnisse kommen? Und 
weiß wie ich es besser machen kann?

Gruß
Peter

von LostInMusic (Gast)


Lesenswert?

Dein "lookupRotate" und das Bitschiebegeraffel sind unnötig kompliziert.

>Und weiß wie ich es besser machen kann?

Wie wäre es z. B. mit einem großen Switch-Case? Da schreibst Du für jede 
interessante Sekunde (ab 15) die passende Aktion rein für den Fall, dass 
das DCF-Bit in dieser Sekunde 1 ist:
1
switch (dcfBitCounter)  
2
  {
3
  case 21:  minute = minute + 1;
4
  case 22:  minute = minute + 2;
5
  case 23:  minute = minute + 4;
6
  case 24:  minute = minute + 8;
7
  case 25:  minute = minute + 10;
8
  case 26:  minute = minute + 20;
9
  case 27:  minute = minute + 40;
10
11
  case 29:  hour = hour + 1;
12
  case 30:  hour = hour + 2;
13
  case 31:  ...
14
  case 32:  ...
15
  ...
16
  // analog für day, month, year
17
  }

Diese Switch-Case-Konstruktion ist maximal 59 Einträge groß. Das ist vom 
Speicherpatz her auch einem kleinen Controller bedenkenlos zumutbar.

(Ja, das kann man wirklich so einfach machen...)

von Mario M. (thelonging)


Lesenswert?

Lass doch mal dcfRxBuffer ausgeben und guck, ob die Daten richtig 
empfangen werden. Dann kann es doch nur noch an der Konvertierung 
liegen.

von Stefan F. (Gast)


Lesenswert?

Der Lösungsansatz von LostInMusic gefällt mir sehr viel besser.

von Michael U. (amiga)


Lesenswert?

Hallo,

keine Ahnung, ob es hilft:
1
#define DEBUG 0
2
3
#include <avr/io.h>
4
#include <util/parity.h>
5
#include "timer_10ms.h"
6
#include "dcf77.h"
7
#include "UART.h"                       // nur Debug
8
9
static union
10
{
11
  volatile uint64_t dcf_bits;
12
  struct
13
  {
14
    volatile uint8_t DUMMY:5;       // Rest für long long
15
    volatile uint8_t START:1;       // Start Minute (0)
16
    volatile uint16_t  METEO:14;    // Wetterdaten
17
    volatile uint8_t RUF:1;         // Rufbit (ehem. Reserveantenne) 
18
    volatile uint8_t MEST_F:1;      // Zeitumstellung am Ende der Stunde
19
    volatile uint8_t MESZ:2;        // MEZ (10), MESZ (01)
20
    volatile uint8_t SEK_S:1;       // Schaltsekunde am Ende der Stunde
21
    volatile uint8_t BEGIN:1;       // Start Zeit (1)
22
    volatile uint8_t MIN_E:4;       // Minute BCD
23
    volatile uint8_t MIN_Z:3;       // Minute BCD  
24
    volatile uint8_t MIN_P:1;       // Parität Minute
25
    volatile uint8_t STU_E:4;       // Stunde BCD
26
    volatile uint8_t STU_Z:2;       // Stunde BCD
27
    volatile uint8_t STU_P:1;       // Parität Stunde
28
    volatile uint8_t TAG_E:4;       // Tag BCD
29
    volatile uint8_t TAG_Z:2;       // Tag BCD
30
    volatile uint8_t WTAG:3;        // Wochentag BCD
31
    volatile uint8_t MON_E:4;       // Monat BCD
32
    volatile uint8_t MON_Z:1;       // Monat BCD
33
    volatile uint8_t JAHR_E:4;      // Jahr BCD
34
    volatile uint8_t JAHR_Z:4;      // Jahr BCD
35
    volatile uint8_t DATUM_P:1;     // Parität Datum
36
  };
37
} dcf77_daten;
38
39
uint8_t dcf77_check(void);
40
void dcf77_init(void);
41
42
static uint8_t dcf77_time_cnt;            // Anzahl 10ms IRQs
43
static uint8_t dcf77_bit_cnt;             // Anzahl Bits seit Minutenwechsel
44
uint8_t dcf77_ok = 0, dcf77_err = 0, dcf77_min = 0;
45
46
//-----------------------------------------------------------------------------------------
47
48
uint8_t dcf77_10ms()
49
{
50
  dcf77_ok = FALSE;
51
52
  if (DCF77_PIN & (1<<DCF77_DATA))        // low oder high?
53
  {                                     // high
54
    dcf77_time_cnt++;                   // 10ms Time +1
55
    if (dcf77_time_cnt > 250)           // 2,5s
56
    {
57
      dcf77_err = TRUE;               // Fehler, kein Impuls
58
    }
59
  }
60
  else
61
  {                                     // low
62
    if (dcf77_time_cnt)                 // bei 0 ist Auswertung fertig
63
    {
64
      if ((dcf77_time_cnt > 195) |  (dcf77_time_cnt < 6))
65
      {
66
        dcf77_err = TRUE;
67
      }
68
      else
69
      {
70
        if (dcf77_time_cnt > 177)   // Minute rum
71
        {                 
72
          dcf77_min = TRUE;       // Flag setzen für Minute komplett        
73
          dcf77_time_cnt -= 100;  // 1s time abziehen für Auswertung
74
        }
75
        if ((dcf77_time_cnt > 95) | (dcf77_time_cnt < 78)) // zu lang oder zu kurz -> Fehler
76
        {
77
          dcf77_err = TRUE;        // Fehler, kein gültiger Impuls
78
        }
79
        else
80
        {
81
          dcf77_bit_cnt++;         // Bitcount erhöhen
82
          asm volatile             // shift long long right und höchstwertiges Bit bleibt 0
83
          (
84
            "lds __tmp_reg__, %0 + 7" "\n\t"
85
            "lsr __tmp_reg__" "\n\t"
86
            "sts %0 + 7, __tmp_reg__" "\n\t"
87
            "lds __tmp_reg__, %0 + 6" "\n\t"
88
            "ror __tmp_reg__" "\n\t"
89
            "sts %0 + 6, __tmp_reg__" "\n\t"
90
            "lds __tmp_reg__, %0 + 5" "\n\t"
91
            "ror __tmp_reg__" "\n\t"
92
            "sts %0 + 5, __tmp_reg__" "\n\t"
93
            "lds __tmp_reg__, %0 + 4" "\n\t"
94
            "ror __tmp_reg__" "\n\t"
95
            "sts %0 + 4, __tmp_reg__" "\n\t"
96
            "lds __tmp_reg__, %0 + 3" "\n\t"
97
            "ror __tmp_reg__" "\n\t"
98
            "sts %0 + 3, __tmp_reg__" "\n\t"
99
            "lds __tmp_reg__, %0 + 2" "\n\t"
100
            "ror __tmp_reg__" "\n\t"
101
            "sts %0 + 2, __tmp_reg__" "\n\t"
102
            "lds __tmp_reg__, %0 + 1" "\n\t"
103
            "ror __tmp_reg__" "\n\t"
104
            "sts %0 + 1, __tmp_reg__" "\n\t"
105
            "lds __tmp_reg__, %0" "\n\t"
106
            "ror __tmp_reg__" "\n\t"
107
            "sts %0, __tmp_reg__"
108
            : "+m" (dcf77_daten)
109
          );
110
          if (dcf77_time_cnt < 87) // Bit war 1 
111
          {
112
            asm volatile        // höchstwertiges Bit des long long auf 1 setzen
113
            (
114
              "lds __tmp_reg__, %0 + 7" "\n\t"
115
              "set" "\n\t"                      // T setzen
116
              "bld __tmp_reg__, 7" "\n\t"       // und in Bit 7 kopieren
117
              "sts %0 + 7, __tmp_reg__" "\n\t"
118
              : "+m" (dcf77_daten)
119
            );
120
          }
121
        }
122
123
#if DEBUG
124
  uart_send_byte_hex(dcf77_bit_cnt);
125
  uart_send_byte(' ');
126
  uart_send_byte_hex(dcf77_time_cnt);
127
  uart_send_byte(' ');
128
  uart_send_byte_hex(dcf77_min);
129
  uart_send_text("\r\n");
130
#endif
131
132
        dcf77_time_cnt = 0;
133
        if (dcf77_min)
134
        {
135
          if (dcf77_bit_cnt == 59) // alle Bits da?
136
          {
137
            dcf77_ok = dcf77_check();
138
          }
139
          dcf77_err = TRUE;
140
        }
141
      }
142
    }
143
  }
144
  if (dcf77_err)                          // Fehler?
145
  { 
146
    dcf77_reset();
147
  }
148
  return dcf77_ok;
149
}
150
151
//-----------------------------------------------------------------------------------------
152
153
void dcf77_reset()
154
{
155
  dcf77_daten.dcf_bits = 0;
156
  dcf77_time_cnt = 0;
157
  dcf77_bit_cnt = 0;
158
  dcf77_err = FALSE;
159
  dcf77_min = FALSE;
160
}
161
162
//-----------------------------------------------------------------------------------------
163
164
void dcf77_init()
165
{
166
  DCF77_DDR &= ~(1<<DCF77_DATA);          // Eingang
167
  DCF77_PORT |= (1<<DCF77_DATA);          // PullUp ein
168
169
  dcf77_reset();
170
}
171
172
//-----------------------------------------------------------------------------------------
173
174
unsigned char dcf77_check()
175
{
176
  uint8_t parity;
177
178
   // wenn Parität gerade ist Ergebnis 0
179
  parity = parity_even_bit((dcf77_daten.MIN_Z << 5) | (dcf77_daten.MIN_E << 1) | dcf77_daten.MIN_P);
180
  if (parity)
181
  {
182
    return FALSE;                        // Fehler
183
  }
184
 
185
  // wenn Parität gerade ist Ergebnis 0, dazu das Ergebnis von oben
186
  if (parity_even_bit((dcf77_daten.STU_Z << 5) | (dcf77_daten.STU_E << 1) | dcf77_daten.STU_P))
187
  {
188
    return FALSE;                        // Fehler
189
  }
190
191
  // wenn Parität gerade ist Ergebnis 0
192
  parity = parity_even_bit((dcf77_daten.TAG_Z << 4) | dcf77_daten.TAG_E);
193
194
  // wenn Parität gerade ist Ergebnis 0, dazu das  Ergebnis von oben 
195
  parity = parity_even_bit((dcf77_daten.MON_Z << 5) | (dcf77_daten.MON_E << 1) | parity); 
196
197
  // wenn Parität gerade ist Ergebnis 0, dazu die  Ergebnisse von oben 
198
  parity = parity_even_bit((dcf77_daten.JAHR_Z << 5) | (dcf77_daten.JAHR_E << 1) | parity); 
199
200
  // wenn Parität gerade ist Ergebnis 0, dazu die  Ergebnisse von oben 
201
  parity = parity_even_bit((dcf77_daten.WTAG << 2) | (dcf77_daten.DATUM_P << 1) | parity); 
202
203
  if (parity)
204
  {
205
    return FALSE;                       // Fehler
206
  }
207
  uhrzeit.SEK = 0;                        // und Zeit übernehmen
208
  uhrzeit.MIN = (dcf77_daten.MIN_Z << 4) | dcf77_daten.MIN_E;
209
  uhrzeit.STU = (dcf77_daten.STU_Z << 4) | dcf77_daten.STU_E;
210
  uhrzeit.WTAG = dcf77_daten.WTAG; //
211
  uhrzeit.TAG = (dcf77_daten.TAG_Z << 4) | dcf77_daten.TAG_E;
212
  uhrzeit.MON = (dcf77_daten.MON_Z << 4) | dcf77_daten.MON_E;
213
  uhrzeit.JAHR = (dcf77_daten.JAHR_Z << 4) | dcf77_daten.JAHR_E;
214
  FLAGS.FLAG_MINUTE = 1;
215
  FLAGS.FLAG_TAG = 0;                     // keine Datums-Berechnung in Software nötig
216
217
  return TRUE;                            // ok
218
}
219
220
//-----------------------------------------------------------------------------------------

Der DCF77 Pin wird im 10ms Timer-IRQ abgefragt.
Danke auch heute noch an J.Wunsch für die Hilfe beim ASM einbinden in C.
Einen Shift über ein uint64_t in C ist (war damals?) nicht praktisch 
sinnvoll.
Wenn es von Interesse ist und was wichtiges fehlt einfach fragen.
Die ISR hat noch Tasten abgefragt usw, der DCF77 Teil hier:
1
ISR(TIMER1_COMPA_vect) 
2
{
3
  static uint8_t hsek;
4
  uint8_t byte;
5
6
  if (!(dcf77_10ms()))                       // dcf77 gibt 1 zurück, wenn Uhrzeit gültig gesetzt
7
  { 
8
    hsek++;         
9
    if (hsek == 100)
10
    {
11
      hsek = 0;
12
      soft_time();                       // Sonst eben per Software die Zeit erhöhen (kein Datum!!!)  
13
      FLAGS.FLAG_SEKUNDE = TRUE;         // Flag für main usw. 
14
    }
15
  }    
16
  else
17
  {
18
    hsek = 0;
19
    FLAGS.FLAG_SEKUNDE = TRUE;             // DCF77 hat Zeit gesetzt, Flag für main usw.
20
  }
21
}

Gruß aus Berlin
Michael

: Bearbeitet durch User
von Michael (Gast)


Lesenswert?

Was ist so schwer an "Längeren Sourcecode nicht im Text einfügen, 
sondern als Dateianhang"

Ein anderer Michael

von Peter D. (peda)


Lesenswert?

LostInMusic schrieb:
> Wie wäre es z. B. mit einem großen Switch-Case?

Ich würde auch vorschlagen, die Bits in knallharter Echtzeit 
auszuwerten, also direkt beim Eintreffen.
Dabei kann man auch gleich dieses beknackte packed-BCD in Binär 
umwandeln. Das erleichtert die Zahlenausgabe.
Bit-Structs sind nur in Ausnahmefällen wirklich sinnvoll, erzeugen aber 
viel umständlichen Code.
Ich hab auch ne LED mit an den MC gehängt, die den Eingang ausgibt. Dann 
sieht man schön, ob der Empfang gestört ist oder nicht.

von Peter (Gast)


Lesenswert?

Hallo,

ich habe die Auswertung jetzt mit einem Switch-Case gemacht. Zunächst 
kam genau das selbe heraus, wir es vorher war. Das hochzählen des 
dcfBitCounter war falsch. Jetzt bekomme ich die Richtigen Daten heraus.

Als nächstes werde ich die Parität berücksichtigen und falls etwas nicht 
passt, oder kein Empfang mehr da sein sollte die Uhr selber stellen. 
Wenn dort wieder Probleme auftreten, wo ich nicht weiter komme, werde 
ich mich wieder melden.

Aber bis hier hin schonmal besten Dank an alle

von Michael U. (amiga)


Lesenswert?

Hallo,

Michael schrieb:
> Was ist so schwer an "Längeren Sourcecode nicht im Text einfügen,
> sondern als Dateianhang"
>
> Ein anderer Michael

Du hast in der Sache ja Recht, mein Fehler.

PS: warum sind eigentlich so häufig Gäste so bemüht irgendwas schreiben 
zu müssen auch wenn sie nichts zum Thema beitragen wollen?

Gruß aus Berlin
Michael

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

... weil es Angemeldete sind, die nicht erkannt werden wollen?

Gruß aus dem Schwarzwald

von Jacko (Gast)


Lesenswert?

DCF war ja für manchen hier DAS erste µC-Projekt.

Ob man es in ASM, oder C macht, ist Geschmackssache.
Die Diskussion, ob Abtastung oder Interrupt vom DCF-Signal
ist auch schon mehrfach heiß geführt worden, obwohl es bei
jeweils angemessener Programmierung keine nennenswerten
Nachteile gibt.

Merkwürdig ist allerdings die Zählweise: In ASM und C ist
es eher Brauch, ab Null (Minutenstartbit) zu zählen.
Die Minute wird also mit Bit 21...27 übertragen, Minuten-Parity
ist Bit 28.

In jedem Fall gehört zur DCF-Decodierung die Erkennung des
Minutenbeginns. Ob dann einfach ein Array, oder kompliziert
eine struct mit den DCF-Bits gefüttert wird, oder die sofortige
Auswertung per Case gemacht wird - das funktioniert alles, wenn
man es richtig macht.

Soll die Uhr wirklich nur sichere Zeitangaben ausgeben,
ist es einfacher in der Wartepause vor dem Minutenbeginn
die gesammelten Daten aus Case-Auswertung, Array, oder Struct
incl. Parität und Ankündigung von Zeitzonenwechsel, sowie UTC-
Differenz auszuwerten - und mit einer ordentlich
selbstprogrammierten Zeit- und Kalenderrechnung abzugleichen.

Das geht in wenigen ms, so dass zum nächsten Minutenbeginn
mit größtmöglicher Sicherheit die ECHTE aktuelle Zeit bereitsteht.
Mit Quarz läuft die dann auch Stunden und Tage ohne DCF-Empfang
genau weiter...

Viel Erfolg!

von nachtmix (Gast)


Lesenswert?

Jacko schrieb:
> Merkwürdig ist allerdings die Zählweise: In ASM und C ist
> es eher Brauch, ab Null (Minutenstartbit) zu zählen.

Es wird zweckmäßig sein die offizielle Zählweise des Signals zu 
verwenden.
Wenn diese von der im Programm verwendeten abweicht, sollte man 
erforderliche Umrechnungen in den Kommentaren des Sourcecodes finden.

von nachtmix (Gast)


Lesenswert?


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.