Forum: Mikrocontroller und Digitale Elektronik DCF77 Code, Paritätsprüfung klappt nicht


von Matze (Gast)


Lesenswert?

Hallo,

Ich Habe folgenden Code zur DCF77-Decodierung geschrieben,
Grundsätzlich funktioniert alles Notwendige.
Jedoch gibt es 2 Probleme:
Der Paritätsckek des Datums ist immer Falsch
Gibts es da vielleicht ein Schleifen / Array-Überlauf Problem?

Wenn ich bewust Fehler einstreue, z.b. im Minuten-Teil der übertragung,
kommt es bei der Auswertung vor, dass die Minute sich nicht verändert.
Sie ist dann falsch, dennoch ist die Parität, sowie Sinhaftigkeit des 
wertes <9 gegeben.

Es wird also die Zeile 
getZeitinAnzeige(&Anzeige[3],3,25);
            Anzeige[1].dp=1;    //Anzeige Parität der Minute OK
in der vielfachen if-Abfrage ausgeführt.
Da dies passiert, ist angeblich die Parität richtig und der Wert 
sinvoll.
Gleichzeitig bleibt die Minute jedoch stehen, und läuft nicht weiter.
Folglich ist ein Fehler, den ich absichtlich eingestreut habe 
eingetreten.
Das einstreuen des Fehlers führt jedoch niemals zu Falscher Parität der 
Form:
            Anzeige[1].dp=0;
in den Else-Zweigen einer der IF-Abfragen.
Die Zeit bleibt stehen, und dennoch ist angeblich immer alles richtig.
Da ich das bestimmt schon 10 mal getestet habe, wird es lansgam sehr 
unwahrscheinlich.

Sieht vielleicht jemand das Problem?

