Hallo, ich hab ein etwas seltsames Verhalten: Beim ersten Mal nach dem Reset vom AVR wird der CCA vom Timer1 zu früh ausgelöst, danach scheint es immer korrekt zu laufen. Es dürfte wohl in der Initialisierung etwas faul sein... nur komme ich nicht drauf, hat wer einen Tipp für mich? Hier der Code vom Starten des Timers: void timer_init(void) { timer_reset(); TCCR1B = (TCCR1B & ~T1_PRESCALE_MASK) | T1_PRESCALE; } void TIM_reset(void) { TIMSK1 &= ~_BV(OCIE1A); TIMSK1 &= ~_BV(OCIE1B); OCR1A = 0; OCR1B = 0; TCNT1 = 0; } Interrupt aktivieren an CCA: uint8_t timer_attach_CCA(uint16_t count, void(*callback)(void)) { uint16_t value = count; if(callback_CCA) { return T1CCA_RESERVED; } value = value + TIM_Get_Value1(); OCR1A = value; callback_CCA= callback; TIMSK1 |= _BV(OCIE1A); return T1_OK; } ISR(TIMER1_COMPA_vect) { TIMSK1 &= ~_BV(OCIE1A); if (callback_CCA) { callback_CCA(); } callback_CCA=0; } In der Applikation wird dann timer_attach_CCA aufgerufen, wie gesagt beim ersten Mal wird die Funktion(callback) fast sofort ausgeführt ca. 20 Timerticks später, bei den Nachfolgenden exakt zu dem Eingstellten Zeitpunkt. (Habs mit Oszi und AVR Debugging versucht einzugrenzen nur komme ich nicht auf das Problem) Danke!
schon ausprobiert nach TIMSK1 |= _BV(OCIE1A); mal TCNT1 = 0x0; in timer_attach_CCA zu setzen?
Hmm nein aber das möchte ich ja nicht, weil es kann auch sein das am CCB (selbiger Code wie CCA) ein Event hängt und das würde dann verfälscht, verlängert, ... werden. Ist dies leicht nötig?
avr-gast schrieb: > Beim ersten Mal nach dem Reset vom AVR wird der CCA vom Timer1 zu früh > ausgelöst, danach scheint es immer korrekt zu laufen. Passiert das im wahren Leben oder in der Simulation?
avr-gast schrieb: > leider im in der Realität ... :-( Und im Simulator auch? Dann würden sich ja ein Ansatzpunkt ergeben.
Du startest den Timer, während OCR1A 0 ist, damit dürfte es sofort einen Compare-Event geben und das entsprechende Interrupt-Flag gesetzt werden. Ergo wird dann auch sofort nach erlauben der Interrupts dieser ausgelöst werden.
Welchen Ansatzpunkt siehst du da? Also es passiert ohne AVR JTAG und mit AVR JTAG im Debugg Modus - Simuliert hab ich es nicht.
@Stefan: Danke für den Hinweis, leider ist es das auch nicht, ich hab z.B. void TIM_reset(void) { TIMSK1 &= ~_BV(OCIE1A); TIMSK1 &= ~_BV(OCIE1B); OCR1A = 0; OCR1B = 0; TCNT1 = 1; } gesettzt bei meiner Takrate sollte erst in 1 sek. ein Überlauf auftreten, trotzdem gehts es nicht. Hier geht es um ein Zeitfenster von ca. 15ms. Noch einen Nachtrag: Ich stoppe den Timer immer zwischen durch mit void timer_stop(void) { TCCR1B = (TCCR1B & ~TIM_PRESCALE_MASK) | TIM_CLK_STOP; } (wegen den Power Modi) und starte diesen dann wieder mit timer_init(); d.h. eigentlich sind es immer die selben Ausgangsbedingungen trotzdem gibts nach dem Reset diese "komische" Verhalten. also ungefähr so: void cca_function() { timer_stop(); ...Ich mache etwas... } void app(void) { ... if(Bedingung) { timer_init(); timer_attach_CCA(15ms, cca_function); } ... } Fällt noch jemanden etwas ein, bin mir sicher das ist eine Kleinigkeit die ich Übersehe... Danke!
Hab im Datenblatt zwar was gefunden, nur leider hilft das auch nichts: ### Since writing TCNTn in any mode of operation will block all compare matches for one timer clock cycle, there are risks involved when changing TCNTn when using any of the Output Compare channels, independent of whether the Timer/Counter is running or not ### Hmm schön langsam verzweifle ich ... ;(
Generell sollte man erstmal den MC zu nennen. Es gibt viele AVR-Typen und die Timer sind unterschiedlich. avr-gast schrieb: > Noch einen Nachtrag: > Ich stoppe den Timer immer zwischen durch mit > void timer_stop(void) > { > TCCR1B = (TCCR1B & ~TIM_PRESCALE_MASK) | TIM_CLK_STOP; > } > > (wegen den Power Modi) Stop spart keinen Strom. Manche AVRs können aber den Takt von einiger Peripherie abschalten. Wenn es darauf ankommt, dann löscht man erstmal das Pending-Flag, bevor man einen Interrupt freigibt. Es kann ja schon durch ne frühere Bedingung gesetzt worden sein. Bei AVRs mit PLL-fähigem Timer zwischen Löschen und Freigeben noch 3 Zyklen warten! AVR-Fallgrube Nr.1: Pending-Flags setzen, um sie zu Löschen !!! Peter
Hallo Peter, danke für dein Feedback @Stop: Doch weil Timer 1 nur im IDLE Modus läuft und ich aber auf PWR_SAVE gehe. @Controller: Puh stimmt hab ich ganz vergessen, sorry! ATmega1284P @Flag löschen: Hab ich auch schon probiert klappt leider auch nicht, danke für dne Hinweis ich bin hinein getappt aber leider bringt es umgekehrt auch nichts.... Ich mach jetzt mal ein komplettes cleanes Projekt und teste das Modul einzeln, das Projekt ist doch schon ziemlich groß und event. Funkt da etwas dazwischen ... (anders kann ich es mir nicht mehr vorstellen) Ich melde mich dann wieder, danke!
avr-gast schrieb: > @Flag löschen: > Hab ich auch schon probiert klappt leider auch nicht, Man muß die Reihenfolge genau einhalten: timer_init: - cli - Timermoderegister einstellen - Timerwerteregister laden - Flagregister setzen (um zu löschen) - Interruptquellen enablen - sei Peter
Hallo, also es war leider wirklich ein Modul welches blöderweise rein gespielt hat. Trotzdem herzlichen Dank an Peter für die nette Unterstützung!
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.