Hi Leuts, ich habe hier irgendwie einen Rechenfehler, vielleicht kann mir jemand helfen: Ich habe einen Mega128 mit 16 MHz Quarz. Nun möchte ich Timer2 so konfigurieren, dass im Abstand von 1 ms ein Interrupt (ich habe mal den Compare genommen) ausgelöst wird. Zum Test lasse ich mal eine LED blinken. Prinzipiell funktioniert der Code, aber das mit der 1 ms haut nicht hin. Derzeit blinkt die LED vielleicht alle 500 ms (geschätzt). Ich rechne folgendermaßen: Bei 16 MHz stelle ich einen Prescaler von 128 ein, womit ich bei 125 kHz bin. Das entspricht einer Periodendauer von 8 µs. Wenn ich dann bis 125 zähle bin ich bei genau 1 ms. Wo liegt mein Rechenfehler ? int main() { DDRG = 0xff; // fuer die LED // CTC-Mode einstellen TCCR2 =0; TCCR2 |= (1<<WGM21) | (0<<WGM20); // Prescaler einstellen 128 TCCR2 |= (1<<CS00) | (1<<CS02); // CTC-Vergleichswert OCR2 = 125; // Compare-Interrupt aktivieren TIMSK |= (1<<OCIE2); liveled = 0; sei(); while (1) { // LiveLED steuern if (liveled > 0) { liveled = 0; PORTG ^= (1<<PG4); } } return 1; } ISR(TIMER2_COMP_vect) { liveled++; }
Hi
>Bei 16 MHz stelle ich einen Prescaler von 128 ein,
Hat der Timer nicht.
TCCR2 |= (1<<CS00) | (1<<CS02); <- Fehler
Abgesehen, das es CS20/CS22 heissen muss, stellt das beim Timer2 einen
Vorteiler von 1024 ein.
MfG Spess
Stimmt. Aber wenn ich über 64 gehe und bis 250 zähle passiert gar nix mehr. int main() { DDRG = 0xff; // 16 bit Counter // TCNT2 = 65536-125; /* aktuellen Zaehlerstand setzen */ // Einstellungen definieren // TCCR2 = 0; // Takt = CPU Takt / 128 // TCCR2 |= (1<<CS00) | (1<<CS02); // Normalmode // TCCR2 |= (0<<WGM00) | (1<<WGM01) | (0<<COM01) | (0<<COM00); // Enable Overflowinterrupt // TIMSK |= (1<<TOIE2); // TIMSK |= (1<<OCIE0A); // CTC-Mode einstellen TCCR2 =0; TCCR2 |= (1<<WGM21) | (0<<WGM20); // Prescaler einstellen 64 TCCR2 |= (1<<CS20) | (1<<CS21) | (0<<CS22); // CTC-Vergleichswert OCR2 = 250; // Compare-Interrupt aktivieren TIMSK |= (1<<OCIE2); // Hilfszaehler loeschen liveled = 0; sei(); while (1) { // LiveLED steuern if (liveled > 1000) { liveled = 0; PORTG ^= (1<<PG4); } } return 1; }
Hi Wenn mich meine rudimentären C-Kenntnisse nicht täuschen, sollte 'liveled' volatile sein. MfG Spess
sorry, habe ich vergessen einzublenden. Das ist sie, daran kann es ja auch nicht liegen, denn mit anderen Timereinstellungen blinkt sie ja auch. Aber eben nicht in der richtigen Zeit.
ok, aber wenn ich das mache: if (liveled > 10) { liveled = 0; PORTG ^= (1<<PG4); } dann sehe ich ihn wieder blinken, also muß doch irgendwas an meiner Rechnung nicht stimmen!!!
Hi Poste doch einfach mal ein komplettes Programm und nicht nur Fragmente. Noch ein Hinweis: 'OCR2 = 250;' ist nicht richtig. In der Formel ist noch ein '-1' enthalten. Also 249. MfG Spess
volatile uint8_t liveled=0; int main() { DDRG = 0xff; // CTC-Mode einstellen TCCR2 =0; TCCR2 |= (1<<WGM21) | (0<<WGM20); // Prescaler einstellen 64 TCCR2 |= (1<<CS20) | (1<<CS21) | (0<<CS22); // CTC-Vergleichswert OCR2 = 250; // Compare-Interrupt aktivieren TIMSK |= (1<<OCIE2); // Hilfszaehler loeschen liveled = 0; sei(); while (1) { // LiveLED steuern if (liveled > 10) { liveled = 0; PORTG ^= (1<<PG4); } } return 1; } ISR(TIMER2_COMP_vect) { liveled++; } Bitte, aber ich denke wie gesagt an einen Denkfehler bei mir :-)
liveled wirkt dann als Softwarezähler. Angenommen dein Timer stimmt jetzt mit 1ms, dann toggelst du alle 11 ms. Das ist fast 100 Hz. Das ist schon schwer zu sehen. Je weiter du liveled zählen lässt, desto langsamer und besser sichtbar blinkt die LED.
Stefan B. schrieb: > Das ist > schon schwer zu sehen. Wenn es gut sichtbar ist, dann läuft der µC nicht mit 16 MHz. [[AVR Fuses]] prüfen.
Hi Wenn 'volatile uint8_t liveled=0;' schon immer drin war kann (in deinem 1.Programm) 'if (liveled > 1000)' nicht funktionieren. 'liveled' kann maximal 255 sein. MfG Spess
spess53 schrieb:
> Wenn 'volatile uint8_t liveled=0;' schon immer drin war ...
Das ist einer der tieferen Gründe warum man hier immer vollständigen
Code posten soll.
Oh shit, bin ich doof. Da hast Du natürlich recht, aber leider hilft es nix. Der aktuelle Stand ist so, dass die Led ca. alle 1.5 s blinkt. Bei folgendem Code: volatile uint16_t liveled=0; int main() { DDRG = 0xff; // CTC-Mode einstellen TCCR2 =0; TCCR2 |= (1<<WGM21) | (0<<WGM20); // Prescaler einstellen 64 TCCR2 |= (1<<CS20) | (1<<CS21) | (0<<CS22); // CTC-Vergleichswert OCR2 = 250; // Compare-Interrupt aktivieren TIMSK |= (1<<OCIE2); // Hilfszaehler loeschen liveled = 0; sei(); while (1) { // LiveLED steuern if (liveled > 100) { liveled = 0; PORTG ^= (1<<PG4); } } return 1; } ///////////////////////////////////////////////////////////////// // // ///////////////////////////////////////////////////////////////// ISR(TIMER2_COMP_vect) { liveled++; }
Ok, das war´s :-) lol, stand auf internem RC statt auf externem Quarz. 1000Dank für die Sonntags-Nachhilfe :-) Greets
Hi >Ok, das war´s :-) lol, stand auf internem RC statt auf externem Quarz. >1000Dank für die Sonntags-Nachhilfe :-) Der Hinweis kam schon von Stefan. 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.