1 | //Header Dateien
|
2 | #include <avr/interrupt.h>
|
3 | #include "dcf_clock.h"
|
4 |
|
5 | /////////////
|
6 | //Variablen//
|
7 | /////////////
|
8 | //date
|
9 | uint8_t week_day;
|
10 | uint8_t day;
|
11 | uint8_t month;
|
12 | uint16_t year;
|
13 |
|
14 | //time
|
15 | uint16_t millisecond;
|
16 | uint8_t second;
|
17 | uint8_t minute;
|
18 | uint8_t hour;
|
19 | uint8_t timezone;
|
20 |
|
21 | //Speicherbereich für DCF-Pegel
|
22 | uint8_t dataPC;
|
23 |
|
24 | //Pegel-Auswertung
|
25 | uint16_t counter_high;
|
26 | uint16_t counter_low;
|
27 | uint8_t bit_number;
|
28 |
|
29 | //dcf_date
|
30 | uint8_t dcf_week_day;
|
31 | uint8_t dcf_day;
|
32 | uint8_t dcf_month;
|
33 | uint8_t dcf_year;
|
34 | uint8_t dcf_date_parity;
|
35 |
|
36 | //dcf_time
|
37 | uint8_t dcf_second;
|
38 | uint8_t dcf_minute;
|
39 | uint8_t dcf_minute_parity;
|
40 | uint8_t dcf_hour;
|
41 | uint8_t dcf_hour_parity;
|
42 | uint8_t dcf_timezone;
|
43 |
|
44 | //Puffer für die int --> char Umwandlung
|
45 | char itoa_buffer[8];
|
46 |
|
47 | //Array für die DCF-Datenbits
|
48 | //uint8_t minute_frame[60]; //wird noch nicht genutzt
|
49 |
|
50 | //Schaltjahr
|
51 | uint8_t leapyear;
|
52 |
|
53 | void initClock(void)
|
54 | {
|
55 | //Setzen der Port-Richtungsregister
|
56 | DDRD &= ~(1<<PD2); //PD2 Eingang (0)
|
57 | //Initialisieren der Ports
|
58 | //PORTD |= (1<<PD2); //PD2 Pull-Up gesetzt (1)
|
59 |
|
60 | // Timer 1 konfigurieren
|
61 | TCCR1A = 0;
|
62 | TCCR1B |=(1<<WGM12)|(1<<CS12);
|
63 | OCR1A = 57;
|
64 | TIMSK |= (1<<OCIE1A); //Compare Interrupt erlauben (1)
|
65 | }
|
66 |
|
67 |
|
68 | ////////////////////
|
69 | //Reset-Funktionen//
|
70 | ////////////////////
|
71 | void counter_reset(void)
|
72 | {
|
73 | counter_high=0;
|
74 | counter_low=0;
|
75 | bit_number=0;
|
76 | }
|
77 |
|
78 | void dcf_date_reset(void)
|
79 | {
|
80 | dcf_week_day=0;
|
81 | dcf_day=0;
|
82 | dcf_month=0;
|
83 | dcf_year=0;
|
84 | dcf_date_parity=0;
|
85 | }
|
86 |
|
87 | void dcf_time_reset(void)
|
88 | {
|
89 | dcf_minute=0;
|
90 | dcf_minute_parity=0;
|
91 | dcf_hour=0;
|
92 | dcf_hour_parity=0;
|
93 | dcf_timezone=0;
|
94 | }
|
95 |
|
96 | ///////////////////////
|
97 | //DCF-Synchronisation//
|
98 | ///////////////////////
|
99 | //High-Pegel muß für 1700-1900ms anliegen
|
100 | //Danach muß ein Low-Pegel folgen
|
101 | void dcf_sync(void)
|
102 | {
|
103 | if(!(dataPC & (1<<PIND2)))
|
104 | {
|
105 | if(counter_high>=1750 && counter_high<=1950)
|
106 | {
|
107 |
|
108 | counter_reset();
|
109 | dcf_date_reset();
|
110 | dcf_time_reset();
|
111 | }
|
112 | else
|
113 | {
|
114 | counter_high=0;
|
115 | dcf_sync();
|
116 | }
|
117 | }
|
118 | else
|
119 | {
|
120 | dcf_sync();
|
121 | }
|
122 | }
|
123 |
|
124 | //////////////////
|
125 | //DCF-Auswertung//
|
126 | //////////////////
|
127 | void dcf_0(void)
|
128 | {
|
129 | switch(bit_number)
|
130 | {
|
131 | case 0: ;break; //Start einer neuen Minuten, muß immer 0 sein
|
132 | case 1: ;break; //Wetterdaten
|
133 | case 2: ;break; //Wetterdaten
|
134 | case 3: ;break; //Wetterdaten
|
135 | case 4: ;break; //Wetterdaten
|
136 | case 5: ;break; //Wetterdaten
|
137 | case 6: ;break; //Wetterdaten
|
138 | case 7: ;break; //Wetterdaten
|
139 | case 8: ;break; //Wetterdaten
|
140 | case 9: ;break; //Wetterdaten
|
141 | case 10: ;break; //Wetterdaten
|
142 | case 11: ;break; //Wetterdaten
|
143 | case 12: ;break; //Wetterdaten
|
144 | case 13: ;break; //Wetterdaten
|
145 | case 14: ;break; //Wetterdaten
|
146 | case 15: ;break; //Rufbit für PTB
|
147 | case 16: ;break; //Keine Änderung der Zeitzone
|
148 | case 17: ;break; //Zeitzone: dcf_timezone=dcf_timezone
|
149 | case 18: dcf_timezone+=1;break; //Zeitzone:
|
150 | case 19: ;break; //keine Schaltsekunde
|
151 | case 20: dcf_sync();break; //Beginn der Zeitinformation (immer 1)
|
152 | case 21: ;break;
|
153 | case 22: ;break;
|
154 | case 23: ;break;
|
155 | case 24: ;break;
|
156 | case 25: ;break;
|
157 | case 26: ;break;
|
158 | case 27: ;break;
|
159 | case 28: ;break; //Parität: Minute
|
160 | case 29: ;break;
|
161 | case 30: ;break;
|
162 | case 31: ;break;
|
163 | case 32: ;break;
|
164 | case 33: ;break;
|
165 | case 34: ;break;
|
166 | case 35: ;break; //Parität: Stunde
|
167 | case 36: ;break;
|
168 | case 37: ;break;
|
169 | case 38: ;break;
|
170 | case 39: ;break;
|
171 | case 40: ;break;
|
172 | case 41: ;break;
|
173 | case 42: ;break;
|
174 | case 43: ;break;
|
175 | case 44: ;break;
|
176 | case 45: ;break;
|
177 | case 46: ;break;
|
178 | case 47: ;break;
|
179 | case 48: ;break;
|
180 | case 49: ;break;
|
181 | case 50: ;break;
|
182 | case 51: ;break;
|
183 | case 52: ;break;
|
184 | case 53: ;break;
|
185 | case 54: ;break;
|
186 | case 55: ;break;
|
187 | case 56: ;break;
|
188 | case 57: ;break;
|
189 | case 58: ;break; //Parität: Datum
|
190 | case 59: dcf_sync();break; //keine Absenkung --> neue Minute
|
191 | default: dcf_sync();break;
|
192 | }
|
193 | }
|
194 |
|
195 | void dcf_1(void)
|
196 | {
|
197 | switch(bit_number)
|
198 | {
|
199 | case 0: dcf_sync();break; //Start einer neuen Minute, muß immer 0 sein
|
200 | case 1: ;break; //Wetterdaten
|
201 | case 2: ;break; //Wetterdaten
|
202 | case 3: ;break; //Wetterdaten
|
203 | case 4: ;break; //Wetterdaten
|
204 | case 5: ;break; //Wetterdaten
|
205 | case 6: ;break; //Wetterdaten
|
206 | case 7: ;break; //Wetterdaten
|
207 | case 8: ;break; //Wetterdaten
|
208 | case 9: ;break; //Wetterdaten
|
209 | case 10: ;break; //Wetterdaten
|
210 | case 11: ;break; //Wetterdaten
|
211 | case 12: ;break; //Wetterdaten
|
212 | case 13: ;break; //Wetterdaten
|
213 | case 14: ;break; //Wetterdaten
|
214 | case 15: ;break; //Rufbit für PTB
|
215 | case 16: ;break; //Am Ende dieser Stunde wird auf MEZ/MESZ umgestellt
|
216 | case 17: dcf_timezone+=1;break; //Zeitzone:
|
217 | case 18: ;break; //Zeitzone: dcf_timezone=dcf_timezone
|
218 | case 19: ;break; //Am Ende diese Stunde wird eine Schaltsekunde eingefügt.
|
219 | case 20: ;break; //Beginn der Zeitinformation (immer 1)
|
220 | case 21: dcf_minute+=1;dcf_minute_parity+=1;break;
|
221 | case 22: dcf_minute+=2;dcf_minute_parity+=1;break;
|
222 | case 23: dcf_minute+=4;dcf_minute_parity+=1;break;
|
223 | case 24: dcf_minute+=8;dcf_minute_parity+=1;break;
|
224 | case 25: dcf_minute+=10;dcf_minute_parity+=1;break;
|
225 | case 26: dcf_minute+=20;dcf_minute_parity+=1;break;
|
226 | case 27: dcf_minute+=40;dcf_minute_parity+=1;break;
|
227 | case 28: dcf_minute_parity+=1;break; //Parität: Minute
|
228 | case 29: dcf_hour+=1;dcf_hour_parity+=1;break;
|
229 | case 30: dcf_hour+=2;dcf_hour_parity+=1;break;
|
230 | case 31: dcf_hour+=4;dcf_hour_parity+=1;break;
|
231 | case 32: dcf_hour+=8;dcf_hour_parity+=1;break;
|
232 | case 33: dcf_hour+=10;dcf_hour_parity+=1;break;
|
233 | case 34: dcf_hour+=20;dcf_hour_parity+=1;break;
|
234 | case 35: dcf_hour_parity+=1;break; //Parität: Stunde
|
235 | case 36: dcf_day+=1;dcf_date_parity+=1;break;
|
236 | case 37: dcf_day+=2;dcf_date_parity+=1;break;
|
237 | case 38: dcf_day+=4;dcf_date_parity+=1;break;
|
238 | case 39: dcf_day+=8;dcf_date_parity+=1;break;
|
239 | case 40: dcf_day+=10;dcf_date_parity+=1;break;
|
240 | case 41: dcf_day+=20;dcf_date_parity+=1;break;
|
241 | case 42: dcf_week_day+=1;dcf_date_parity+=1;break;
|
242 | case 43: dcf_week_day+=2;dcf_date_parity+=1;break;
|
243 | case 44: dcf_week_day+=4;dcf_date_parity+=1;break;
|
244 | case 45: dcf_month+=1;dcf_date_parity+=1;break;
|
245 | case 46: dcf_month+=2;dcf_date_parity+=1;break;
|
246 | case 47: dcf_month+=4;dcf_date_parity+=1;break;
|
247 | case 48: dcf_month+=8;dcf_date_parity+=1;break;
|
248 | case 49: dcf_month+=10;dcf_date_parity+=1;break;
|
249 | case 50: dcf_year+=1;dcf_date_parity+=1;break;
|
250 | case 51: dcf_year+=2;dcf_date_parity+=1;break;
|
251 | case 52: dcf_year+=4;dcf_date_parity+=1;break;
|
252 | case 53: dcf_year+=8;dcf_date_parity+=1;break;
|
253 | case 54: dcf_year+=10;dcf_date_parity+=1;break;
|
254 | case 55: dcf_year+=20;dcf_date_parity+=1;break;
|
255 | case 56: dcf_year+=40;dcf_date_parity+=1;break;
|
256 | case 57: dcf_year+=80;dcf_date_parity+=1;break;
|
257 | case 58: dcf_date_parity+=1;break; //Parität: Datum
|
258 | case 59: dcf_sync();break; //keine Absenkung --> neue Minute
|
259 | default: dcf_sync();break;
|
260 | }
|
261 | }
|
262 | /////////////////////////
|
263 | //Berechnung Schaltjahr//
|
264 | /////////////////////////
|
265 | void leap_year(void)
|
266 | {
|
267 | if(year%4==0 && year%100!=0)
|
268 | {
|
269 | leapyear=1; //Schaltjahr, da durch 4 teilbar aber nicht durch 100
|
270 | }
|
271 | else
|
272 | {
|
273 | if(year%4!=0)
|
274 | {
|
275 | leapyear=0;//Kein Schaltjahr, da nicht durch 4 teilbar
|
276 | }
|
277 | else
|
278 | {
|
279 | if(year%400==0)
|
280 | {
|
281 | leapyear=1;//Schaltjahre, da durch 400 teilbar
|
282 | }
|
283 | else
|
284 | {
|
285 | leapyear=0;//Kein Schaltjahr, da durch 100 teilbar aber nicht durch 400
|
286 | }
|
287 | }
|
288 | }
|
289 | }
|
290 |
|
291 | /////////////////////////////
|
292 | //Interrupt Service Routine//
|
293 | /////////////////////////////
|
294 | //Der Compare Interrupt Handler wird aufgerufen, wenn TCNT0 = OCR0 = 250-1 ist (250 Schritte), d.h. genau alle 1 ms
|
295 | ISR (TIMER1_COMPA_vect)
|
296 | {
|
297 | millisecond++; //Counter für die Millisekunden
|
298 | dataPC = PIND; //Der aktuelle Pegel vom DCF-Modul wird eingelesen und in dataPC den anderen Funktionen zur Verfügung gestellt
|
299 | counter_high++; //Counter für die Bit-Auswertung (Dauer des High-Pegels), Rücksetzen muß in den Funktionen geschehen
|
300 | counter_low++; //Counter für die Bit-Auswertung (Dauer des Low-Pegels), Rücksetzen muß in den Funktionen geschehen
|
301 | if(millisecond==1000) //"selbstlaufende" Uhr
|
302 | {
|
303 | second++;
|
304 | millisecond=0;
|
305 | if(second==60)
|
306 | {
|
307 | minute++;
|
308 | second=0;
|
309 | }
|
310 | if(minute==60)
|
311 | {
|
312 | hour++;
|
313 | minute=0;
|
314 | }
|
315 | if(hour==24)
|
316 | {
|
317 | day++;
|
318 | week_day++;
|
319 | hour=0;
|
320 | }
|
321 | if(week_day==8)
|
322 | {
|
323 | week_day=1;
|
324 | }
|
325 | switch(day)
|
326 | {
|
327 | case 29: //Tag 28
|
328 | {
|
329 | leap_year();
|
330 | if(month==2 && leapyear==0)
|
331 | {
|
332 | month++;
|
333 | day=1;
|
334 | }
|
335 | }
|
336 | break;
|
337 |
|
338 | case 30: //Tag 29
|
339 | {
|
340 | leap_year();
|
341 | if(month==2 && leapyear==1)
|
342 | {
|
343 | month++;
|
344 | day=1;
|
345 | }
|
346 | }
|
347 | break;
|
348 |
|
349 | case 31: //Tag 30
|
350 | {
|
351 | if(month==4 || month==6 || month==9 || month==11)
|
352 | {
|
353 | month++;
|
354 | day=1;
|
355 | }
|
356 | }
|
357 | break;
|
358 |
|
359 | case 32: //Tag 31
|
360 | {
|
361 | if(month==1 || month==3 || month==5 || month==7|| month==8 || month==10 || month==12)
|
362 | {
|
363 | month++;
|
364 | day=1;
|
365 | }
|
366 | }
|
367 | break;
|
368 |
|
369 | default: ;break;
|
370 | }
|
371 | if(month==13)
|
372 | {
|
373 | year++;
|
374 | month=1;
|
375 | }
|
376 | }
|
377 | }
|
378 |
|
379 | ////////////////////////////////////////////////////////
|
380 | //Zusammenführung der internen Daten und der DCF-Daten//
|
381 | ////////////////////////////////////////////////////////
|
382 | void match_date(void)
|
383 | {
|
384 | week_day=dcf_week_day;
|
385 | day=dcf_day;
|
386 | month=dcf_month;
|
387 | year=2000+dcf_year;
|
388 | }
|
389 |
|
390 | void match_time(void)
|
391 | {
|
392 | millisecond=0;
|
393 | second=0;
|
394 | minute=dcf_minute;
|
395 | hour=dcf_hour;
|
396 | timezone=dcf_timezone;
|
397 | }
|
398 |
|
399 | ///////////////////////
|
400 | //DCF-Pegelauswertung//
|
401 | ///////////////////////
|
402 | void level_analysis(void)
|
403 | {
|
404 | if(dataPC & (1<<PIND2))
|
405 | {
|
406 |
|
407 | if(counter_low>=60 && counter_low<=140) //logisch 0
|
408 | {
|
409 | // minute_frame[bit_number]=0;
|
410 |
|
411 | dcf_0();
|
412 |
|
413 | bit_number++;
|
414 | dcf_second++;
|
415 |
|
416 | counter_high=0;
|
417 | counter_low=0;
|
418 | }
|
419 | else
|
420 | {
|
421 | if(counter_low>=160 && counter_low<=240) //logisch 1
|
422 | {
|
423 | // minute_frame[bit_number]=1;
|
424 |
|
425 | dcf_1();
|
426 |
|
427 | bit_number++;
|
428 |
|
429 | counter_high=0;
|
430 | counter_low=0;
|
431 | }
|
432 | else
|
433 | {
|
434 | counter_low=0;
|
435 | }
|
436 | }
|
437 | }
|
438 | else
|
439 | {
|
440 | if(counter_high>=1750 && counter_high<=1950)
|
441 | {
|
442 | if(bit_number==59 && dcf_minute_parity%2==0 && dcf_hour_parity%2==0 && dcf_date_parity%2==0)
|
443 | {
|
444 | bit_number=0;
|
445 |
|
446 | match_date();
|
447 | match_time();
|
448 | }
|
449 | else
|
450 | {
|
451 | dcf_date_reset();
|
452 | dcf_time_reset();
|
453 |
|
454 | counter_high=0;
|
455 |
|
456 | dcf_sync();
|
457 | }
|
458 |
|
459 | counter_high=0;
|
460 |
|
461 | dcf_date_reset();
|
462 | dcf_time_reset();
|
463 | }
|
464 | }
|
465 | }
|