Forum: Mikrocontroller und Digitale Elektronik Atmega 328P genaue Sekunde Peter Danneger


von Werner P. (Gast)


Lesenswert?

Hallo zusammen,

da ich gerade einen genauen Sekunden Takt (Uhr) brauche habe ich mal den 
Code von Peter Danneger verwendet. Dank an Peter.

Allerdings geht meine Uhr nach ca. 10 Minuten um 2 Sekunden nach. Kann 
es sein dass der externe Quarz so ungenau ist?

Hier der Code. Und es läuft nur dieser Code um Nebeneffekte 
auszuschliessen. Kein weiterer Timer etc. Fuses usw. passen auch.
1
#define XTAL    8000000L
2
#define DEBOUNCE  256L
3
#define uchar unsigned char
4
#define uint unsigned int
5
uchar prescaler;
6
uint volatile second;
7
8
ISR(TIMER1_COMPA_vect) {
9
#if XTAL % DEBOUNCE
10
  OCR1A = XTAL / DEBOUNCE - 1;
11
#endif
12
  if( --prescaler == 0 ) {
13
    prescaler = (uchar)DEBOUNCE;
14
    second++;
15
#if XTAL % DEBOUNCE
16
    OCR1A = XTAL / DEBOUNCE + XTAL % DEBOUNCE - 1;
17
#endif
18
  }
19
20
}
21
22
// Timer Init
23
24
TCCR1B = (1<<WGM12) | (1<<CS10);
25
OCR1A = XTAL / DEBOUNCE - 1;
26
TCNT1 = 0;
27
prescaler = (uchar)DEBOUNCE;
28
second = 0;
29
30
TIMSK1 = (1<<OCIE1A);
31
32
sei();

In der main setze ich second auf 0 wenn > 0 und mache eine UART Ausgabe

Danke und Grüße

: Verschoben durch Moderator
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Werner P. schrieb:
> Hier der Code. Und es läuft nur dieser Code
Mein Compiler meldet einen Fehler mit diesem Code...

> In der main setze ich second auf 0 wenn > 0
Dann lass doch die main auch noch sehen.
Vielleicht solltest du second auf 0 setzen, sondern nur 1 abziehen?
Was, wenn da second schon auf 2 war?

von Werner P. (Gast)


Angehängte Dateien:

Lesenswert?

Dann mal der komplette Source.

@Lothar

Wie soll second auf 2 kommen. Die Interrupt Routine wird nur 1x pro 
Sekunde aufgerufen. So lange kann der Code in der main loop gar nicht 
dauern.

von Marwin (Gast)


Lesenswert?

Sorry, aber ich finde es total daneben, voellig undokumentierten Code zu 
posten und von anderen zu erwarten, dass sie sich da einlesen um Fehler 
zu finden. Auch wenn der Code so kurz ist wie hier.

Wenn du eine genaue Sekunde brauchst, dann setze einen Timer auf, der im 
Sekundentakt laeuft. Fertig. Der Rest ist, ohne weitere Erklaerung, 
voellig ueberfluessig.

von Peter II (Gast)


Lesenswert?

Marwin schrieb:
> Sorry, aber ich finde es total daneben, voellig undokumentierten Code zu
> posten und von anderen zu erwarten, dass sie sich da einlesen um Fehler
> zu finden. Auch wenn der Code so kurz ist wie hier.

was soll hier noch dokumentiert werden?

> sei();  //IRQ einschaltern


@Werner P.
warum lässt du den code nicht einfach mal im Simulator laufen, dann 
diese du wie lange deine sekunde ist. Wenn es dort stimmt, dann wird es 
wohl an der Hardware liegen.

von Jürgen S. (starblue) Benutzerseite


Lesenswert?

Läuft eventuell der RC-Oszillator?

2 Sekunden auf 10 Minuten = 600 Sekunden sind 1/300 ~ 3000ppm,
so ungenau ist normalerweise kein Quarz.

von Werner P. (Gast)


Lesenswert?

@marwin
sei mir nicht böse, aber was muss an dem code dokumentiert werden?

im prinzip geht es darum ob der timer richtig initialisiert wird. und 
ich denke das wird er.

ich habe den code von peter verwendet um zu testen ob meine 
initialisierung passt. beide varianten weichen in 10 minuten um ca. 2 
sekunden ab.

Jetzt mal meine Variante. F_CPU = 8000000UL
1
// Timer1 Init in main
2
// Alle 1/10 Sekunde
3
TCCR1B |= (1<<WGM12); // CTC Modus
4
TCCR1B |= (1<<CS10) | (1<<CS11); // Prescaler 64
5
OCR1A = 12500; // Top Wert
6
TIMSK1 = (1<<OCIE1A); // Interrupt ein
7
8
9
// Timer1 Interrupt
10
ISR(TIMER1_COMPA_vect){
11
  // Alle 1/10 Sekunde
12
  // second ist als globale volatile uint8_t variable definiert
13
  static uint8_t timer_tick;
14
15
  // @mawin. Muss ich das auch dokumentieren? ;-)
16
  timer_tick++;
17
  if (timer_tick == 10) {
18
    timer_tick = 0;
19
    second++;
20
  }
21
}

Setze ich OCR1A auf 12500 - 22 dann ist die Abweichung geringer. Also 
muss doch der Quarz das Problem sein.

von Werner P. (Gast)


Angehängte Dateien:

Lesenswert?

@Jürgen S.

es läuft definitiv der extern Quarz. Habe die Fuses bestimmt 10 mal 
gecheckt. Siehe Anhang.

von eli (Gast)


Lesenswert?

Da wir hier im Markt sind, könnte ich dir 2 sekunden verkaufen.
Dann sollte deine Uhr wieder richtig gehen.

:-)

von Marcus O. (marcus6100)


Lesenswert?

Was auch immer der Müll eigentlich machen soll, DEBOUNCE = 256L an einen 
unsigned char zuzuweisen ist schon grober Unfug.

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.