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 | }
|