Hi zusammen, ich habe eine Frage zum Thema Interrupts: Ich benutze einen SAMD21J18A und ATMEL START/ATMEL Studio (AFS4) Umgebung, um ihn zu programmieren. Jetzt habe ich folgendes Problem: Ich habe einen SPI Bus, an dem verschiedene Sensoren dran hängen und einen Eingangs-Pin, der bei fallender Flanke eine Interruptfunktion auslösen soll, die mir einen bestimmten Sensor, über die SPI-Verbindung, auslesen soll. Wenn jetzt aber der Fall auftritt, dass gerade ein Sensor, der an besagtem SPI Bus hängt, ausgelesen wird und dabei gleichzeitig die Interruptfunktion aufgerufen wird, um einen anderen Sensor in diesem Bussystem auszulesen, führt das zu Kuddelmuddel. Die Interruptfunktion soll eine höhere Priorität haben, als das auslesen des anderen Sensors. Sprich: Wenn gerade ein Sensor ausgelesen wird und die Interruptfunktion ausgelöst wird, soll das auslesen des anderen Sensors abgebrochen werden, die Interruptfunktion ausgeführt und dann der Sensor erneut ausgelesen werden. Im Programmablauf müssten also nach dem Interrupt ein paar (bereits ausgeführte) Schritte erneut ausgeführt werden. Daraus ergibt sich meine Frage: Gibt es in AFS4 einen Ansatz zu sagen: "Wenn zwischen diesem (Startpunkt) und diesem Punk (Endpunkt) im Code ein Interrupt getriggert wird, dann springe nach ausführen des Interrupts zum Startpunkt(!) zurück." Danke schonmal für konstruktive Vorschläge! Hanna
Ich glaube das musst du "zu Fuß" programmieren. Macht die externe Hardware das denn einfach so mit?
Hanna schrieb: > Die Interruptfunktion soll eine höhere Priorität haben, als das auslesen > des anderen Sensors. Das halte ich für eine verfehlte Architektur. Mach die einzelnen Auslesefunktionen schnell / kurz, aber nicht unterbrechbar. Sensoren, die eine lange Zeit brauchen, haben oft eine Funktion, mit der sie zwischenzeitlich (während ihrer eigentlichen Messphase) den Bus freigeben können. Sowas sollte man nutzen. Ansonsten müsstest du Nägel mit Köpfen machen und uns sagen, welche Art Sensor das ist. Dann kann man dich besser beraten.
Stefan ⛄ F. schrieb: > Macht die externe > Hardware das denn einfach so mit? Da bin ich mir noch nicht sicher :D Jörg W. schrieb: > Sensoren, die eine lange Zeit brauchen, haben oft eine > Funktion, mit der sie zwischenzeitlich (während ihrer eigentlichen > Messphase) den Bus freigeben können. Das könnte eine Alternative sein. Da muss ich dann wohl nochmal Datenblätter durchstöbern.
Hanna schrieb: >> Macht die externe >> Hardware das denn einfach so mit? > Da bin ich mir noch nicht sicher :D Dann prüfe das erst mal, denn was du da vor hast ist schon seltsam.
Hallo! Wären zwei SPI-Busse die Lösung? Einer per Interrupt für diesen einen Sensor und der andere Bus für die restlichen Sensoren per Bit-Banging?
Hanna schrieb: > Wenn jetzt aber der Fall auftritt, dass gerade ein Sensor, der an > besagtem SPI Bus hängt, ausgelesen wird und dabei gleichzeitig die > Interruptfunktion aufgerufen wird, um einen anderen Sensor in diesem > Bussystem auszulesen, führt das zu Kuddelmuddel. In der Tat. > Die Interruptfunktion soll eine höhere Priorität haben, als das auslesen > des anderen Sensors. Sprich: Wenn gerade ein Sensor ausgelesen wird und > die Interruptfunktion ausgelöst wird, soll das auslesen des anderen > Sensors abgebrochen werden, die Interruptfunktion ausgeführt und dann > der Sensor erneut ausgelesen werden. Im Programmablauf müssten also nach > dem Interrupt ein paar (bereits ausgeführte) Schritte erneut ausgeführt > werden. Das geht schief. > Daraus ergibt sich meine Frage: Gibt es in AFS4 einen Ansatz zu sagen: > "Wenn zwischen diesem (Startpunkt) und diesem Punk (Endpunkt) im Code > ein Interrupt getriggert wird, dann springe nach ausführen des > Interrupts zum Startpunkt(!) zurück." Kuddelmuddel! Du brauchst ein anderes Konzept! Egal auf welchem Prozessor. Siehe die Antwort von Jörg. Die Frage ist, wie dringend muss der Sensor WIRKLICH ausgelesen werden? a) Nicht super dringend, die aktuelle Sensorabfrage kann noch beendet werden. Dann reicht es, im Interrupt ein Flag zu setzen und das Auslesen des Sensor in der passenden State machine im Hauptprogramm zu machen, gleich nach der Beendigung des aktuellen Sensorzugriffs. b) SUPER DRINGEND! Wenn das WIRKLICH der Fall ist (über wie viele Millisekunden reden wir her?) muss man den Sensor ggf. an einen extra SPI-Bus hängen und im Interrupt auslesen. Dann kommt sich auch nix in die Quere. c) SUPER DRINGEND und der Sensor kann NICHT an einen an einen extra SPI-Bus gehängt werden. Dann liest man den Sensor im Interrupt direkt aus und setzt ein "Hallo-ich hab mal dazwischengefunkt"-Flag. Dieses wird von den normalen Funktion vor dem normalen Sensorzugriff gelöscht und am Ende nochmal geprüft. Ist es dann gesetzt, hat der Interrupt dazwischen gefunkt und der Zugriff muss wiederholt werden. Dafür braucht es keinerlei exotische Programmfunktionalität.
SPI per Interrupt macht meist keinen großen Sinn. (Ausnahme: man hat seeehr langsame SPI-Clients, die man nur mit vergleichsweise niedrigerer Datenrate takten kann.) Aber da muss uns Hanna erstmal schreiben, welche Sensoren sie da überhaupt am Bus hat.
Route_66 H. schrieb: > Wären zwei SPI-Busse die Lösung? Auch das kommt auf die externe Hardware an. Du kannst nicht bei jedem Chip einfach die Kommunikation mitten im Takt pausieren.
Hanna schrieb: > einen Eingangs-Pin, der bei fallender Flanke eine Interruptfunktion > auslösen soll Woher kommt das Signal das da an diesem "Eingangs-Pin" anliegt? Interrupts nimmt man, wenn etwas, das nicht lange dauert, schnell bearbeitet werden muss. So, wie wenn du gerade einen Kuchen backst. Dann darf dich vielleicht der Postbote ganz kurz unterbrechen. Das Öffnen und Auspacken des Pakets bzw. das Bearbeiten der Post sowie das Bezahlen der Rechnungen verschiebst du aber auf später. Und wenn grade die Eier ins Mehl geschlagen hast und du siehst durchs Fenster, dass draußen die Hecke geschnitten werden muss, dann merkst du dir diese Aufgabe und verschiebst das auf später. Und backst davor erst mal den Kuchen fertig. Hanna schrieb: > Wenn jetzt aber der Fall auftritt, dass gerade ein Sensor, der an > besagtem SPI Bus hängt, ausgelesen wird und dabei gleichzeitig die > Interruptfunktion aufgerufen wird, um einen anderen Sensor in diesem > Bussystem auszulesen, führt das zu Kuddelmuddel. Du gehst also einfach her und merkst dir im jeweiligen Interrupt, dass du den entsprechenden Sensor auslesen musst. Und dann bearbeitest du diese Aufgaben später hübsch nacheinander.
:
Bearbeitet durch Moderator
Stefan ⛄ F. schrieb: > Route_66 H. schrieb: >> Wären zwei SPI-Busse die Lösung? > > Auch das kommt auf die externe Hardware an. Du kannst nicht bei jedem > Chip einfach die Kommunikation mitten im Takt pausieren. Dann ist es kein Jim Beam, ähhh, SPI. Aber OK, es gibt einige ICs, z.B. AD-Wandler, welche mit dem SPI-Takt die Wandlung durchführen oder zumindest starten. Aber alles in allem ist es keine sonderlich gute Idee, das SPI im Interrupt einfach so brachial zu übernehmen.
Falk B. schrieb: > Aber OK, es gibt einige ICs, z.B. > AD-Wandler, welche mit dem SPI-Takt die Wandlung durchführen oder > zumindest starten. Genau das hatte ich dabei im Sinn.
Hi Zusammen, um nochmal etwas Klarheit zu schaffen: Die beiden Sensoren um die es geht sind 1. Ein Accelerometer, das hin und wieder ausgelesen werden soll (ca alle 200ms- 1 mal pro Sekunde). Ich benötige momentan 1.6ms für die gesamte Kommunikation mit dem Accelerometer. (Hier ist vermutlich noch Verbesserungspotenzial) und 2. ein ADC, der (siehe Falk Bs Antwort) SUPER DRINGEND ausgelesen werden muss. (ca. einmal pro ms und dann muss der Interrupt innerhalb weniger us (genauere Werte habe ich hier noch nicht) aufgerufen werden). Falk B. schrieb: > c) SUPER DRINGEND und der Sensor kann NICHT an einen an einen extra > SPI-Bus gehängt werden. Dann liest man den Sensor im Interrupt direkt > aus und setzt ein "Hallo-ich hab mal dazwischengefunkt"-Flag. Dieses > wird von den normalen Funktion vor dem normalen Sensorzugriff gelöscht > und am Ende nochmal geprüft. Ist es dann gesetzt, hat der Interrupt > dazwischen gefunkt und der Zugriff muss wiederholt werden. Dafür braucht > es keinerlei exotische Programmfunktionalität. Bei dem Vorschlag mit der "Hallo-ich hab mal dazwischengefunkt"-Flag wäre dann vorher vermutlich wieder die Frage ob die Hardware das so einfach mitmacht... Route_66 H. schrieb: > Wären zwei SPI-Busse die Lösung? Zwei SPI-Busse sind keine Alternative
Hanna schrieb: > Bei dem Vorschlag mit der "Hallo-ich hab mal dazwischengefunkt"-Flag > wäre dann vorher vermutlich wieder die Frage ob die Hardware das so > einfach mitmacht... klingt aber erstmal einfacher als meine erste Idee :D
Hanna schrieb: > Hi Zusammen, > > um nochmal etwas Klarheit zu schaffen: > Die beiden Sensoren um die es geht sind > 1. Ein Accelerometer, das hin und wieder ausgelesen werden soll (ca alle > 200ms- 1 mal pro Sekunde). Also absolut unkritisch. > Ich benötige momentan 1.6ms für die gesamte > Kommunikation mit dem Accelerometer. (Hier ist vermutlich noch > Verbesserungspotenzial) Klingt so, denn in 1,6ms kann man selbst bei nur 1MHz SPI-Takt satte 1600 Bit bzw. 200 Bytes übertragen. Und ich glaube nicht, daß dein SPI nur mit 1MHz läuft. > und > 2. ein ADC, der (siehe Falk Bs Antwort) SUPER DRINGEND ausgelesen werden > muss. (ca. einmal pro ms und dann muss der Interrupt innerhalb weniger > us (genauere Werte habe ich hier noch nicht) aufgerufen werden). AHA! Also ein periodischer Interrupt mit schon recht hoher Frequenz. Aber daran erkennt man, daß es mit 1,6ms Auslesezeit für das Accelerometer so oder so nicht geht, denn diese Zugriffe müssen in die Lücken des ADCs passen. Und damit ist auch das Konzept klar. Der Interrupt macht einen sofortigen, direkten ADC-Zugriff. Direkt danach, noch im Interrupt wird geprüft, ob das Zeitfenster für das Accelerometer erreicht ist. Wenn ja, wird es im Anschluß ausgelesen. Damit gibt es keinerlei Überschneidungen beim SPI-Zugriff, alle Zugriffe finden an einer Stelle nur im Interrupt statt.
Falk B. schrieb: > Also ein periodischer Interrupt mit schon recht hoher Frequenz. Leider nicht ganz (Hätte ich vielleicht anders formulieren sollen). Es gibt auch Phasen hin und wieder, da wird der Interrupt nur sehr selten bis gar nicht ausgelöst. Trotzdem soll dann das Accelerometer ausgelesen werden.
Hanna schrieb: > Leider nicht ganz (Hätte ich vielleicht anders formulieren sollen). > Es gibt auch Phasen hin und wieder, da wird der Interrupt nur sehr > selten bis gar nicht ausgelöst. Trotzdem soll dann das Accelerometer > ausgelesen werden. Hmm, schon wieder ein sehr fragwürdiges Konzept. Wenn das denn WIRKLICH so ist und so sein soll, hast du das Problem, daß du auch in den Pausen das Accelerometer nicht in der Hauptschleife auslesen kannst, denn der Interrupt kann ja jeden Moment zuschlagen. Oder gibt es wenigstens eine Art Vorhersagemöglichkeit, daß man weiß, OK, wir haben JETZT ca. ???ms Ruhe vom ADC, jetzt können wir das Accelerometer auslesen. Wenn du das nicht hast, wird es ZIEMLICH schwierig, das sauber zu lösen.
Hanna schrieb: > und 2. ein ADC, der (siehe Falk Bs Antwort) SUPER DRINGEND ausgelesen > werden muss. (ca. einmal pro ms und dann muss der Interrupt innerhalb > weniger us (genauere Werte habe ich hier noch nicht) aufgerufen werden). Kann man den ADC nicht sauber per Timer die Wandlung triggern lassen und dann ggf. sogar noch per DMA die Ergebnisse transferieren? (Ich weiß, DMA und SPI vertragen sich nicht immer, je nachdem, wie das Select erfolgt.) Ansonsten sollte man vielleicht das aus einem Timer-Interrupt anwerfen, der regelmäßig zuerst den ADC abfragt und dann ggf. noch das Accelerometer.
Falk B. schrieb: > Oder gibt es wenigstens eine Art Vorhersagemöglichkeit, daß man weiß, > OK, wir haben JETZT ca. ???ms Ruhe vom ADC, jetzt können wir das > Accelerometer auslesen Da will mir nichts einfallen...
Ich würde eher versuchen, die Kontrolle selbst zu übernehmen: Lassen sich die Sensorwerte auch abfragen(*), oder ist man darauf angewiesen, dass der Sensor sich meldet? (*) Die Sensoren sollen in einem ausreichend feinen Zeitraster abgefragt werden.
Jörg W. schrieb: > Kann man den ADC nicht sauber per Timer die Wandlung triggern lassen und > dann ggf. sogar noch per DMA die Ergebnisse transferieren? (Ich weiß, > DMA und SPI vertragen sich nicht immer, je nachdem, wie das Select > erfolgt.) Wenn ich das richtig verstehe, funktioniert das leider nicht, da ich den Wert vom ADC zu exakt (zumindest sehr genau zu) dem Zeitpunkt brauche, an dem der Interrupt ausgelöst wird und in der Interruptfunktion passieren noch andere Dinge, die unmittelbar mit dem ADC-Auslesen zusammenhängen. (sprich: Reset von Integratoren). Ralf G. schrieb: > Lassen sich die Sensorwerte auch abfragen(*), oder ist man darauf > angewiesen, dass der Sensor sich meldet? Das verstehe ich nicht, im Moment melde ich mich beim Sensor: "Schick mir doch bitte die Werte" woraufhin der Sensor mir die Werte schickt ;)
Beitrag #6441682 wurde vom Autor gelöscht.
Hanna schrieb: > dass der Sensor sich meldet? Er meint damit den Interrupt Pin, der dich dazu bewegt beim Sensor anzufragen.
Ackerbau schrieb: >> dass der Sensor sich meldet? > > Er meint damit den Interrupt Pin, der dich dazu bewegt beim Sensor > anzufragen. Achso... also man könnte auch den ADC auslesen und wenn der einen bestimmten Wert ausgibt, dann könnte ich quasi die Interrupt Funktion manuell ausführen, aber dann müsste ich ja wirklich fast durchgehend die Werte vom ADC abfragen und ich weiß nicht, was mir das bringen würde...
Ahh, ich glaube, jetzt hab' ich's (nach mehrmaligem Durchlesen)... Der Interrupt ist die Anforderung, dass jetzt bestimmte|alle Sensoren abgefragt werden sollen. Wie groß darf der Fehler sein? - (Extrem '1') 'gegen null': dann sollte der Abruf möglichst aller Sensoren innerhalb des kürzestmöglichen Interruptintervalles erfolgen können - (Extrem '2') 'naja, geht so': Sensoren reihum auslesen und speichern, bei Interrupt Daten aus 'Datenbank' übermitteln (auch wenn die dann vielleicht nicht millisekundenaktuell sind) Lese gerade: Hanna schrieb: > aber dann müsste ich ja wirklich fast durchgehend die > Werte vom ADC abfragen und ich weiß nicht, was mir das bringen würde... Du legst fest, was passiert! Sonst quatschen alle durcheinander... Nochmal zu: 'Ahh, ich glaube, jetzt hab' ich's'... ... wahrscheinlich doch nicht? Der Sensor löst einen Interrupt aus, wenn er was zu melden hat?
:
Bearbeitet durch User
Hanna schrieb: > Falk B. schrieb: >> Oder gibt es wenigstens eine Art Vorhersagemöglichkeit, daß man weiß, >> OK, wir haben JETZT ca. ???ms Ruhe vom ADC, jetzt können wir das >> Accelerometer auslesen > > Da will mir nichts einfallen... D.h. die Interrupts kommen sporadisch und trotzdem mit hoher Frequenz?
Falk B. schrieb: > D.h. die Interrupts kommen sporadisch und trotzdem mit hoher Frequenz? Könnte man so sagen... Also es kommt aufs Eingangssignal drauf an, das ich messen möchte. Wesentlich ist: Bei großem Eingangssignal kommt der Interrupt häufiger (bis zu 1x pro 1ms) Bei kleinem Eingangssignal seltener (nur 1x pro Minute o.ä.) Das Eingangssignal ist nicht vorhersehbar, sprich folgt keinem bestimmten Muster (Sinusfrequenz o.ä.)
Hanna schrieb: > Könnte man so sagen... > Also es kommt aufs Eingangssignal drauf an, das ich messen möchte. > Wesentlich ist: > Bei großem Eingangssignal kommt der Interrupt häufiger (bis zu 1x pro > 1ms) > Bei kleinem Eingangssignal seltener (nur 1x pro Minute o.ä.) > Das Eingangssignal ist nicht vorhersehbar, sprich folgt keinem > bestimmten Muster (Sinusfrequenz o.ä.) Was ist das denn für ein komischer ADC? Klingt nach einem selbstgestrickten ADC mit Zählverfahren. Was muss denn im Interrupt aus dem ADC ausgelesen werden?
Ralf G. schrieb: > Ahh, ich glaube, jetzt hab' ich's (nach mehrmaligem Durchlesen)... > Der Interrupt ist die Anforderung, dass jetzt bestimmte|alle Sensoren > abgefragt werden sollen. > > Wie groß darf der Fehler sein? > - (Extrem '1') 'gegen null': dann sollte der Abruf möglichst aller > Sensoren innerhalb des kürzestmöglichen Interruptintervalles erfolgen > können > - (Extrem '2') 'naja, geht so': Sensoren reihum auslesen und speichern, > bei Interrupt Daten aus 'Datenbank' übermitteln (auch wenn die dann > vielleicht nicht millisekundenaktuell sind) > > Lese gerade: > Hanna schrieb: >> aber dann müsste ich ja wirklich fast durchgehend die >> Werte vom ADC abfragen und ich weiß nicht, was mir das bringen würde... > > Du legst fest, was passiert! Sonst quatschen alle durcheinander... > > Nochmal zu: > 'Ahh, ich glaube, jetzt hab' ich's'... > ... wahrscheinlich doch nicht? Der Sensor löst einen Interrupt aus, wenn > er was zu melden hat? Nicht ganz... Der eine Sensor (ADC) soll ausgelesen werden, wenn ein bestimmter I/O Pin seinen Zustand von high auf low wechselt (das passiert bis zu 1000x pro Sekunde, muss aber nicht). Ein anderer Sensor (der Accelerator) soll in regelmäßigen Zeitabständen (z.B. alle 200ms) ausgelesen werden. Beide Sensoren hängen im gleichen SPI-Bussystem. Beim ADC ist das Timing sehr(!) wichtig. Beim Accelerator eher weniger.
Falk B. schrieb: > Hanna schrieb: >> Könnte man so sagen... >> Also es kommt aufs Eingangssignal drauf an, das ich messen möchte. >> Wesentlich ist: >> Bei großem Eingangssignal kommt der Interrupt häufiger (bis zu 1x pro >> 1ms) >> Bei kleinem Eingangssignal seltener (nur 1x pro Minute o.ä.) >> Das Eingangssignal ist nicht vorhersehbar, sprich folgt keinem >> bestimmten Muster (Sinusfrequenz o.ä.) > > Was ist das denn für ein komischer ADC? Klingt nach einem > selbstgestrickten ADC mit Zählverfahren. Was muss denn im Interrupt aus > dem ADC ausgelesen werden? Damit meine ich nicht das Eingangssignal vom ADC, sondern ein anderes. Ich möchte im Grunde einen Strom messen. Der ADC soll natürlich nur die Eingangsspannung messen, bei großen Strömen halt häufiger.
Hanna schrieb: >> Was ist das denn für ein komischer ADC? Klingt nach einem >> selbstgestrickten ADC mit Zählverfahren. Was muss denn im Interrupt aus >> dem ADC ausgelesen werden? > > Damit meine ich nicht das Eingangssignal vom ADC, sondern ein anderes. > Ich möchte im Grunde einen Strom messen. Der ADC soll natürlich nur die > Eingangsspannung messen, bei großen Strömen halt häufiger. Und dafür macht du so ein Theater? Lies den ADC REGELMÄßIG aus, dann weißt du, wann Pausen für andere Dinge sind.
Ich würde eine Globle Variable setzt z.b. stoped = false Die Interruptroutine wird so gecodet Sub Interrupt If stoped = true then exit sub if stoped = false then stoped = true call gemuetlich_auslesen end if exit sub sub gemuetlich_auslesen lese_senor_1_aus lese_senor_2_aus lese_senor_3_aus stoped = false end sub Problem gelöst. Ach ja ich code unter B4a da würde der Code funktioniern
Ohje, jetzt kommen die BASCOM-Philosophen.
Falk B. schrieb: > Ohje, jetzt kommen die BASCOM-Philosophen. Ich code nicht in Bascom. Das ist B4R um genau zu sein. B4R schreibe einen Arudino-IDE fähigen Code. Ruft die IDE auf, compiliert und die Arduino-IDE schiebt ihn auf den Chip. Ich bin einfach nur ein Mensch der Geschweifte Klammern hasst. ;)
Nachtrag : https://www.b4x.com/android/forum/ Der fast gleiche Code (Programm-Engine) (besondere Eigenheiten der Geräte müssen berücksichtigt werden) funktioniert auf Raspberry, Java, Android und für 100 Euro im Jahr auch auf Apple-Zeug. Ergo : Alles was nicht MS + VB ist code ich damit. Und der Editor ist Visual-Basic like. Also wieso 100 Syntax für den selben Mist. und Wieso teures Bascom bezahlen. ??!
Falk B. schrieb: > nd dafür macht du so ein Theater? Lies den ADC REGELMÄßIG aus, dann > weißt du, wann Pausen für andere Dinge sind. Ich dachte das könnte ich mir sparen, denn ich tue viele andere Dinge :D
Hanna schrieb: >> nd dafür macht du so ein Theater? Lies den ADC REGELMÄßIG aus, dann >> weißt du, wann Pausen für andere Dinge sind. > > Ich dachte das könnte ich mir sparen, denn ich tue viele andere Dinge :D Was denn? Nebenbei Instagrammen und Influencen? ;-) Sag doch mal, was das für ein komischer ADC sein soll und was der wie mißt und warum du glaubst, das mit derartig sporadischen, dann aber mikrosekundengenauen SPI-Zugriffen machen zu müssen. Bei den meisten ADCs ist das nicht so, die halten ihre Ergebnisse bis zum Sankt Nimmerleinstag in den Registern, die kann man beliebig langsam auslesen, wenn gleich die nächste Wandlung dann warten muss.
> 1. Ein Accelerometer, das hin und wieder ausgelesen werden soll (ca alle > 200ms- 1 mal pro Sekunde). Ich benötige momentan 1.6ms für die gesamte > Kommunikation mit dem Accelerometer. (Hier ist vermutlich noch > Verbesserungspotenzial) >und > 2. ein ADC, der (siehe Falk Bs Antwort) SUPER DRINGEND ausgelesen werden > muss. (ca. einmal pro ms und dann muss der Interrupt innerhalb weniger > us (genauere Werte habe ich hier noch nicht) aufgerufen werden). Die beiden Forderungen sind mit einem einzelnen SPI-Bus nicht unter einen Hut zu bekommen. a) Wenn der ADC jede Millisekunde eine Abfrage fordert, bleiben keine 1.6ms mehr für den Beschleunigungssensor übrig. b) Wenn das Auslesen des Accelerometer gerade läuft und dann eine Anforderung des ADC ankommt, kann diese nicht sofort bedient werden. Selbst falls die Abfrage des Accelerometers unterbrochen werden könnte, dauert das einige SPI-Takte und du hast dann einen Jitter auf dem ADC-Abfragezeitpunkt.
Ehe man so ein Zippel Zappel an einem SPI Bus macht, schliesst man das Acceldings an ein paar freie Pins an und bitbangt die paar Bytes ein. Dann bleibt die ganze ISR/SPI Hardware frei für diesen ADC.
:
Bearbeitet durch User
Matthias S. schrieb: > Dann bleibt die ganze ISR/SPI Hardware frei für diesen ADC. Naja, ein SAMD21 hat sechs(!) SERCOMs, daran allein kann es eigentlich auch nicht liegen …
:
Bearbeitet durch Moderator
Eventsystem mit DMA Controller ist keine Lösung für dein ADC? Falls der ACC Sensor länger als 1ms zum Auslesen benötigt muss der dann natürlich an einen anderen SPI...
/Bei dem Vorschlag mit der "Hallo-ich hab mal dazwischengefunkt"-Flag wäre dann vorher vermutlich wieder die Frage ob die Hardware das so einfach mitmacht.../ man nimmt da einfach ein Register und setzt dort ein einzelnes Bit, dies ist das das oben genannte "Hallo-ich hab mal dazwischengefunkt"-Flag. Mir ist noch kein µC begegnet der das nicht gekonnt hätte. 00000000 Interrupt xyz hat nicht dazwischengefunkt 00000001 Interrupt abc hat dazwischengefunkt 00000010 Interrupt 123 hat dazwischengefunkt Für mich hört sich das so an als ob du diesen Wert gar nicht alle 1mSek benötigst, warscheinlich ist dieser eh veraltet da ihn der Sensor vielleicht schon vor 5 mSek gemessen hat und du ihn jetzt erst abrufst. ansonsten dein µC hat doch passende ADC's onboard, wieso dann nicht gleich den passenden Sensor nehmen und auf die SPI Krücke verzichten. *12-bit, 350ksps Analog-to-Digital Converter (ADC) with up to 20 channels Differential and single-ended input *1/2x to 16x programmable gain stage *Automatic offset and gain error compensation *Oversampling and decimation in hardware to support 13-, 14-, 15- or 16-bit resolution
>> Bei dem Vorschlag mit der "Hallo-ich hab mal dazwischengefunkt"-Flag >> wäre dann vorher vermutlich wieder die Frage ob die Hardware das so >> einfach mitmacht... > > Mir ist noch kein µC begegnet der das nicht gekonnt hätte. Mit Hardware ist nicht der Prozessor sondern die SPI-Peripherie gemeint.
Hanna schrieb: > Sprich: Wenn gerade ein Sensor ausgelesen wird und > die Interruptfunktion ausgelöst wird, soll das auslesen des anderen > Sensors abgebrochen werden, die Interruptfunktion ausgeführt und dann > der Sensor erneut ausgelesen werden. Das ist Unfug^³. SPI ist nicht reentrant. Entweder alles als Interrupt oder als Main. Die Main-Funktionen können ja einfach in einen Puffer schreiben, den der SPI-Interrupt dann abarbeitet. Wenn es aber unbedingt so sein muß (muß es nie), dann nimmt man einfach einen MC mit mehreren SPI. Z.B. der ATmega2560 kann bis 5 SPI-Master parallel benutzen, die 4 UARTs können auch SPI.
Peter D. schrieb: > dann nimmt man einfach einen MC mit mehreren SPI Hat sie doch, schrieb ich oben: stolze 6 SERCOMs sind zur Verfügung. Inwiefern natürlich ggf. das Hardware-Layout vergurkt ist und an wie viele man davon rankommt, muss sie selbst klären.
Hanna schrieb: > Wenn jetzt aber der Fall auftritt, dass gerade ein Sensor, der an > besagtem SPI Bus hängt, ausgelesen wird und dabei gleichzeitig die > Interruptfunktion aufgerufen wird, um einen anderen Sensor in diesem > Bussystem auszulesen, führt das zu Kuddelmuddel. Auf einem Controller mit einem einzigen Kern gibt es kein "gleichzeitig" ;-) Der Interrupt kann die erste Lesefunktion nur unterbrechen, wenn du es ihm erlaubst. Alles andere ist eine Frage der Softwarearchitektur - und ganz richtig - zwei verschachtelte Leseoperationen auf dem selben Bus gehen schief.
>Es gibt auch Phasen hin und wieder, da wird der Interrupt nur sehr >selten bis gar nicht ausgelöst. Man kann eine CPU nicht mit mit beliebig kurzen aufeinanderfolgenden INT-Anforderungen belasten. Irgentwann packt die es nicht mehr, und jede ISR benötigt eine gewisse Anzahl von Takten (je weniger desto besser). Je öfter/schneller das passieren soll desto höher die INT-Priorität desto weniger die Takte in der ISR (sonst fährt das System sich fest). Betr dem ADC wäre die Frage: Wie genau, bzw wie einfach könnte das Timing (!) gemacht werden; ob nicht vieleicht sogar ein period. Abfrage (1 ms) gehen würde / gemacht werden sollte, was einfacheres Timing wäre. (Es schadend nichts, wenn CPU manchmal einige Werte 'zuviel' liest, die gar nicht benötigt werden, diese Werte später aber wieder da sind wenn sie benötigt werden (im worstcase wären es vermutlich sowiso 1ms)). Und wenn ein Sensor bsp. nur alle 50ms mal abgefragt werden soll heist das nicht, dass die Abfrage selbst 50ms dauern muss. Dies Abfrage passt doch problemlos in ein 1ms 'Protokoll' hinein.
MCUA schrieb: >>Es gibt auch Phasen hin und wieder, da wird der Interrupt nur sehr >>selten bis gar nicht ausgelöst. > Man kann eine CPU nicht mit mit beliebig kurzen aufeinanderfolgenden > INT-Anforderungen belasten. Irgentwann packt die es nicht mehr, und jede > ISR benötigt eine gewisse Anzahl von Takten (je weniger desto besser). > Je öfter/schneller das passieren soll desto höher die INT-Priorität > desto weniger die Takte in der ISR (sonst fährt das System sich fest). Mann O Mann, dümmer kann man wohl kaum antworten! Da spricht der OP von selten bis gar nicht bzw. maximal 1x pro Millisekunde und ein "Experte" faselt was von beliebig kurzen Interruptanforderungen! Setzen, Sechs! Thema verfehlt!
In Größenordnungen um 1ms sind Interruptroutinen meistens sowieso das falsche Mittel. Da geht man mit Hardware ran, die Daten ganz alleine erfasst und in Puffer schreibt. -> Siehe Soundkarten und Grafikkarten (bzw. Chipsätze) im PC Die CPU kann die gepuffertem Daten wesentlich effizienter blockweise abarbeiten.
Stefan ⛄ F. schrieb: > In Größenordnungen um 1ms sind Interruptroutinen meistens sowieso das > falsche Mittel. Da geht man mit Hardware ran, die Daten ganz alleine > erfasst und in Puffer schreibt. Unsinn, wir leben nicht mehr im Jahr 1970, wo Mikrocontroller bestenfalls dreistellige kHz Taktraten hatten. 1ms ist selbst für kleine Mikrocontroller ala AVR, PIC & Co eine kleine Ewigkeit. > -> Siehe Soundkarten und Grafikkarten (bzw. Chipsätze) im PC > > Die CPU kann die gepuffertem Daten wesentlich effizienter blockweise > abarbeiten. OMG! Du vergleichst Melonen mit Erdnüssen!
Falk B. schrieb: > OMG Nu werde mal nicht religiös. Ich will will nicht dein Gott sein, und der andere "da oben" oder so hat andere Sorgen.
>Setzen, Sechs! Thema verfehlt!
von wegen...
du musst dich setzen!
Auch kannst du nicht lesen!
Der TO hat von us-genauer Anforderung geschrieben.
Im Gegensatz zu deinem Gesülze ist an meinem Beitrag Rein Gar Nichts
auszusetzen.
> In Größenordnungen um 1ms sind Interruptroutinen meistens sowieso das > falsche Mittel. Nö, grade nicht. Sind bei 100MHz ganze 100000 Takt-Cyclen (also bestenfalls so viele Befehle), mit denen du arbeiten kannst.
wenn ich die Frage richtig verstanden habe, dann seh ich auch den grösseren Nutzen darin den "unkritischen" Sensor in einer schleife zu lesen, dessen Wert kann damit ruhig einen Schleifendurchlauf altern (eben unkritisch) solange der ADC (was auch immer dran hängt) das nicht tut, der bleibt in einer ISR. Im Grunde braucht es also zwei globale variablen einen für den alternden wert, den anderen für die Abfrage ob die ISR aufgerufen wurde wurde das kostet Taktzyklen leider.. ich glaub 5? in pseudo code in etwa
1 | //global vars |
2 | accsensordata; //kA was rein soll, int array würde ich vermuten |
3 | isrtriggered = false; // 'ne boolean |
4 | ....... |
5 | isr() |
6 | { |
7 | read_adcvalue(); |
8 | isrtriggered = true; |
9 | report_isrdata(); |
10 | ....... |
11 | } |
12 | |
13 | main() //Hauptschleife, im Grunde irgendeine while(1) oder so |
14 | { |
15 | ........ |
16 | loopstart: |
17 | isrtriggered = false; // ab hier ist nichtmehr egal ob der isr ausgelöst wurde |
18 | // hier sollte nur was zwischen was auch den Beschleunigungssensor betrifft. |
19 | preaparation(&sens); |
20 | some_random_stuff(&sens); |
21 | if(isrtriggered) goto loopstart; //bis hier ist alles 'geschützt' |
22 | accsensordata = read_accsensor(&sens); |
23 | report_sensordata(); |
24 | ........ |
25 | } |
Nachteil: das Auslesen des Beschleunigungssensors (das war doch der unkritische, oder?) über irgendetwas anderes als mundgemaltes Assembler vermutlich eine mehrzeilige ungesicherte Lücke lässt in der der Interrupt die ISR auslösen kann. ich glaube nicht, dass der isr zu jedem Taktzyklus ausgelöst werden kann, ich meine immer nur vor oder nach einem assembler Befehl (nie probiert); Also müsste die Abfrage ob der isr auslöste (isrtriggered) so nah wie möglich an das neuschreiben der Speicherzelle (accsensordata) wenn es mehrere speicherzellen sind (array?) eventuell sogar vor jede davon. Assembler verknotet mir aber zu sehr das Gehirn um das auch nur annäherend logisch/inhaltlich korrekt hier hinkritzeln zu können.(da brauch ich cheatsheets und Kaffee und jmd der mir die Hand hält für) Das kann bestimmt jmd anderes besser als ich ;) Das Prinzip bleibt dasselbe. nachdem der immens wichtige Senor durch den interrupt ausgelöst wurde, setzt man ein flag, das man in einer permanent laufenden schleife exakt vor dem neuschreiben der Beschleunigungssensordaten prüft um ggf zum Anfang der Schleife zurückzuspringen. 'okay' geht das in jeder Hochsprache die Sprungmarken akzeptiert (alle mir bekannten) 'richtig gut' geht das mMn nur in Assembler, weil man nur da sicherstellen kann, dass die Abfrage auch EXAKT einen Befehl vor dem Schreiben des Speichers landet und man im Zweifel auch an bessere Position zurückspringen kann. 'perfekt' geht das mMn garnicht, da ich glaube der Interrupt kann keinen 'laufenden' assemblerbefehl abbrechen, Also könnte der interrupt im Zweifel trotzdem exakt ausgelöst werden nachdem gepüft wurde ob der isr aufgerufen worden ist, womit der Speicher in dieser Schleife dennoch mit dem möglicherweise schon veralteten 'neuen Wert' beschrieben würde. Glücklicherweise ist das aber ja der unkritische von beiden ;) Ich mag aber auch die Frage falsch verstanden haben, und der acc-sensor muss ebenfalls unbedingt via interrupt Aufruf seine Daten preisgeben. #schulterzuck In dem Fall würde man den interrupt des 'unkritischen' während der isr des 'dringenden' löschen müssen und erst nach dessen Ausführung wieder zulassen. 'sid
Wie viele Daten müssen vom Accelerometer geholt werden? Kann man die in kleineren Häppchen holen? Lässt der/die/das Accelerometer das zu? Dann wäre folgendes möglich: jede 1ms ADC lesen und im Anschluss ein Häppchen vom Accelerometer
>da ich glaube der Interrupt kann keinen 'laufenden' assemblerbefehl >abbrechen, Ein Interrupt unterbricht i.d.R. keinen ASM-Befehl, braucht er auch gar nicht, da ein ASM-Befehl, norm. sehr kurz ist. (Ausnahme vielleicht umfangreiche Befehle, MUL, MAC, RMAC, Stingbefehle usw, die umfassendere Hardware erfordern. Bei einigen CPUs sind solche Befehle unterbrechbar (ggfs je nach INT-Priorität), bei anderen nicht. Man sollte also je nach Timing-Anforderung (sofern man 'ms' und 'us' unterscheiden kann) drauf achten, zu lang andauernde Befehle ggfs. nicht zu benutzen, auch dürfen u.U. wegen Abhängigkeiten zusammenhängende Befehlsfolgen gar nicht unterbrochen werden.)
>Unsinn, wir leben nicht mehr im Jahr 1970, wo Mikrocontroller >bestenfalls dreistellige kHz Taktraten hatten. Im Jahr 1970 gab es keine Mikrocontroller.
Event System mit DMA sollte das ohne CPU Intervention hinbekommen...
Uwe schrieb: > Event System mit DMA sollte das ohne CPU Intervention hinbekommen... Auf EINEM SPI-Bus? Soso . . .
Beitrag #6443507 wurde von einem Moderator gelöscht.
Hanna schrieb: > Ich benutze einen SAMD21J18A und ATMEL START/ATMEL Studio (AFS4) > Umgebung, um ihn zu programmieren. Das ist hier völlig nebensächlich. Nimm als Toolchain was dir gefällt, es spielt für einen sinnvollen Aufbau einer Firmware keine Rolle. > Jetzt habe ich folgendes Problem: > Ich habe einen SPI Bus, an dem verschiedene Sensoren dran hängen und > einen Eingangs-Pin, der bei fallender Flanke eine Interruptfunktion > auslösen soll, die mir einen bestimmten Sensor, über die SPI-Verbindung, > auslesen soll. > > Wenn jetzt aber der Fall auftritt, dass gerade ein Sensor, der an > besagtem SPI Bus hängt, ausgelesen wird und dabei gleichzeitig die > Interruptfunktion aufgerufen wird, um einen anderen Sensor in diesem > Bussystem auszulesen, führt das zu Kuddelmuddel. Eben die Idee, so etwas machen zu wollen, ist der Grund für deinen Kuddelmuddel. Also mal was Grundsätzliches zu Interrupts: Ein Interrupt ist etwas, das von der µC-Peripherie aktiviert wird, wenn eben genau DIESE ganz dringend einen Service benötigt. Die Betonung liegt auf DIESE. Du hast hingegen irgend einen Eingang, an dem irgend eine Schaltung dran herumziehen kann, wenn sie meint, daß ein Sensor auszulesen sei. Ist ja nett, aber das hat mit dem SPI und dem Sensor rein garnichts zu tun. Es ist eine andere Aktivität als das Auslesen eines Sensors. Also hat so etwas auch rein garnichts in einer Interruptroutine zu suchen. Mach eines: Wenn dein von irgendwo ausgelöster Interrupt kommt, dann generiere daraus einen Event, der in eine Event-Warteschlange eingereiht wird. Und eben diese Event-Warteschlange wird schön der Reihe nach in der Grundschleife in main abgearbeitet. Damit kannst du all die ganze Ausleserei gut genug steuern. Meinetwegen nenne deine Events "LiesSensor1aus", "LiesSensor2aus", "LiesSensor4711aus" oder sonstwie und ordne diesen Events irgend eine passende Nummer zu. Wenn du nicht mehr als rund 250 verschiedene Eventarten brauchst, dann reicht pro Event ein simples Byte in der Queue aus. W.S.
Beitrag #6443630 wurde von einem Moderator gelöscht.
> Event System mit DMA sollte das ohne CPU Intervention hinbekommen...
Das funktioniert wie oben erläutert über gleiches SPI (mehrere Sensoren
...) bis zu einer bestimmten Timing-Anforderung (sofern man Lesen kann
und nicht auf Anfänger-Gesülze hört) über SPI-FIFO.
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.