Mir fällt da ein externer Interrupt ein, in dessen ISR wird bei jeder Periode eine Variable hochgezählt.
Wenn du dann die Variable im Sekundentakt ausliest, und diese dann wieder auf Null setzt hast du im Prinzip schon was du willst. http://arduino.cc/de/Reference/AttachInterrupt
Alternativ kann man auch die Periodendauer messen und daraus die Frequenz ausrechnen.
Dann wird die Funktion trigger bei jeder steigenden Flanke des Rechtecksignal angesprungen und die Variable counter inkrementiert.
Jetzt musst du nur noch im Sekundentakt die Variable auslesen und wieder auf 0 setzen.
Also hat der Interrupt immer Priorität vor allen anderen Sachen?
Aber was passiert denn, wenn jetzt genau während der Bearbeitung einer Funktion ein Signal rein kommt?
Wird die Funktion dann abgebrochen? Oder wird dann die Funktion an der Stelle pausiert, die Zählervariable inkrementiert und die Funktion an der Stelle wieder weitergeführt?
rudirabbit:
Du kannst die Interupts kurz abschalten, wenn du die Variable bearbeitest.
void loop()
{
noInterrupts();
// critical, time-sensitive code here
interrupts();
// other code here
}
Das würde ich nicht empfehlen, da es sein kann dass genau dann ein Signal kommt wenn die Interrupts aus sind.
Tritt ein Interrupt auf, so wird das Programm angehalten und die Interruptfunktion aufgerufen. Wenn diese fertig ist, wird an der stelle fortgesetzt, wo unterbrochen wurde. Da ein Interrupt auftreten kann, während "counter" gerade benutzt wird, ist es sinnvoll, die Variable als volatile festzulegen, dann kann im Normalfall nichts schiefgehen
MGOS:
"counter" gerade benutzt wird, ist es sinnvoll, die Variable als volatile festzulegen, dann kann im Normalfall nichts schiefgehen
Ahh.. genau da war was. THX !
Ich habe die Atmels vorher immer mit Pascal "vergewaltigt", in C (++) habe ich immer noch so ein gefährliches Halbwissen - tappe deshalb öfters in sowas.
Also sollte man generell alle Variablen die außerhalb einer ISR verändert werden als volatile definieren ?
Variable, die in der ISR verändert werden und in loop gelesen werden, sollten auch als "volatile" deklariert werden.
Das teilt dem Compiler mit, keine falsche Optimierung einzubauen: Immer wenn die Variable gebraucht wird, muss sie auch aus dem Speicher gelesen werden.
Und Variable, die größer als 1 byte sind, müssen unter geschlossenem Interrupt umkopiert werden. Da sonst im Extremfall die ISR dazwichenkommen kann und in loop ein inkonsistenter Zustand erkannt wird.
Das ist zwar recht selten, aber daher um so schlimmer.
Stell dir vor, die ISR erhöht den counter von 255 (0x00ff) auf 256 (0x0100).
Wenn counter in loop gleichzeitig verwendet wird, kann der Wert auch 0x01ff oder 0x0000 sein, je nachdem welches byte zuerst gelesen wird.
Nach noInterrupt() geht übrigens kein Interrupt verloren, sondern wird nur verzögert, falls das nur kurz geschieht ( zum Umkopieren der ISR Variablen )
Das wird beim Fragesteller hier auch von Interesse sein.
Meinem Verständnis nach gibt es nun zwei Möglickeiten:
1 . Zwei Byte Counter "volatile" deklariert - die Logig (hi byte lo byte) des inkrementierens in der ISR.
Innerhalb einer ISR sollte man sich kurz fassen ! - dies wäre auch ein einfacher kurzer Code.
In der Main Loop hätte man dann zugriff auf beide Byte Variablen ohne die Interrupt's zu stoppen.
Int Counter auch als "volatile" deklariert innerhalb der ISR reicht dann ein einfaches counter++
In der Main Loop müssen dann für die Zeit des umkopierens die Interrupt's gestoppt werden.
Nach noInterrupt() geht übrigens kein Interrupt verloren, sondern wird nur verzögert, falls das nur kurz geschieht ( zum Umkopieren der ISR Variablen )
Sind das deine Erfahrungen, oder steht das irgendwo im Datasheet des Atmel ?
rudirabbit:
1 . Zwei Byte Counter "volatile" deklariert - die Logig (hi byte lo byte) des inkrementierens in der ISR.
Innerhalb einer ISR sollte man sich kurz fassen ! - dies wäre auch ein einfacher kurzer Code.
In der Main Loop hätte man dann zugriff auf beide Byte Variablen ohne die Interrupt's zu stoppen.
Bringt Dir nichts. Wenn Du den Interrupt nicht sperrst, kann er Dir nach dem Lesen des ersten Bytes und vor dem Lesen des zweiten Bytes den Inhalt ändern. Dann bist Du genau so weit wie mit einer int Variable.