Ungenaue Sekunde bei Timer1 im CTC-Modus

OP #2589024
Lesenswert?

Hallo!

Meine Sekunde ist beim Timer1 im CTC-Modus keine genaue Sekunde! Nach 10 
Sekunden habe ich ca. eine Abweichung von 1 Sekunde. Ich verwende den 
ATtiny44.

Meine Frequenz beträgt 1MHz. Den Timer Compare Match habe ich auf 50000 
gesetzt. Also alle 20ms ein Timer-Interrupt.

Hier meine Initialisierung und die ISR:
1
void start_timer1(void)
2
{
3
  TIMSK1 |=  (1<<TOIE1);          // Timer1 overflow interrupt enable
4
  TIMSK1 |=  (1<<OCIE1A);        // Interrupt bei Timer Compare
5
  TCCR1B |=  (1<<CS10);          // Prescaler = 1 (f=1MHz)
6
  TCCR1B |=  (1<<WGM12);          // CTC-Mode (Clear Timer on Compare)
7
  OCR1A  =  50000;            // Set timer1 match to 50000
8
}
9
.
10
.
11
.
12
ISR (TIM1_COMPA_vect)
13
{
14
  if (overflow <= 20)        // count 20 timeroverflows ( 1 second )
15
    overflow ++;
16

17
  else
18
  {    
19
    PORTA |= (1<<PA5);
20
    overflow = 0;        // reset counter for timeroverflows
21
    sekunden ++;        // count seconds
22

23
    ADC_Wert = Read_ADC();    // ADC value (sense voltage) einlesen
24
    ADC_gesamt += ADC_Wert; 
25
    PORTA &= ~(1<<PA5);
26
  }
27
}
Gast #2589031
Lesenswert?

Diesen Denkfehler hatte ich letzte Woche auch mal :-)
Anstatt mit 50000 musst du das Compare Register mit 50000-1 laden, dann 
hast du den Überlauf wirklich nach 50000 Zählschritten.

Der Fehler summiert sich natürlich auf je länger deine Software läuft.

Viele Grüße,
lex
OP #2590014
Lesenswert?

Johann L. schrieb:
> H. G. schrieb:
>
>> Meine Frequenz beträgt 1MHz. Den Timer Compare Match habe ich auf 50000
>> gesetzt. Also alle 20ms ein Timer-Interrupt.
>
> Die Formel für den OCR-Wert im CTC-Mode ist:
>
> (unsigned long) F_CPU / PRESCALE / IRQS -1
>
> F_CPU    = 1000000
> PRESCALE = 1
> IRQS     = 1 / 20m = 50
>
> --> OCR1A = 19999

Das verstehe ich jetzt nicht. warum 20000 bzw.19999?

Der Mikrocontroller wird mit 1 MHz betrieben. Bei einem Teiler von 1 
zählt der Timer also mit 1000000 / 1 = 1000000 Pulsen pro Sekunde.
Wenn ich den Timer nun mit 50000 vorlade, dann erhalte ich demnach 20 
Überläufe pro Sekunde. Also ist nach 20 Überläufen "genau" eine Sekunde 
vergangen.
#2590026
Lesenswert?

@H. G. (ledi)

>zählt der Timer also mit 1000000 / 1 = 1000000 Pulsen pro Sekunde.

Jao.

>Wenn ich den Timer nun mit 50000 vorlade,

Nix Vorladen, das ist der VERGLEICHSWERT, nachdem der Zähler wieder bei 
Null anfängt.

> dann erhalte ich demnach 20

Nö, einen Bruchteil weniger. Er zählt von 0-50000, damit einen Takt zu 
lange. 0-49999 sind 5000 Takte und damit exakt.

MFG
Falk
Gast #2590041
Lesenswert?

teste es doch einfach im Simulator, der zeigt genau an wie lange die 
sekunde ist. Dann kannst du wenigsten den Quarz( oder RC) als 
fehlerquelle ausschließen. Wenn die simulation schon nicht stimm, dann 
brauchst du es auch nicht auf der hardware laufen zu lassen.
#2590052
Lesenswert?

H. G. schrieb:
> Floh schrieb:
>> H. G. schrieb:
>>> if (overflow <= 20)        // count 20 timeroverflows ( 1 second )
>>>     overflow ++;
>>
>> Wieviele Durchläufe gibt das?
>
> 20

Nö. 21

Zähl nach. Angenommen da stünde nicht 20 sondern 5 (kleiner Zahl damit 
wir nicht s0 viel schreiben müssen). Wieviele Zählvogänge hast du bei 
...


  if( overflow <= 5)
    overflow++;
  else
    overflow = 0;

bis du von 0 einmal rundum wieder bei 0 bist

  0  -
  1  - 1 Zählvorgang
  2    2
  3    3
  4    4
  5    5
  0    6

zähl nach: nach 6 mal erhöhen bist du einmal rundum wieder bei 0 
angelangt.
(UNd genau aus dem gleichen Grund musst du auch das OCR Register um 1 
weniger laden)

In den allermeisten Fällen musst du sofort zusammenzucken, wenn du in C 
ein <= im Zusammenhang mit irgendwelchen Zählsachen siehst. Meistens ist 
es falsch. Aus genau dem gleichen Grund wird zb eine for Schleife 
meistens diese Gestalt haben

    for( i = 0; i < 5; i++ )

diese Schleife wird 5-mal durchlaufen.
#2590055
Lesenswert?

> Es liegt an der Ungenauigkeit der internen RC.

Auch. Aber das ist nicht alles. Du hast einen Denkfehler bei der 
Zählung.
Eigentlich hast du in deinem Programm 3 Fehler

* den internen RC
* den falschen Compare Wert
* du zählst nicht 20 sondern 21 Wiederholungen

Durch Anpassen des Compare Wertes kannst du alle zum Verschwinden 
bringen. Aber insbesondere der 20-21 Fehler ist dadurch ja immer noch im 
Programm.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren