Forum: Mikrocontroller und Digitale Elektronik ms-Timer atmega8


von stfn (Gast)


Lesenswert?

Hi,
ich hab grad ein Verständnisproblem beim Interrupt-Timing mit dem 
Atmega8. Ich hätte gern jede Millisekunde einen Interrupt, allerdings 
lande ich mit meinem Code bei ca 2ms und hab überhaupt keine Ahnung 
warum. Hier mal mein Code:

// timer setup
//Timer Prescaler auf /8
TCCR2 |= (1 << CS01);
//Timer2_Compare Interrupt aktivieren
TIMSK |= (1 << OCIE2);
// compare wert auf 125 setzen um eine interruptfrequenz von 1ms zu 
bekommen // ((1000000/8)/1000) = 125
OCR2 = 125 - 1;


// activate interrupts and callback
sei();

ISR(TIMER2_COMP_vect) {
// fängt nach 49.71027 Tagen wieder bei 0 an :P
systemTime++;
// other stuff...
}

Wie man gut sieht hab ich den code aus dem Timer Tutorial hier. Ich weiß 
nicht, warum ich die doppelte Zeit bekomme. Hier gehe ich ja davon aus, 
dass die CPU mit 1Mhz läuft... stimmt die Annahme nicht und er läuft nur 
mit 500kHz? Das würde den Wert erklären... Ich hab wie blöd das 
Datenblatt druchwühlt, aber nichts entsprechendes gefunden.

Für eine Idee wär ich sehr dankbar :)

cya

von Alex S. (thor368)


Lesenswert?

Tach stfn!

Deine Rechnungen stimmen so erstmal. Ich habe es jetzt noch nicht 
ausprobiert aber vom Prinzip her stimmen alle Werte.

Nur mal so eine Frage: Wie misst du eigentlich die Frequenz des Timers? 
Togglest du ein portbit? Dann entspricht die Frequenz nur der halben 
Taktrate, weil du ja mit jedem toggle nur ein Hälfte eines Wellenzuges 
machst.

Ansonsten fällt mir dazu jetzt auch nichts ein.

Thor

von spess53 (Gast)


Lesenswert?

Hi

Du must den CTC-Mode einstellen. Bei dir läuft der Timer nach dem 
Interrupt einfach weiter und nach 2ms kommt der nächste Interrupt. Bei 
CTC wird der Timer automatisch wieder auf Null gestellt.

MfG Spess

von Martin V. (oldmax)


Lesenswert?

Hi
Zuerst mal eine Frage, wie hoch taktest du ?
 Dieser Codeschnipsel macht exakt eine ms bei 16 MHz
1
;----------Timer 1 Parametrierung ---------------------
2
3
InitTimer1:
4
  ldi  Temp_Reg, high( 2000 - 1 )  (16 MHz / Vorteiler / 2000 = 1ms )
5
  out  OCR1AH, Temp_Reg        
6
  ldi  Temp_Reg, low( 2000 - 1 )        
7
  out  OCR1AL, Temp_Reg    
8
 ; CTC Modus einschalten                                   
9
; Vorteiler auf 8        
10
  ldi  Temp_Reg, ( 1 << WGM12 ) | ( 1 << CS11 )          
11
  out  TCCR1B, Temp_Reg         
12
  ldi  Temp_Reg, 1 << OCIE1A  ;OCIE1A: Interrupt bei Compare        
13
  out  TIMSK, Temp_Reg
14
15
Ret
Auch dieses ist hier aus dem Tutorial. Wenn du die CPU mit 1 MHz 
taktest, dann vergiss den Vorteiler durch 8 (also, nicht CS11 sondern 
CS10 setzen)und setze da wo 2000 steht 1000 rein.
Zum Verständnis: Timer-Compare heißt Interrupt beim Erreichen eines 
voreingestellten Wertes.
Wenn eine CPU mit 1 MHz taktet und blos 1000 zählt, dann einen Interrupt 
auslöst und wieder bei 0 anfängt, heißt das 1 000000 / 1 000 = 1 000 
Interrupts / Sek entspricht 1 ms.
Gruß oldmax

