Forum: Mikrocontroller und Digitale Elektronik AVR32 - AT32UC3A1512 "Zuviel" in der Interrupt Service Routine (Ringpuffer, Ringspeicher)


von Martin S. (Gast)


Lesenswert?

Hallo Leute,
ich bin noch Anfänger, wenn es ums µC-programmieren geht. Deshalb würde 
ich mich sehr über einige Tipps freuen!;)

Mein Ziel ist es gerade ein analoges Signal abzutasten und diese Werte 
nun in ein Ringpuffer zuspeichern, um das Signale zu analysieren und 
eventuell den zeitl. Abstand der auftretenden Maxima zu 
berechnen/auszugeben. Abtasten möchte ich mit 1kHz. (Zwischen dem 
Samplen und dem "Einlesen" in den Ringspeicher wäre noch ein digitales 
Tiefpassfilter erforderlich.)

Ich hab es mir nun so gedacht, dass ich das Abtasten mit einem 
entsprechenden TIMER-Interrupt realisieren kann. In dieser ISR wird dann 
jeweils ein Wert mittels SPI von einem externen Analog-Digital-Wandler 
geholt. Nun müssen die Werte ja nacheinander in den Ringpuffer 
geschrieben werden.
Mein "Gedanken-Problem" liegt nun daran, dass ich schon öfters gelesen 
habe, dass man nicht so viel in einer ISR reinschreiben soll. Sie dient 
u.a. halt nur, wie in meinem Bsp., zum Abholen des ADC-Wertes jede 
Millisekunde.
Ich meine, Werte in ein Array zu schreiben und dabei den Schreibpointer 
zu inkrementieren stellt nicht das große Problem dar. Nur müsste dies 
doch auch mit in der Interrupt Service Routine stehen, oder? Eigentlich 
dachte ich, dass diese Aufgaben dann eher wieder in der Hauptschleife 
des Programms gehören.
Aber der Ringpuffer muss ja nur jede Millisekunde neu gefüttert werden 
und wenn das Ganze in der Hauptschleife steht, dann wird das Schreiben 
ja öfters als 1kHz ausgeführt, da der µC mit einem Takt von 48MHz läuft. 
Folglich wären dann ja mehrere gleiche Werte nacheinander in diesem 
Ringspeicher vorhanden (bis dann der neue Wert aus der ISR vom ADC 
bereitgestellt wird)..!?

Wie kann man dieses Problemchen lösen und die Aufgabe am klügsten 
bewerkstelligen? Wie macht man sowas "normalerweise"?

Ich hoffe, Ihr könnt mir helfen und hilfreiche Tipps geben!;)

Viele Grüße..Martin

von Thomas D. (t0mmy)


Lesenswert?

Naja ich denke das Inkrementieren und Kopieren von ein paar Bytes kannst 
du ohne Probleme in deiner ISR erledigen. Überleg mal, wie lange das bei 
48MHz dauern könnte.

Die Lösung für deine eigentliche Frage ist eine einfache Bool-Variable, 
die von der ISR auf true gesetzt und von deiner Hauptschleife wieder 
zurückgesetzt wird, sobald du deine Daten gespeichert hast. Somit kannst 
du überprüfen ob du die aktuelle Daten schon in den Ringpuffer geschoben 
hast oder nicht.

von Martin S. (Gast)


Lesenswert?

Oki..danke;)
Das mit der BOOL Variable ist natürlich wieder zu "einfach" gewesen, um 
alleine darauf zu kommen! gg

Und wie "kommuniziert" die Main-Schleife am besten mit einer ISR? Mit 
globalen Variablen oder mit Pointern, die auf die jeweiligen Adressen 
zeigen? Oder ists ansich das "Gleiche"? Wo liegen dabei Vor/Nachteile, 
Unterschiede?

Ist es richtig, dass, wenn ich globale Variablen verwende, ich diese 
auch als VOLATILE deklarieren muss, damit sie auch immer direkt in den 
Speicher geschrieben und nicht "optimierend" in ein Register gesichert 
werden?!

Grüße..Martin

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Sowas macht man am besten direkt in der ISR. Bei 1 KHz ist das kein 
Problem, da lohnt es sich auch nicht DMA zu bemühen.

> Ist es richtig, dass, wenn ich globale Variablen verwende, ich diese
> auch als VOLATILE deklarieren muss, damit sie auch immer direkt in den
> Speicher geschrieben und nicht "optimierend" in ein Register gesichert
> werden?!

Ja. Außerdem musst du darauf achten, dass dein Hauptprogramm jederzeit 
von der ISR unterbrochen werden kann. Du musst also ggf. Interrupts 
deaktivieren wenn du etwas mit der Variable machst was im Fall einer 
Unterbrechung zu einem Fehler führen kann.

von Martin S. (Gast)


Lesenswert?

> Ja. Außerdem musst du darauf achten, dass dein Hauptprogramm jederzeit
> von der ISR unterbrochen werden kann. Du musst also ggf. Interrupts
> deaktivieren wenn du etwas mit der Variable machst was im Fall einer
> Unterbrechung zu einem Fehler führen kann.

Oki..danke für den Tipp, aber was passiert, wenn in der zeitl. Phase, wo 
die Interrups deaktiviert sind, der TIMER gerade den Wert erreicht, der 
einen Interrupt auslöst!? Ja klar..er wird nicht ausgeführt - Aber die 
Abtastung des Signals muss doch sichergestellt werden!?

Gruß..Martin

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.