1
#define F_CPU 4000000UL
2
#include <avr/interrupt.h>
3
#include "delay.h"
4
#include "DS1820.h"
5
#include "Uhr.h"
6
7
8
/*unsigned short int C_Halbe=0;
9
unsigned short int C_Einer=0;
10
unsigned short int C_Zehner=0;
11
unsigned short int VZ=0;*/
12
13
short volatile unsigned int DCF77flag;
14
volatile unsigned short int count1;
15
volatile unsigned short int count0;
16
volatile short int Prot_Start;
17
unsigned short int Temperatur[6];
18
19
int main()
20
{
21
  Init();
22
  Anzeige[0].Zahl=0;  //einer  Sek
23
  Anzeige[1].Zahl=0;  //Zehner Sek
24
  Anzeige[2].Zahl=0;  //einer  min 
25
  Anzeige[3].Zahl=0;  //Zehner min
26
  Anzeige[4].Zahl=0;  //Einer  Std
27
  Anzeige[5].Zahl=0;  //Zehner Std
28
  count1=0;
29
  count0=0;
30
  Prot_Start=-1;
31
  while(1)
32
  {      
33
    ;
34
  }
35
}
36
37
void Init()
38
{
39
  int A=1;
40
  //Port-Einstell
41
  DDRA|=0xff;      //Port A = Ausgabe
42
  DDRC|=0xfc;      //PORT C = Ausgabe Anode
43
  DDRB&=0xf0;      //Port B = 3 Taster, DS1820 als Eingabe
44
  DDRD&=0x00;      //Port D = Eingabe 
45
  //--------------- Timer 0 ------------------------------------
46
  // 1ms-Interrupt @ 3.999.968HZ
47
  // 3999968/256= 15.624,875Hz=> Prescaler=256
48
  // 3999968/64= 62.499,5Hz  => Prescaler=64 --> Gewählt
49
  // 3999968/8= 499.996.0Hz  => Prescaler=8 --> mind 1935 IRQs / Sec
50
  //Ziel = 1000IRQ/Sec
51
  // 62.499,5/1000=62,4995  => Einstell CTC
52
  //--> Schlecht !
53
  //--------------- Timer 1 ----------------------
54
  // 1ms-Interrupt @ 3.999.968HZ
55
  // 3999968/256=    15.624,875 Hz  => Prescaler=256
56
  // 3999968/ 64=    62.499,5   Hz  => Prescaler=64 
57
  // 3999968/  8=   499.996,0   Hz  => Prescaler=8 
58
  // 3999968/  1= 3.999.968,0   Hz  => Prescaler=1 --> mind 61,034 IRQs / Sec
59
  //Ziel = 1000IRQ/Sec
60
  // 3999968/1000=3999,968  => Einstell CTC = 4000
61
  //--> Schlecht !
62
  TCNT1H=0x00;      //Timer auf 0 Low
63
  TCNT1L=0x00;
64
  OCR1A =0x0F9F;      //=4000-(1) -> Laut Formel in Datasheet (S.102) für 1000 IRQs/Sec
65
  TCCR1B |= (1<<WGM12);  //CTC-Modus
66
  TCCR1B |= (1<<CS10);  //Prescaler = 1 / Start Timer
67
  TIMSK |= (1<<OCIE1A);  //Compare - Interrupt Enable
68
  sei();          //Global IRQ-Enable
69
  //--------------DCF77 an Port D2 / Int0-------------------
70
  MCUCR |= (1<<ISC01);  //-->Interrupt bei steigender Pflanke
71
  MCUCR |= (1<<ISC00);
72
  GICR |= (1<<INT0);  // Interrupt 0 Enable
73
  DCF77flag=0;
74
}
75
76
ISR (INT0_vect)
77
{
78
  if(DCF77flag==0)  //Steigende Pflanke
79
  {
80
    if((Prot_Start>=0)&&(Prot_Start<=57))  //Zurücksetzten am Ende der Minute
81
    {
82
      Prot_Start++;
83
    }    
84
    if((Prot_Start==58))  //Auswertung der Zeitinformation am ende einer Minute
85
    {            
86
//------------ Einstellung der Uhr auf Korrekte zeit (Minuten) -----------------------------
87
      unsigned short int par= Zeit[21]+Zeit[22]+
88
                  Zeit[23]+Zeit[24]+
89
                  Zeit[25]+Zeit[26]+
90
                  Zeit[27]+Zeit[28];
91
      if(par%2==0)  //Minute OK --> Patität
92
      {
93
        if((Zeit[21]*1+Zeit[22]*2+Zeit[23]*4+Zeit[24]*8)<=9) //Minute OK --> WERT OK
94
        {
95
          getZeitinAnzeige(&Anzeige[2],4,21);
96
          if((Zeit[25]*1+Zeit[26]*2+Zeit[27]*4)<=6)  //Minute OK --> Wert OK
97
          {
98
            getZeitinAnzeige(&Anzeige[3],3,25);
99
            Anzeige[1].dp=1;    //Anzeige Parität der Minute OK
100
          }
101
          else
102
          {
103
            Anzeige[1].dp=0;    //Anzeige Parität der Minute FALSCH
104
          }
105
        }
106
        else
107
        {
108
          Anzeige[1].dp=0;    //Anzeige Parität der Minute FALSCH
109
        }
110
      }
111
      else
112
      {
113
        Anzeige[1].dp=0;    //Anzeige Parität der Minute FALSCH
114
      }
115
//------------ Einstellung der Uhr auf Korrekte zeit (Stunden) -----------------------------
116
      par  =  Zeit[29]+Zeit[30]+
117
          Zeit[31]+Zeit[32]+
118
          Zeit[33]+Zeit[34]+
119
          Zeit[35];
120
      if(par%2==0)  //Minute + Stunde OK
121
      {
122
        getZeitinAnzeige(&Anzeige[4],4,29);
123
          //Anzeige Parität Stunden OK
124
        if((Zeit[29]*1+Zeit[30]*2+Zeit[31]*4+Zeit[32]*8)<=9) //Minute OK --> WERT OK
125
        {
126
          
127
          if((Zeit[33]*1+Zeit[34]*2)<=2)  //Minute OK --> Wert OK
128
          {
129
            getZeitinAnzeige(&Anzeige[5],2,33);
130
            Anzeige[2].dp=1;  
131
          }
132
          else
133
          {
134
            Anzeige[2].dp=0;    //Anzeige Parität der Stunden Falsch
135
          }
136
        }        
137
        else
138
        {
139
          Anzeige[2].dp=0;    //Anzeige Parität der Stunden Falsch
140
        }
141
      }
142
      else
143
      {
144
        Anzeige[2].dp=0;    //Anzeige Parität der Stunden Falsch
145
      }
146
//------------ Einstellung der Uhr auf Korrekte zeit (Datum) -----------------------------  
147
      par=0;
148
      for(int i=36;i<=58;i++)
149
      {
150
        par+=Zeit[i];
151
      }
152
      if(par%2==0) //Minute + Stunde + Datum OK
153
      {
154
        Anzeige[3].dp=1;      //Anzeige Parität Datum = OK
155
      }
156
      else
157
      {
158
        Anzeige[3].dp=0;    //Anzeige Parität des Datums Falsch
159
      }
160
      //------------------- Anzeige Syncronisation -------------------------------------    
161
      Prot_Start=-1;            //Reset der Sync-Info
162
      Anzeige[0].dp=0;          //Anzeige ob Uhr Syncronisiert
163
    }      
164
165
    //Debuging der ms eines 1 Pegels
166
    //Anzeige[2].Zahl=0;  //einer  min
167
    //Anzeige[3].Zahl=0;  //Zehner min
168
    //Anzeige[4].Zahl=0;  //Einer  Std
169
    
170
    count1=0;
171
    MCUCR &= (0<<ISC00);//Einstell Fallende flanke
172
    DCF77flag=1;
173
  }
174
  else        //Fallende Pflanke
175
  {
176
    count0=0;
177
    MCUCR |= (1<<ISC00);//Einstell steigende flanke
178
    DCF77flag=0;
179
  }
180
  //-------Debuging der Pflankenwechsel des DCF77-Signals-------
181
  //debDCF77Sig()
182
}
183
184
void getZeitinAnzeige(segment *anz, unsigned short int wandl, unsigned short int startbit)
185
{//Anz   = Zeiger auf Anzeige-Segment
186
 //wandl = Wie weit gezählt werden soll
187
   (*anz).Zahl=0;
188
  for(int i=0;i<wandl;i++)  //Einer_Minute auf Anzeige
189
  {
190
    switch (i)
191
    {
192
      case 0: (*anz).Zahl+=Zeit[startbit+i]*1;  break;
193
      case 1: (*anz).Zahl+=Zeit[startbit+i]*2;  break;
194
      case 2: (*anz).Zahl+=Zeit[startbit+i]*4;  break;
195
      case 3: (*anz).Zahl+=Zeit[startbit+i]*8;  break;
196
      default: (*anz).Zahl=100;      break;
197
    }
198
  }
199
}
200
201
ISR (TIMER1_COMPA_vect)  //Alle 1ms
202
{
203
  volatile static short unsigned int tick;
204
  Ausgabe(&Anzeige);
205
  tick++;
206
  if(tick==1000)  //
207
  {
208
    Uhr_Sek();
209
    tick=0;
210
  }
211
212
  if(DCF77flag==1)    //Zählung der 1-Impulse,
213
  {
214
    count1++;
215
    //--------------Zälung der ms eines 1 Pegels---------------
216
    //void debDCF77ms()
217
    if((count0>950)&&(count0<1500))  //Fehler zu kürze 1-Zeit, 0 nicht lange genug für Sync
218
    {
219
      Anzeige[4].dp=1;    //Anzeige Erkannter Fehler
220
    }
221
    else if ((count0>=1500)&&(count0<=2300))//Erkennen einer neuen Minute
222
    {
223
      Anzeige[0].Zahl=0;
224
      Anzeige[1].Zahl=0;
225
      Prot_Start=0;
226
      Anzeige[0].dp=1;
227
    }
228
    else if(count0>2300)    //Fehler zu lange 0-Zeit
229
    {
230
      Anzeige[4].dp=1;    //Anzeige Erkannter Fehler
231
    }
232
233
  }
234
  //----------------- Auswertung des Empf-Wert---------------------
235
  else // Nach dem Ende des 1-Pegels -> Auswertung
236
  {
237
    count0++;
238
    if(count1<70)    //Fehler --> Keine Sync mehr
239
    {      
240
      Anzeige[4].dp=1;    //Anzeige Erkannter Fehler
241
    }
242
    else if ((count1>=70) && (count1<=160))  //0 Empfangen
243
    {
244
      Zeit[Prot_Start]=0;
245
      Anzeige[5].dp=0;    //0-Empfangen
246
      Anzeige[4].dp=0;    //Erkannter Fehler Löschen
247
    }
248
    else if((count1>160) && (count1<300))  //1 Empfangen
249
    {
250
      Zeit[Prot_Start]=1;
251
      Anzeige[5].dp=1;    //1-Empfangen
252
      Anzeige[4].dp=0;    //Erkannter Fehler Löschen
253
    }
254
    else //(count1>=300)//Fehler --> Keine Sync mehr
255
    {
256
      Anzeige[4].dp=1;    //Anzeige Erkannter Fehler
257
    }
258
  }
259
  //---------------Überprüfung der Zeitbasis------------ --> OK = 5000
260
  //void debTimeBase()
261
}
262
263
void debTimeBase()
264
{
265
  static unsigned short int a=0;
266
  if(a==0)
267
  {
268
    DDRD|=0x40;  //Port D.6 = Ausgabe 
269
    a=1;
270
    PORTD|=0x40;//Port D.6 = High
271
  }
272
  else
273
  {
274
    a=0;
275
    PORTD&=0xAF;//Port D.6 = Low
276
  }
277
}
278
279
void debDCF77ms()  //Zälung der ms eines 1 Pegels
280
{
281
  Anzeige[2].Zahl++;
282
  if(Anzeige[2].Zahl==10)
283
  {
284
    Anzeige[2].Zahl=0;
285
    Anzeige[3].Zahl++;
286
    if(Anzeige[3].Zahl==10)
287
      {
288
      Anzeige[3].Zahl=0;
289
      Anzeige[4].Zahl++;
290
      if(Anzeige[4].Zahl==10)
291
      {
292
        Anzeige[4].Zahl=0;
293
      }
294
    }
295
  }
296
}
297
298
void debDCF77Sig() //Debuging der Pflankenwechsel des DCF77-Signals
299
{
300
  Anzeige[1].Zahl++;
301
  if(Anzeige[1].Zahl==10)
302
  {
303
    Anzeige[1].Zahl=0;
304
  }
305
}
306
307
void Ausgabe(segment *segstr)
308
{        
309
  static short int Z=0;
310
  Z++;
311
  PORTC=0x00;
312
  PORTA=0xFF;
313
  switch(Z)
314
  {
315
  case 0:  
316
    PORTC=0x04;    //Einer Sek
317
    BCDDecode(&segstr[0]);
318
  break;
319
  case 1:
320
    PORTC=0x08;    //Zehne Sek
321
    BCDDecode(&segstr[1]);
322
  break;
323
  case 2:  
324
    PORTC=0x10;    //Einer Min
325
    BCDDecode(&segstr[2]);
326
  break;
327
  case 3:  
328
    PORTC=0x20;    //Zehne Min
329
    BCDDecode(&segstr[3]);
330
  break;
331
  case 4:
332
    PORTC=0x40;    //Einer Std
333
    BCDDecode(&segstr[4]);
334
  break;
335
  case 5:  
336
    PORTC=0x80;    //Zehne Std  
337
    BCDDecode(&segstr[5]);
338
    Z=-1;
339
  break;
340
  }
341
}
342
343
void BCDDecode(segment *Wert)
344
{
345
  PORTA=0x00;
346
  if((*Wert).dp==0)  //Kein Punkt
347
  {
348
    PORTA|=0x80;  //Punkt löschen
349
  }
350
  else
351
  {
352
    PORTA&=0x7F;  //Punkt setzen
353
  }
354
  switch((*Wert).Zahl)
355
  {
356
    case 0: PORTA|= 0x01;  break;
357
    case 1: PORTA|= 0x37;  break;
358
    case 2: PORTA|= 0x42;  break;
359
    case 3: PORTA|= 0x12;  break;
360
    case 4: PORTA|= 0x34;  break;
361
    case 5: PORTA|= 0x18;  break;
362
    case 6: PORTA|= 0x08;  break;
363
    case 7: PORTA|= 0x33;  break;
364
    case 8: PORTA|= 0x00;  break;
365
    case 9: PORTA|= 0x10;  break;
366
    case 10: PORTA|= 0x70;  break; //°
367
    case 11: PORTA|= 0x7F;  break; //Leer
368
    case 12: PORTA|= 0x7E;  break; //Minus
369
    default: PORTA|= 0x12;  break; //-->3.
370
  }
371
}

