Ich möchte mit dem ATMega2561 eine Uhr programmieren. Dafür habe ich den µC einen 32768kHz Uhrenquarz gegeben. Die Interrupt Routine wird auch aufgerufen, aber die Zeit stimmt nicht. Wenn ich die Uhr 10min laufen lasse gibt es schon Differenzen im Minuten Bereich. Ich denke ich habe irgendo was falsch konfiguriert, finde aber den Fehler nicht. Kann mir da jemand einen Hinweis geben?
1 | volatile uint8_t second = 0; |
2 | volatile uint8_t minute = 0; |
3 | volatile uint8_t hour = 0; |
4 | volatile uint8_t day = 1; |
5 | volatile uint8_t month = 1; |
6 | volatile uint8_t year = 15; |
7 | volatile uint8_t halfSecFlag = 0; |
8 | |
9 | ISR(TIMER2_OVF_vect) |
10 | { |
11 | second++; |
12 | if(second == 60) |
13 | { |
14 | second = 0; |
15 | minute++; |
16 | if(minute == 60) |
17 | { |
18 | minute = 0; |
19 | hour++; |
20 | if(hour == 24) |
21 | { |
22 | hour = 0; |
23 | day++; |
24 | switch(month) |
25 | { |
26 | case 9: |
27 | case 4: |
28 | case 6: |
29 | case 11: |
30 | if(day == 31) |
31 | { |
32 | day = 1; |
33 | month++; |
34 | } |
35 | break; |
36 | case 2: |
37 | if((year % 4) == 0) |
38 | { |
39 | if(day == 30) |
40 | { |
41 | day = 1; |
42 | month++; |
43 | } |
44 | } |
45 | else |
46 | { |
47 | if(day == 29) |
48 | { |
49 | day = 1; |
50 | month++; |
51 | } |
52 | } |
53 | break; |
54 | |
55 | default: |
56 | if(day == 32) |
57 | { |
58 | day = 1; |
59 | month++; |
60 | if(month == 13) |
61 | { |
62 | month = 1; |
63 | year ++; |
64 | if(year == 100) |
65 | { |
66 | year = 0; |
67 | } |
68 | } |
69 | } |
70 | break; |
71 | } |
72 | } |
73 | } |
74 | } |
75 | } |
76 | |
77 | ISR(TIMER2_COMPA_vect) |
78 | { |
79 | // Jeder halbe Sekunde |
80 | halfSecFlag = 1; |
81 | } |
82 | |
83 | void InitRTC(void) |
84 | { |
85 | // Deaktiviert die Timer2 Interrups |
86 | // TIMSK2 – Timer/Counter2 Interrupt Mask Register |
87 | // Datenblatt Seite 193 |
88 | TIMSK2 = 0; |
89 | |
90 | // Aktiviert den Asynchronous Modus mit externen 32.768kHz Uhrenquarz. |
91 | // ASSR – Asynchronous Status Register |
92 | // Datenblatt Seite 192 |
93 | ASSR = (1<<AS2); |
94 | |
95 | // Setzt den Initialisierungswert für Counter 2 |
96 | // TCNT2 – Timer/Counter Register |
97 | // Datenblatt Seite 191 |
98 | TCNT2=0; |
99 | |
100 | // OCR2A – Output Compare Register A |
101 | // Datenblatt Seite 191 |
102 | OCR2A = 128 -1; |
103 | |
104 | // Setzt den Teiler auf 128 |
105 | // TCCR2B – Timer/Counter Control Register B |
106 | // Datenblatt Seite 190 |
107 | TCCR2B |= (1<<CS22) | (1<<CS20); // 128 |
108 | //TCCR2B |= (1<<CS22)| (1<<CS21); // 256 |
109 | //TCCR2B |= (1<<CS22)| (1<<CS21) | (1<<CS20); // 1024 |
110 | |
111 | // Wartet bis die Register die neuen Einstellungen übernommen haben. |
112 | // ASSR – Asynchronous Status Register |
113 | // Datenblatt Seite 192 |
114 | while (ASSR & ((1<<TCN2UB) | (1<<TCR2BUB) | (1<<OCR2AUB))); |
115 | |
116 | // Löscht das Interrupt Flag |
117 | // TIFR2 – Timer/Counter2 Interrupt Flag Register |
118 | // Datenblatt Seite 193 |
119 | TIFR2 = (1<<TOV2) | (1<<OCF2A); |
120 | |
121 | // Aktiviert den TOV2 Interrupt |
122 | // TIMSK2 – Timer/Counter2 Interrupt Mask Register |
123 | // Datenblatt Seite 193 |
124 | TIMSK2 = (1<<TOIE2) | (1<<OCIE2A); |
125 | } |