Prozessor: Atmega8 betrifft Tiemr1 16-bit
Morgen,
ich habe ein ICP Interrupt, in dem ich Sachen abfrage, unter anderem
einen Timerstand. Bei dem Timer können Overflows auftreten.
Wenn jetzt ein OVF gleichzeitig auftritt, muss ich das ja mit
berücksichtigen.
Wie man das grundlegend macht, ist mir klar, man frägt das Interrupt
Register, ob das Interrupt Flag für den OVF gesetzt ist ab und prüft, ob
der Zählerstand noch klein ist (also das oberste bit 7 nicht gesetzt
ist)
Die Frage stellt sich für mich, welchen Zählerstand frage ich ab bzw.
angenommen ich berechne in der ICP Routine eine Division, die ca. 100us
beansprucht. Danach muss ich wissen, ob ein Overflow stattgefunden hat.
Muss ich dann das Timer/Counter Register TCNT1 zur Abfrage des obersten
bits nehmen und frisch auslesen, oder genügt es, das vor der Division
(100us "alte) ICR1 Register des ICP zu nehmen.
Also kann praktisch während der Abarbeitung des ICP Interrupts ein
Overflow auftreten? Im Prinzip doch schon, da der Timer ja weiter läuft,
oder nicht?
Demnach müsste ich doch direkt vor der Stelle, an denen die Overflows in
die Berechnung mit einfließen, das Interrupt Flag und den aktuellen
Zählerstand TCNT1 prüfen, also so:
1
// hier befinden wir uns im Input Capture Interrupt Vektor
2
ISR(TIMER1_CAPT_vect){
3
if((TIFR&(1<<TOV1))&&(!(TCNT1&0x8000))){
4
OverflowZaehler+=65536;
5
}
6
}
So wäre das doch fehlerbehaftet oder?
1
// hier befinden wir uns im Input Capture Interrupt Vektor
2
ISR(TIMER1_CAPT_vect){
3
ICPStand=ICP;
4
// hier käme dann die Division, die ca. 100us dauert
5
6
if((TIFR&(1<<TOV1))&&(!(ICPStand&0x8000))){
7
OverflowZaehler+=65536;
8
}
9
}
Ich hoffe, jemand versteht, worauf ich hinaus will.
Es geht darum, dass wären der Abarbeitung des Interrupts bis zu dem
Teil, wo die Overflows dann mit in einer Rechnung berücksichtigt werden,
der Timer umspringen kann und ich das nicht mitbekomme… und hierzu muss
ich doch dann nochmal gemäß dem Code oben den aktuellen TCNT1 prüfen und
nicht den direkt am Anfang der ISR Rounte eingelesenen ICP Wert oder?
Nadine schrieb:> Die Frage stellt sich für mich, welchen Zählerstand frage ich ab bzw.> angenommen ich berechne in der ICP Routine eine Division, die ca. 100us> beansprucht
Muss die Division unbedingt in der ISR geschehen?
Für ISR gilt ja "in der Kürze liegt die Würze".
Nadine schrieb:> Prozessor: Atmega8 betrifft Tiemr1 16-bit>> Morgen,>> ich habe ein ICP Interrupt, in dem ich Sachen abfrage, unter anderem> einen Timerstand. Bei dem Timer können Overflows auftreten.> Wenn jetzt ein OVF gleichzeitig auftritt, muss ich das ja mit> berücksichtigen.> Wie man das grundlegend macht, ist mir klar, man frägt das Interrupt> Register, ob das Interrupt Flag für den OVF gesetzt ist ab und prüft, ob> der Zählerstand noch klein ist (also das oberste bit 7 nicht gesetzt> ist)>> Die Frage stellt sich für mich, welchen Zählerstand frage ich ab bzw.> angenommen ich berechne in der ICP Routine eine Division, die ca. 100us> beansprucht. Danach muss ich wissen, ob ein Overflow stattgefunden hat.> Muss ich dann das Timer/Counter Register TCNT1 zur Abfrage des obersten> bits nehmen und frisch auslesen, oder genügt es, das vor der Division> (100us "alte) ICR1 Register des ICP zu nehmen.> Also kann praktisch während der Abarbeitung des ICP Interrupts ein> Overflow auftreten? Im Prinzip doch schon, da der Timer ja weiter läuft,> oder nicht?
Ja.
Allerdings braucht dein OVerflowzähler nicht um 65536, sondern nur um 1
erhöht werden.
STK500-Besitzer schrieb:> Ja.
Worauf war dieses "Ja" nun bezogen?
Ich addiere pro Overflow +65536 zu einer uin32_t Variable, um mir später
die Multiplikation mit der Anzahl Overflows zu sparen. So rechne ich
einfach nur Additionen.
Und ja, die Division sollte in der ISR geschehen. Ich weiß, dass ISRs
gering wie möglich gehalten werden müssen, aber das Programm läuft
vorwiegend aufgrund extrem zeitkritischer Dinge Interrupt-gesteuert.
Nadine schrieb:> Ich addiere pro Overflow +65536 zu einer uin32_t Variable, um mir später> die Multiplikation mit der Anzahl Overflows zu sparen. So rechne ich> einfach nur Additionen.
OMG. Wie teuer ist denn deiner Meinung nach eine "Multiplikation" mit
65536?
Zumal man das ja eigentlich eher so macht:
1
volatileunion{
2
uint32_tval;/* ein 32-bit Wort */
3
uint16_tw[2];/* oder 2 16-bit Worte */
4
}counter;
5
6
icp_isr()
7
{
8
counter.w[0]=ICRx;/* das lo-Word */
9
}
10
11
ovr_isr()
12
{
13
counter.w[1]++;/* das hi-Word */
14
}
15
16
main()
17
{
18
...
19
printf("...%lu...",counter.val);
20
...
21
}
> Und ja, die Division sollte in der ISR geschehen. Ich weiß, dass ISRs> gering wie möglich gehalten werden müssen, aber das Programm läuft> vorwiegend aufgrund extrem zeitkritischer Dinge Interrupt-gesteuert.
Den Test, ob gleichzeitig ein Timerüberlauf passiert ist, muß man doch
sowieso am Anfang der ISR machen. Auf jeden Fall bevor man mit dem
kompletten (also incl. Überläufe) Zählerwert rechnen kann.
Wenn der Überlauf erst während der Abarbeitung der Capture-ISR passiert,
ist das egal. Sobald die Capture-ISR endet, wird der Controller die
Überlauf-ISR ausführen. Die einzige Bedingung ist, daß die Capture-ISR
nicht so lang dauern darf, daß der Zähler inzwischen ein weiteres Mal
überläuft. Bei 100µs und einem 16-Bit Zähler besteht die Gefahr aber
normalerweise nicht.
Ach nochwas: es ist weitgehend zweckfrei, am Anfang einer ISR zu prüfen
ob das zugehörige Interrupt-Flag gesetzt ist. Wenn es das nämlich nicht
wäre, würde die ISR nicht ausgeführt.
XL
Axel Schwenke schrieb:> enn der Überlauf erst während der Abarbeitung der Capture-ISR passiert,> ist das egal. Sobald die Capture-ISR endet, wird der Controller die> Überlauf-ISR ausführen. Die einzige Bedingung ist, daß die Capture-ISR> nicht so lang dauern darf, daß der Zähler inzwischen ein weiteres Mal> überläuft. Bei 100µs und einem 16-Bit Zähler besteht die Gefahr aber> normalerweise nicht.
Das ist mir klar.
Aber angenommen ich prüfe am Anfang der Capture-ISR, es liegt kein
Überlauf vor.
Ich rechne meine Division, ca. 100us.
Danach benötige ich die Anzahl der Overflows.
In der Zeit zwischen der Division und der Benötigung des Overflows
könnte ja rein theoretisch auch noch ein Overflow geschehen, den ich
dann nicht mitbekommen habe, weil ich zunächst am Anfang der ISR geprüft
habe, ob einer anliegt.
Daher meine Frage, ist es nicht zwingend notwendig, diese Prüfung direkt
VOR der Verwendung des Overflow-Wertes einzubauen?
Nadine schrieb:> Axel Schwenke schrieb:>> enn der Überlauf erst während der Abarbeitung der Capture-ISR passiert,>> ist das egal. Sobald die Capture-ISR endet, wird der Controller die>> Überlauf-ISR ausführen.> Aber angenommen ich prüfe am Anfang der Capture-ISR, es liegt kein> Überlauf vor.> Ich rechne meine Division, ca. 100us.> Danach benötige ich die Anzahl der Overflows.
Die Anzahl der Overflows seit wann?
Normalerweise verwendet man die Capture-Unit doch, um den Zeitpunkt
eines Ereignisses zu bestimmen. Und der Zeitpunkt ergibt sich aus dem
Zählerwert im ICR Register und eventuell höherwertigen Bits, die
Zählerüberläufe mitzählen. Wenn das Ereignis also eintritt, will man in
der Capture-ISR doch normalerweise den Zählerstand zu genau dem
Capture-Zeitpunkt wissen. Warum sollte einen der Wert der höherwertigen
Zeitbits ca. 100µs später interessieren?
> In der Zeit zwischen der Division und der Benötigung des Overflows> könnte ja rein theoretisch auch noch ein Overflow geschehen, den ich> dann nicht mitbekommen habe, weil ich zunächst am Anfang der ISR geprüft> habe, ob einer anliegt.
Ja. Und?
Wenn du auf die Uhr schaust, als der Zug abfährt und es ist 12:59 Uhr
und 45 Sekunden. Dann ziehst du dein Handy und rufst deine Mutter an um
ihr die Abfahrtszeit durchzugeben. Macht es dann was aus, daß
unterdessen die Minuten einen Überlauf hatten und die Stunden eins
hochgezählt wurden?
XL