Forum: Mikrocontroller und Digitale Elektronik ATMega2561 RTC mit Uhrenquarz


von MCProgger (Gast)


Lesenswert?

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
}

von Helmut -. (dc3yc)


Lesenswert?

Kann das sein, dass der ATMEGA mit 32MHz nicht mehr korrekt arbeitet?
=> Quarz mit niedriger Frequenz verwenden!

Ansonsten hilft es vielleicht, wenn du in der ISR nur ein Flag setzt und 
die Berechnung in der Main-Schleife machst.

: Bearbeitet durch User
von MCProgger (Gast)


Lesenswert?

Sorry da habe ich wohl das Komma vergessen das ist ein 32,768 Khz 
Uhrenquarz.
Der µC selber hat einen 14 MHz Quarz.

von Thomas E. (thomase)


Lesenswert?


: Bearbeitet durch User
von MCProgger (Gast)


Lesenswert?

Noch eine kleine Erläuterung zum Uhrenquarz, der ATMega2561 hat extra 
Pins für einen zusätzlichen Uhrenquarz und dieser wird von der Interrupt 
Routine als Taktquelle benutzt.

von MCProgger (Gast)


Lesenswert?

@Thomas Eckmann

Ich habe das jetzt wie im dem Link beschrieben geändert, aber das 
Problem besteht weiterhin. Nach 10min (von Normaler Uhr abgelesen) hat 
der µC 16min also 6 min zu viel.
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
8
ISR(TIMER2_COMPA_vect)
9
{
10
  TCCR2B = TCCR2B;
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
  while(ASSR & ((1<<TCN2UB) | (1<<OCR2AUB) | (1<<OCR2BUB) | (1<<TCR2AUB) | (1<<TCR2BUB)));
77
}
78
79
void InitRTC(void)
80
{
81
  GTCCR |= (1 << TSM) | (1 << PSRASY);  //Timer anhalten, Prescaler Reset
82
  
83
  // Aktiviert den Asynchronous Modus mit externen 32.768kHz Uhrenquarz.
84
  // ASSR – Asynchronous Status Register
85
  // Datenblatt Seite 192
86
  ASSR  = (1<<AS2);
87
    
88
  TCCR2A = (1 << WGM21);                //CTC Modus
89
  
90
  // Setzt den Teiler auf 256
91
  // TCCR2B – Timer/Counter Control Register B
92
  // Datenblatt Seite 190
93
  TCCR2B |= (1<<CS22)| (1<<CS21); // 256
94
95
  
96
  // OCR2A – Output Compare Register A
97
  // Datenblatt Seite 191
98
  OCR2A = 128 - 1; // half second int
99
    
100
  // Aktiviert den TOV2 Interrupt
101
  // TIMSK2 – Timer/Counter2 Interrupt Mask Register
102
  // Datenblatt Seite 193
103
  TIMSK2  = (1<<OCIE2A);
104
  
105
  GTCCR &= ~(1 << TSM);
106
}

von Pete K. (pete77)


Lesenswert?

Was soll denn die While-Schleife in der ISR?

P.S.: Für so etwas nehme ich einen DS3231 oder DS1307.

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

Um auszuschließen, dass second oder minute falsch interpretiert bzw. 
angezeigt werden, zu Beginn der ISR eine LED blinken lassen, der 
Sekundentakt ist, bei einem Fehler von 16:10, klar erkennbar.
Danach kann es nur noch die Hardware sein, d.h. der Quarz schwingt nicht 
auf 32 KiHz.

von MCProgger (Gast)


Lesenswert?

Pete K. schrieb:
> Was soll denn die While-Schleife in der ISR?

Ich habe das aus dem Tutorial (link im Kommentar von Thomas Eckmann).
Warum das jetzt im Interrupt Funkton selbst gemacht werden soll, 
verstehe ich auch nicht.


Pete K. schrieb:
> P.S.: Für so etwas nehme ich einen DS3231 oder DS1307.

Ja, das wäre wohl besser gewesen. Hilft mir leider aber nicht, ich habe 
jetzt den Uhrenquarz mit Interrupt.

von MCProgger (Gast)


Lesenswert?

@ S. Landolt
Ich vermute auch das was am Quarz nicht i.O. sein könnte.

Ich hatte gehofft, das ich irgendein groben Patzer gemacht hätte, 
welchen von jemand anders sofort erkannt wird.

von Thomas E. (thomase)


Lesenswert?

MCProgger schrieb:
> Ich habe das jetzt wie im dem Link beschrieben geändert, aber das
> Problem besteht weiterhin. Nach 10min (von Normaler Uhr abgelesen) hat
> der µC 16min also 6 min zu viel.

Das beschriebene Problem ist ein 100%ig reproduzierbares.

Woran kann es noch liegen?
32,768K : 256 : 128 ergibt eine Sekunde. Das passt.

Ist denn die Sekunde wirklich eine Sekunde lang? Welche Lastkapazitäten 
hängen am Quarz? Eigentlich gehören da gar keine ran.

Mal abgesehen davon, dass das mit dem Uhrenquarz natürlich laufen muss. 
Das läuft auch. Das habe ich mit anderen Controllern auch schon gemacht. 
Es stellt sich trotzdem die Frage, was das soll. Deswegen mache ich 
sowas auch nicht mehr.

MCProgger schrieb:
> Der µC selber hat einen 14 MHz Quarz.

Eine Uhr kannst du auch damit laufen lassen. Auch wenn der Controller 
über getrennte Anschlüsse verfügt. Richtig Sinn macht die Async-RTC nur, 
wenn der Controller sein Hauptdasein im Sleep-Mode fristet. Der wiederum 
macht aber mit einem Quarz für den Systemtakt keinen Sinn.

Der Sekundentakt lässt sich genauso gut aus den 14MHz ableiten. 16-Bit 
Timer hat der Controller doch genug. Da braucht man sich nicht einmal 
mit Softwarezählern grossartig abmühen.

mfg.

: Bearbeitet durch User
von MCProgger (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> Das beschriebene Problem ist ein 100%ig reproduzierbares.

Ja, ich habe es jetzt ein Paar mal gemacht, immer die gleiche 
Abweichung, die Sekunde im µC ist also kleiner als die echte Sekunde.

Thomas Eckmann schrieb:
> Ist denn die Sekunde wirklich eine Sekunde lang? Welche Lastkapazitäten
> hängen am Quarz? Eigentlich gehören da gar keine ran.

Ich habe die Hardware nicht gemacht, und muß mich jetzt wohl mit dem der 
sie gemacht hat unterhalten.

Thomas Eckmann schrieb:
> Eine Uhr kannst du auch damit laufen lassen. Auch wenn der Controller
> über getrennte Anschlüsse verfügt. Richtig Sinn macht die Async-RTC nur,
> wenn der Controller sein Hauptdasein im Sleep-Mode fristet.

Der Controller ist die meißte Zeit im Sleep, es ist ein Datenlogger.

Thomas Eckmann schrieb:
> Der Sekundentakt lässt sich genauso gut aus den 14MHz ableiten. 16-Bit
> Timer hat der Controller doch genug. Da braucht man sich nicht einmal
> mit Softwarezählern grossartig abmühen.

Ja, zur not werde ich das so irgendwie machen, aber erstmal rede ich mit 
dem der Hardware gemacht hat. Ich glaube, da ist irgendetwas mit dem 
Quarz nicht in Ordnung.

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.