Forum: Mikrocontroller und Digitale Elektronik ICP und OVF Interrupt gleichzeitig, wie behandeln?


von Nadine (Gast)


Lesenswert?

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?

von STK500-Besitzer (Gast)


Lesenswert?

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.

von Nadine (Gast)


Lesenswert?

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.

von Axel S. (a-za-z0-9)


Lesenswert?

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
volatile union {
2
  uint32_t val;  /* ein 32-bit Wort */
3
  uint16_t w[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

von Nadine (Gast)


Lesenswert?

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?

von Axel S. (a-za-z0-9)


Lesenswert?

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

von Nadine (Gast)


Lesenswert?

Hallo Axel,

ok, das ist so wie du schreibst richtig und kann ich nachvollziehen.

Danke.

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