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
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
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
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
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
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
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.