uhr.h
1
typedef struct
2
{
3
  unsigned short int Zahl;
4
  unsigned short int dp;
5
} segment;
6
7
unsigned short int Zeit[60];
8
segment Anzeige[6];
9
unsigned short int Weckzeit[6];
10
11
void Uhr_Sek();
uhr.c
1
#include <avr/io.h>
2
#include "Uhr.h" 
3
#include "delay.h"
4
5
void Uhr_Sek()
6
{
7
  Anzeige[0].Zahl++;        //Sekunde
8
  if(Anzeige[0].Zahl==10)      
9
  {
10
    Anzeige[0].Zahl=0;      //Zehner_Sek
11
    Anzeige[1].Zahl++;
12
    if(Anzeige[1].Zahl==6)    
13
    {
14
      Anzeige[1].Zahl=0;    //Einer_Min
15
    }
16
  }
17
}

von Bitflüsterer (Gast)


Lesenswert?

Ja, ja. Das mit dem Lesen funktioniert noch nicht so recht. Das sollten 
wir nochmal üben. :-)

Wichtige Regeln - erst lesen, dann posten!
    <snip>
    Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

von Matze (Gast)


Lesenswert?

Stimmt, wäre hier sinvoll gewesen ;-)

von Daniel S. (daniel_s49)


Lesenswert?

