Forum: Mikrocontroller und Digitale Elektronik simpler Sekunden-Timer mit AVR


von Q_M (Gast)


Lesenswert?

Ich möchte jede Sekunde eine Berechnung ausführen. Wobei es nicht 
supergenau auf die Sekunde ankommt. Kann auch paar Promille abweichen.
1. innerhalb der While(1) mit _delay_ms(1000)
2. mit Timer interrupt

Ich denke 2. ist sauberer.

Da stellen sich die Fragen:
- mit CTC interrupt?
- oder mit Timer Overflow interrupt?
- Kann man das auch mit dem 8-Bit Timer realisieren oder brauchts den 
16er ?
- Andere meinen man soll den WDT nehmen..

von S. R. (svenska)


Lesenswert?

Timer ist besser. Für sowas nimmt man eher den Overflow-Modus.
Wenn der Timer zu schnell zählt, dann zählst du in der Timer-ISR eben 
noch eine zweite Variable mit, dann kommst du auch mit einem 8-Bit Timer 
aus.

von Falk B. (falk)


Lesenswert?

@ Q_M (Gast)

>Ich möchte jede Sekunde eine Berechnung ausführen. Wobei es nicht
>supergenau auf die Sekunde ankommt. Kann auch paar Promille abweichen.

Dann brauchst du einen Quarz an deinem AVR.

>1. innerhalb der While(1) mit _delay_ms(1000)

Nein.

>2. mit Timer interrupt

Ja.

>Ich denke 2. ist sauberer.

Ja.

>- mit CTC interrupt?
>- oder mit Timer Overflow interrupt?
>- Kann man das auch mit dem 8-Bit Timer realisieren oder brauchts den
>16er ?

Geht mit allen drei Möglichkeiten, bei bestimmten Quarzfrequenzen mal 
etwas einfacher, mal etwas komplizierter. Siehe Timer.


>- Andere meinen man soll den WDT nehmen..

Nein, der ist ungenau.

von degoode (Gast)


Lesenswert?

Dafür kommt einzig und alleine ein 8 Bit Timer mit dem "CTC-Interrupt" 
infrage. Ein 16 Bit Timer ist zu wertvoll und rausgeschmissene Recource. 
Eine while Abfrage für ein delay blockiert die ganze Schleife. Man 
könnte ein Timer auch mehrfach ausnutzen um Recourcen zu entlasten.

von grundschüler (Gast)


Lesenswert?

1
init_timer_smh() {
2
/*
3
cs02+01+00:
4
0 no clock
5
1 no presc
6
2 /8
7
3 /64
8
4 /256
9
5 /1024
10
*/
11
12
TCCR0A |= (1<<WGM01);
13
    // 1; Timer0 Vorteiler: 64 -> bei 16 MHz: 
14
    // 16.000.000 / 64 = 250000 Mal pro Sek gibts einen Takt an den Timer
15
TCCR0B |= ((1<<CS02)|(1<<CS00));//1024
16
    
17
    // Timer0 soll bei 250 einen Output Compare Interrupt auslösen ->
18
    // 250.000 / 250 = 1000 mal pro Sek gibts einen Interrupt
19
OCR0A = 77;
20
21
    //Compare Interrupt aktivieren
22
TIMSK0 |= (1<<OCIE0A);
23
24
    //Globale Interrupts aktivieren
25
sei();
26
}
27
28
29
ISR(TIMER0_COMPA_vect)
30
{
31
timer_proc_10ms();
32
}

Timer für den m328 etc. bei 8MHz. Im timer_proc_10ms dann bis zu Sekunde 
hochzählen. Genauigkeit 100/255-> +-0,5%

von Q_M (Gast)


Lesenswert?

grundschüler schrieb:
> init_timer_smh() {
> /*
> cs02+01+00:
> 0 no clock
> 1 no presc
> 2 /8
> 3 /64
> 4 /256
> 5 /1024
> */
>
> TCCR0A |= (1<<WGM01);
>     // 1; Timer0 Vorteiler: 64 -> bei 16 MHz:
>     // 16.000.000 / 64 = 250000 Mal pro Sek gibts einen Takt an den
> Timer
> TCCR0B |= ((1<<CS02)|(1<<CS00));//1024
>
>     // Timer0 soll bei 250 einen Output Compare Interrupt auslösen ->
>     // 250.000 / 250 = 1000 mal pro Sek gibts einen Interrupt
> OCR0A = 77;
>
>     //Compare Interrupt aktivieren
> TIMSK0 |= (1<<OCIE0A);
>
>     //Globale Interrupts aktivieren
> sei();
> }
>
> ISR(TIMER0_COMPA_vect)
> {
> timer_proc_10ms();
> }
>
> Timer für den m328 etc. bei 8MHz. Im timer_proc_10ms dann bis zu Sekunde
> hochzählen. Genauigkeit 100/255-> +-0,5%

Danke,

ist genau mein System: mega328 mit 8Mhz extern.
Aber dein Beispiel passt nicht zum Text, bzw. löst glaub alle 1ms aus.

Wie hast du denn das OCR0A berechnet?

von Counterdenker (Gast)


Lesenswert?

grundschüler schrieb:
> ISR(TIMER0_COMPA_vect)
> {
> timer_proc_10ms();
> }

Im Compare Modus wird der Timer nicht zurückgesetzt sondern
läuft einfach weiter. Daher muss in der ISR der Counter "von
Hand" zurückgesetzt werden (--> ergibt Ungenauigkeit bei
jedem ISR-Eintritt).

Daher lieber den Overflow-Modus anwenden, da braucht am Counter
nichts gesetzt werden.

von degoode (Gast)


Lesenswert?

Counterdenker schrieb:
> Im Compare Modus wird der Timer nicht zurückgesetzt sondern
> .
> Daher lieber den Overflow-Modus anwenden, da braucht am Counter

Jetzt hab ich sämtliche Datenblätter durchschaut und finde weder 
"Compare Modus" noch "Overflow-Modus" darin. Von was sprichst du. Falls 
du mit Compare Modus den CTC (Clear Timer On Compare) Modus meinst: da 
wird der Timer sehr wohl zurückgesetzt.

von wendelsberg (Gast)


Lesenswert?


von grundschüler (Gast)


Lesenswert?

Q_M schrieb:
> Wie hast du denn das OCR0A berechnet?

ich habe auch 8MHz intern. Das OCR0A habe ich solange probiert, bis die 
geringste Gangabweichung der Uhr erreicht war. Etwa alle 5 Minuten 1sec 
Abweichung. Wenn das stört müsste man z.B. jede Stunde den 
Gangunterschied ausgleichen.

Counterdenker schrieb:
> Im Compare Modus wird der Timer nicht zurückgesetzt

Das glaube ich nicht. Wenn das stimmen würde, hätte die Veränderung von 
OCR0A keinen Einfluss auf die Bestimmung der Uhrzeit. Hat sie aber.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Counterdenker schrieb:
> Im Compare Modus wird der Timer nicht zurückgesetzt sondern
> läuft einfach weiter. Daher muss in der ISR der Counter "von
> Hand" zurückgesetzt werden (--> ergibt Ungenauigkeit bei
> jedem ISR-Eintritt).

 Das ist mir aber neu.
 Es gibt sowas wie CTC - Clear Timer on Compare match, und wenn
 es kein PWM ist, benutzt man genau diesen Modus.

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.