Hallo, ich komme einfach nicht weiter. Gerade Probiere ich mit dem ATmega128 eine Zeitmessung. Über PC5 starte ich mit einer steigenden Flanke ein Ereignis (t0) in einer externen Schaltung. Zeitversetzt bekomme ich eine über PD2 (INT2) eine steigende Flanke zurück, welche meine 'Stopzeit' (t) sein soll. Allerdings möchte ich nicht ewig auf das Signal an PD2 warten, sondern ein limit von 35ms setzen. Versucht habe ich es so: #define CNT_WAIT 0 #define CNT_MEASURED 1 #define CNT_OVERFLOW 2 volatile uint8_t cnt_state = CNT_WAIT; volatile uint16_t cnt_value = 0x0; ISR(TIMER1_COMPA_vect) { if(cnt_state==CNT_WAIT) cnt_state = CNT_OVERFLOW; } ISR(INT2_vect) { cnt_value = TCNT1; EIMSK &= ~(1<<INT2); // INT2 disable if(cnt_state==CNT_WAIT) cnt_state = CNT_MEASURED; } int main(void) { ... EICRA |= (1<<ISC21)|(1<<ISC20); // INT2 rising edge ... // Timer1 initalisieren TCCR1A = 0; // CTC Mode, TCCR1B = (1<<WGM12)|(1<<CS11); // clk/8 542.535 ns OCR1A = 64511; // CompareA 35ms TIMSK |= (1<<OCIE1A); // Output CompareA Enable EIMSK |= (1<<INT2); // INT2 enable cnt_state = CNT_WAIT; TCNT1 = 0; // Counter1 reset PORTC |= (1<<PC5); while(cnt_state==CNT_WAIT); // Auf 10%-Triggersignal oder CompareA warten ... } Der INT2_vect wird definitiv ausgelöst. Allerdings steht dann cnt_state bereits auf CNT_OVERFLOW. Also wird TIMER1_COMPA_vect bereits vorher ausgelöst obwohl INT2_vect innerhalb der 35ms erfolgt. Wo ist mein Gedankenfehler?
Hal Smith schrieb: > TIMSK |= (1<<OCIE1A); // Output CompareA Enable Hal Smith schrieb: > cnt_state = CNT_WAIT; Hal Smith schrieb: > if(cnt_state==CNT_WAIT) > cnt_state = CNT_OVERFLOW; = Reihenfolge der Abarbeitung noch vor while() Hal Smith schrieb: > Allerdings möchte ich nicht ewig auf das Signal an PD2 > warten, sondern ein limit von 35ms setzen. Müsste diese Zeitmessung nicht erst in ISR_INT2 gestartet werden?
Ralf schrieb: > Hal Smith schrieb: >> TIMSK |= (1<<OCIE1A); // Output CompareA Enable > > Hal Smith schrieb: >> cnt_state = CNT_WAIT; > > Hal Smith schrieb: >> if(cnt_state==CNT_WAIT) >> cnt_state = CNT_OVERFLOW; > = Reihenfolge der Abarbeitung noch vor while() > Verstehe ich jetzt nicht. Ich nehme an, dass der TIMER1_COMPA_vect erst ausgelöst wird wenn TCNT1==OCR1A erreicht? Ralf schrieb: > Hal Smith schrieb: >> Allerdings möchte ich nicht ewig auf das Signal an PD2 >> warten, sondern ein limit von 35ms setzen. > Müsste diese Zeitmessung nicht erst in ISR_INT2 gestartet werden? Nein. Die Messung soll mit PORTC |= (1<<PC5) starten und mit einer steigenden Flanke an PD2 enden.
Hal Smith schrieb: > Verstehe ich jetzt nicht. Ich nehme an, dass der TIMER1_COMPA_vect erst > ausgelöst wird wenn TCNT1==OCR1A erreicht? Na klar, aber der fängt doch sofort an zu zählen. Und ~35ms nach dem Einschalten des µC ist der Stand erreicht. Ja okay, ein paar while-Schleifen macht er noch. Hal Smith schrieb: > Die Messung soll mit PORTC = (1<<PC5) starten und mit einer > steigenden Flanke an PD2 enden. ... außer das ganze dauert länger als 35ms (wenn ich's richtig verstanden habe).
Hal Smith schrieb: > Wo ist mein Gedankenfehler? Vermutlich in diesen drei Zeilen:
1 | TCCR1B = (1<<WGM12)|(1<<CS11); // clk/8 542.535 ns |
2 | OCR1A = 64511; // CompareA 35ms |
3 | TIMSK |= (1<<OCIE1A); // Output CompareA Enable |
Der Timer wird gestartet während OCR1A 0 ist, also gibt es sofort ein Compare-Event (vermutlich, bin mir nicht 100%ig sicher). Der entsprechende Interrupt ist zwar noch nicht eingeschaltet, aber das verhindert ja nicht, dass das entsprechende Flag gesetzt wird. Wenn die Interrupts dann eingeschaltet werden, lößt der Compare-Interrupt sofort aus (wegen des gesetzten Flags).
Stefan Ernst schrieb: [/c]Der Timer wird gestartet während OCR1A 0 ist, also gibt es sofort > ein Compare-Event (vermutlich, bin mir nicht 100%ig sicher). Sollte doch eigentlich nichts ausmachen. Mit TCNT1 = 0 wird auch cnt_state auf CNT_WAIT gesetzt. Falls davor ein TIMER1_COMPA_vect aufgerufen sein sollte ist das damit unerheblich!? cnt_state = CNT_WAIT; TCNT1 = 0; IO_PORT |= (1<<IR_ENABLE); while(cnt_state==CNT_WAIT);
Hal Smith schrieb: > Sollte doch eigentlich nichts ausmachen. Mit TCNT1 = 0 wird auch > cnt_state auf CNT_WAIT gesetzt. Falls davor ein TIMER1_COMPA_vect > aufgerufen sein sollte ist das damit unerheblich!? Beginnt die Zeitmessung über Interrupt nach dem Start des µC innerhalb von 35ms? Ich hoffe, ich habe keinen Denkfehler. So wie ich das sehe, gibts alle 35ms einen TIMER1_COMPA-Interrupt.
Hal Smith schrieb: > Die Messung soll mit PORTC |= (1<<PC5) starten und mit einer > steigenden Flanke an PD2 enden. ok ... vielleicht ist es so verständlicher: Die Messung soll mit dem Schalten von PC5 von Low auf High starten (PORTC |= (1<<PC5);) und bei einer steigenden Flanke an PD2 (INT2) enden. Die Messung soll aber nach 35ms beendet werden falls keine steigende Flanke an PD2 anliegt. Ich weiß, dass das setzen des Counters auf 0 und das Schalten von PC5 auf HIGH-Pegel nicht synchron erfolgen kann. Aber wenn dies nacheinander geschieht, sollte der Zeitversatz konstant sein und kann daher in der Auswertung berücksichtigt werden.
Ah, jetzt hab' ich verstanden wie das alles gemeint war. Was sagt denn der Simulator? Wann wird der Timer1_IR ausgeführt?
Hal Smith schrieb: > Wie kann ich so etwas Zeitkritisches mit dem Simulator testen? Einfach mal starten. Und sehen, wo der Timer zulangt.
Danke für den Tip mit dem Interrupt Flag. Allerdings liegt es nicht am Timer sondern am INTF2 im EIFR Register. Also vor dem das INT2-Bit in EIMSK auf 1 gesetz wird das INTF2-Bit im EIFR Register auf 0 setzen. Danke! Wieder was gelernt ;-)
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.