soo viel Code ;-)

Die Parität des Datums funktioniert nie, die Paritäten von Minute und 
Stunde funktionieren immer? Hast du sonst mal die Datums-Paritäten 
(Zeit[58] und die berechnete par) ausgegeben? GgF. mal selber 
nachrechnen, wie der Wert sein sollte und gucken, ob in den Variablen 
überhaupt das richtige steht.

Ansonsten ist das Paritätsbit das letzte der Übertragung. Sowas ist 
gerne mal ein typischer Off-By-One Error. Sprich, du fängst schon mit 
der Auswertung an, obwohl das letzte Bit noch nicht empfangen wurde.
Ich bin jetzt nicht komplett in den Code eingestiegen, aber sagt der 
folgende Schnipsel nicht, dass du zu Beginn des 58. Bit direkt mit der 
Auswertung beginnst? Obwohl du in der anderen ISR erst 100ms später 
herausbekommst, ob das 58. Bit eine 1 oder eine 0 ist?
Als Quickfix vielleicht mal ausprobieren die Auswertung bei 
Prot_Start==0 zu machen oder aber erst bei der fallenden Flanke zu 
reagieren.
1
  if(DCF77flag==0)  //Steigende Pflanke
2
  {
3
    if((Prot_Start>=0)&&(Prot_Start<=57))  //Zurücksetzten am Ende der Minute
4
    {
5
      Prot_Start++;
6
    }    
7
    if((Prot_Start==58))  //Auswertung der Zeitinformation am ende einer Minute


Unabhängig von deinem Fehler fällt mir grad noch ins Auge, dass Minute 
64 formal korrekt ist. Das <=6 bei der Überprüfung stimmt nicht. (Tritt 
vermutlich eh nie auf und fällt damit auch nie auf)

: Bearbeitet durch User
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.