von Martin V. (oldmax)


Lesenswert?

Hi
Sorry, hab mich im Timer vertan, der Timer 2 ist ja nur ein 8 bit Timer. 
Dan stimmt die Rechnung, nur der CTC Modus fehlt.
Gruß oldmax

von stfn (Gast)


Lesenswert?

wow tatsache,

TCCR2 = (1<<WGM21);

hat gefehlt, warum auch immer ich das vergessen hab^^. Dann zählt der 
Timer natürlich bis das byte voll ist.
Vielen Dank!

Was wäre denn, wenn ich statt WGM21 WGM20 nehmen würde?

Ich arbeite grad an meinem ersten µC-Projekt... daher die Folgefrage: 
warum ist die Ausgangstaktrate für den internen Timer 1Mhz? Das ist doch 
nicht die CPU-Taktrate oder? Das Datenblatt ist für mich teilweise noch 
sehr kryptisch und auf der Suche nach dem Fehler hab ich das wie blöd 
durchwühlt aber keine eindeutige Antwort auf die Frage gefunden:
mit wieviel hz läuft die CPU und mit wieviel der Timer vor einem 
Prescale? Hat so 'n Timer n eigenen Takt? Offensichtlich, denn 1Mhz ist 
etwas wenig für die CPU, wenn bis zu 16Mhz drin sind laut Datenblatt... 
?

Oh und noch eine Anfängerfrage: was passiert denn, wenn ich in der 
interrupt-routine so viel code drin habe, dass die Durchlaufzeit größer 
als 1ms ist? (Bzw. nah an 1ms wär ja auch schon fatal, weil nichts mehr 
für die Hauptschleife übrig bleibt...). Gibt's ne Methode Fehlverhalten 
diesem Sachverhalt zuzuordnen?

Danke und Grüße

von lightninglord (Gast)


Lesenswert?

Die "CPU" läuft mit dem Takt den du vorgibst:

1. Du hast ein Quarz angeschlossen, und auf Quarz gefused -> CPU wird 
mit Quarzfrequenz getaktet

2. Du hast ein Quarz angeschlossen, auf Quarz und internen Teiler 
gefused -> CPU wird mit XTAL/8 getaktet

3. Du hast auf internen RC gefused, dann wir je nach AVR und Fuses mit 
1-8 Mhz getaktet

...

Es gibt viele Möglichkeiten einen AVR zu takten, zB auch mit RC-Glied 
oder einfach nur einem externen Takt. Für den Anfang ist es besser bei 
Quarzen zu bleiben oder beim internen RC, weil wenn du dich bei den 
Takt-Fuses vertust, kannnst du dich sehr schnell aus deinem AVR 
aussperren.

von spess53 (Gast)


Lesenswert?

Hi

>...mit wieviel hz läuft die CPU und mit wieviel der Timer vor einem
>Prescale?

Der Timer hat vor dem Prescaler den gleichen Takt wie die CPU. Gilt auch 
für die übrigen IO-Module.

>Offensichtlich, denn 1Mhz ist etwas wenig für die CPU,

Wieso? Du kannst einen AVR auch mit 32kHz betrieben. Ist für manche 
Anwendunge durchaus ausreichend. Die Controller werden oft unterschätzt.

>Oh und noch eine Anfängerfrage: was passiert denn, wenn ich in der
>interrupt-routine so viel code drin habe,... Gibt's ne Methode Fehlverhalten
>diesem Sachverhalt zuzuordnen?

Interrupts gehen verloren, deine Hauptschleife wird nicht mehr, oder nur 
schleppend abgearbeitet....

Aber selbst bei 1MHz sind das etwa 600...700 Assemblerbefehle, die in 
einer ms abgearbeitet werden können.

MfG Spess

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.