Timer macht nicht das, was er soll?

Gast #3091523
Lesenswert?
• ▲
▼
Hallo,

ich wollte zuerst einen einfachen Timer programmieren, der jede Sekunde 
eine Variable auf 1 setzt. Dazu habe ich den 8-Bit Timer2 genommen, den 
Prescaler auf 1024 gesetzt und den Overflow Interrupt eingeschaltet. 
Jetzt sollte dieser Interrupt alle 1 / (16.000.000 / 1.024 / 256) = ca. 
61 Millisekunden ausgelöst werden. Dies geschieht aber bei mir nur ca. 
alle 3 bis 5 Millisekunden. Mein Code:

1
#define SET_BIT(x,y) x|=(1<<y)
2
#define CLR_BIT(x,y) x&=~(1<<y)
3
#define TGL_BIT(x,y) x^=(1<<y)
4
#define IS_BIT(x,y)  (x&(1<<y))
5

6

7
volatile int changed = 0;
8

9

10
void setup () {
11
  Serial.begin(9600);
12
  
13
  SET_BIT(TCCR2B, CS20);
14
  SET_BIT(TCCR2B, CS22);
15
  SET_BIT(TIMSK2, TOIE2);
16
}
17

18
void loop () {
19
  long t = millis();
20
  while(changed == 0);
21
  t = millis() - t;
22
  Serial.println(t);
23
  changed = 0;
24
}
25

26
ISR (TIMER2_OVF_vect) {
27
  changed = 1;
28
}

Was mache ich falsch?


Danke schon mal
burgerohnealles
Gast #3091566
Lesenswert?
• ▲
▼
Walter S. schrieb:
> du verwendest timer2, dann musst du auch die Werte für timer2 nehmen

Ahh. Ok. Ich habe jetzt dieses Bit noch gesetzt, aber es funktioniert 
trotzdem noch nicht ganz. Nach meinem Programm wird der Interrupt ca. 
alle 32ms ausgelöst. Es müsste doch ca. alle 16ms sein. Wo ist jetzt der 
Fehler?
#3091574
Lesenswert?
• ▲
▼
Jonathan K. schrieb:
> Warum steht da:
> http://www.mikrocontroller.net/attachment/173218/table.png was anderes
> als da:
> 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_Zähler_des_AVR#8-Bit_Timer.2FCounter
> ?

Weil Atmel zig-verschiedene µC produziert mit jeweils unterschiedlicher 
Ausstattung an Timern.
Ein Tutorial zeigt immer die Dinge beispielsweise anhand eines 
spezifischen µC (und in diesem Fall anhand eines spezfischen Timers, den 
dieser im Tutorial benutzte µC besitzt).

Für dich ist das Tutorial ein Überblick, was die Timer so können und wie 
man sei konfiguriert. Aber deine Bibel, die einzig für dich relevante 
Dokumentation, ist das Datenblatt zu deinem Prozessor.
#3091595
Lesenswert?
• ▲
▼
Mach da mal
1
void loop () {
2

3
  while(changed == 0)
4
    ;
5
  changed = 0;
6

7
  long t = millis();
8
  while(changed == 0)
9
    ;
10
  t = millis() - t;
11

12
  Serial.println(t);
13
  changed = 0;
14
}

draus.
je nach Baudrate braucht auch der println seine Zeit. Wenn du da einen 
Timer-Interrupt verpasst, dann misst du die Zeit zwischen 2 Interrupts.
Gast #3091607
Lesenswert?
• ▲
▼
Electronics'nStuff schrieb:
> Electronics'nStuff schrieb:
>> Naja, dann hast du offensichtlich die falsche Taktquelle.
>
> EDIT: Ich tippe mal auf interne Taktquelle, 8MHz.

Hab mal die Fuses gecheckt: FF DE 05 -> Das heißt Ext. Crystal Osc.
Der Arduino läuft mit 16Mhz. Das heißt daran kann es schon mal nicht 
liegen.

Karl Heinz Buchegger schrieb:
> Mach da mal
> void loop () {
>
>   while(changed == 0)
>     ;
>   changed = 0;
>
>   long t = millis();
>   while(changed == 0)
>     ;
>   t = millis() - t;
>
>   Serial.println(t);
>   changed = 0;
> }
>
> draus.
> je nach Baudrate braucht auch der println seine Zeit. Wenn du da einen
> Timer-Interrupt verpasst, dann misst du die Zeit zwischen 2 Interrupts.

Das geht leider auch nicht. Der Arduino gibt immer noch 32 aus.
Gast #3092895
Lesenswert?
• ▲
▼
Hab jetzt nochmal ein bisschen herumprobiert. Ich dachte schon evtl. ist 
mein Arduino kaputt. Aber mit der Library "TimerOne" funktionierts 
perfekt. Der folgende Code sollte ca. alle 4 Sekunden die LED auf dem 
Arduino ein-/ausschalten (1 / (16.000.000Hz/1024/65536) = ca. 4,2s). 
Warum funktioniert der folgende Code nicht (die LED blink gar nicht)?
1
#define SET_BIT(x,y) x|=(1<<y)
2

3
void setup () {
4
  pinMode(13, OUTPUT);
5

6
  // prescaler: 1024
7
  SET_BIT(TCCR1B, CS12);
8
  SET_BIT(TCCR1B, CS11);
9
  SET_BIT(TCCR1B, CS10);
10
  
11
  // overflow interrupt enable
12
  SET_BIT(TIMSK1, TOIE1);
13
  
14
  // enable global interrupts
15
  sei();
16
}
17

18
ISR (TIMER1_OVF_vect) {
19
  digitalWrite(13, digitalRead(13)^1);
20
}
21

22
void loop () {
23
  // nothing
24
}

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.