Hallo, ich wollte gern gleichzeitig Signale mit dem ADC des stm32F107VC aufnehmen und mit dem DAC ausgeben. Signal Ein- wie Ausgabe werde mit Hilfe der DMA durchgeführt. Die Werte des ADCs sollen dabei auf eine Variable geschrieben werden, nach dem Schreiben auf eine andere kopiert werden um von dort mit dem DAC ausgegeben zu werden. Dies soll als Grundlage zum manipulieren und erfassen der Daten dienen. Das Signal hat somit zwischen ADC und DAC ein Timerinterrupt Verzögerung. Angesteuert werden ADC wie DAC vom Timer3 TRGO Interrupt. Wird der Timer zwischendurch abgeschaltet werden weder vom ADC noch vom DAC Daten geschrieben oder ausgegeben, somit nehme ich an, dass die Zeiten eingehalten werden (Momentan 4000 * 4000 auf 72MHz Basis). Neben dem Problem, dass der ADC eher einen Schätzometer als ein Spannungsmesser darstellt habe ich das Problem, dass mein DAC mir irgendwelche sinnlosen wild springenden Werte ausgibt. Diese ändern sich zwar mit Höhe der ADC Spannung, aber nicht sinnvoll (springen auf Null, Drift in die entgegengesetzte Richtung ect.). Der ADC funktioniert vom Prinzip her und der DAC gibt wenn man feste Werte vorgibt oder den Wert in der Variablen hoch zählen lässt auch die Werte aus die man vorgibt. Mein erster Versuch war es die Übergabe direkt in der „while(1)“ Schleife der main zu tätigen (DAC_wertespeicher = ADC_wertespeicher). Dabei dachte ich könnte der DAC eventuell genau auf die Zeit zugegriffen haben wo Daten geschrieben werden und deswegen so merkwürdige Werte ausspucken. Aber auch im Interrupt der DMA des ADC (DMA1_IT_TC1) brachte die Werteübergabe keine Besserung. Wie kann man am besten im Hauptprogramm ohne Interrupt zur geeigneten Zeit Werte übertragen, sprich: welche Flags kann man nutzen bzw. kann man vielleicht auch die Interrupt Flags nutzen ohne die Clocks für einen Interrupt Aufruf zu verschwenden. Und was könnte der Fehler bei der Geschichte sein. Wie gesagt ADC und DAC funktionieren für sich und direktes Schreiben auf die DAC Variable funktioniert auch, nur wenn die Übernahme von ADC- auf DAC Variable stattfindet gibt es Probleme. Gruß Marcus
DMA ist in deinem Fall wahrscheinlich nicht das optimale. Damit werden größere Mengen Daten auf/von einen Buffer geschrieben/gelesen.Wenn ich dich richtig verstanden habe, willst du einen ADC Wert so schnell wie möglich auf den DAC ausgeben. Das geht am besten wenn du das im ADC interrupt machst(ganz ohne DMA). Mit DMA musst du einen Wechselpufferbetrieb einrichten wobei sich damit die Verzögerung unmittelbar mit der Puffergröße ändert. D.h. während der eine Buffer mittels DMA über den ADC beschrieben wird, wird der andere Buffer verarbeitet bzw. ausgegeben.Vorsicht ist beim Bufferwechsel geboten, weil du sicherstellen musst, dass die Bufferadressen in der DMA innerhalb einer ADC Abtastung geändert werden. Grüsse
Meintest du dass die Adressen NICHT innerhalb der ADC Abtastung geändert werden? Ich dachte die DMA wäre auch für einzelne Werte gewinnbringend nutzbar, da in einem ST Beispiel (ext. Trigger) auch die DMA verwendet wurde um auf Tastendruck ADC Werte auslesen zu können. Ich habe mir so eine Entlastung der CPU erhofft, da doch recht oft abgetastet werden sollte. Ich habe mir mal die Speicher-Variable für den DAC angeschaut. Die enthält z.B. den Wert 3000 und ausgegeben bekomme ich einen Wert von 0 bzw. Schwankungen über den gesamten Bereich. Ich versuche mal die Ausgabe ohne DMA. Achso und ich verwende DMA1 für den ADC und DMA2 für den DAC, also dachte ich die beiden könnten gleichzeitig laufen und es würden sich keine Probleme aus irgendwelchen Puffern ergeben. Gruß Marcus
>Ich habe mir so eine Entlastung der CPU erhofft, da doch recht oft >abgetastet werden sollte. was ist oft bei dir? Glaub mir, die CPU ist wirklich sehr schnell. >Ich habe mir mal die Speicher-Variable für den DAC angeschaut. Die >enthält z.B. den Wert 3000 und ausgegeben bekomme ich einen Wert von 0 >bzw. Schwankungen über den gesamten Bereich. Da hat's wohl was. Wenn du mal sagen würdest was du vor hast, würde das die Sache ungemein erleichtern. Grüsse
Ich möchte vorerst ein Sinussignal bis 3KHz abtasten, es aufzeichnen, manipulieren und wieder ausgeben können und das so schnell wie möglich, am besten wäre also wenn das aufgenommene Sample beim nächsten Sample schon wieder ausgegeben wird. Um auf Spitzenwertspeicher und sonstige Hardwarebeschaltungen zu verzichten und die Sache etwas flexibler zu gestalten dachte ich mir ich taste das Signal so oft wie möglich ab und gebe es real wieder aus anstelle einer Lookup table. Zwischendurch möchte ich die Frequenz und die Amlitude über CAN oder USB an einen Rechner schicken bzw. von diesem das Signal beeinflussen. Da sollten bei ausreichend Samples nicht mehr allzuviel übrig bleiben von den einstigen 72Mhz die ich als Sysclock verwende. Ich habe jetzt mal eine Ausgabe ohne DMA geschrieben und die DAC Spannung folgt jetzt "exakt" der ADC Spannung. Sofern man bei dem geribbel was der ADC schon ausließt von exakt sprechen kann. Dazu folgende Zeilen in der While(1) #################### while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); DAC1_Ausgabe_Wert = ADC1_Konv_Wert; DAC_SetChannel1Data(DAC_Align_12b_R ,DAC1_Ausgabe_Wert ); #################### Was mich außerdem wundert ist dass sich die ADC Variable scheinbar viel zu oft ändert, das kann aber auch mein Fehler sein, weil im Debug Modus der Timer wohl weiter läuft, auch wenn ein Breakepoint erreicht ist. Ich werde mal versuchenden den alten Code einzustellen(müsste ihn erst mal etwas lese tauglich gestalten) Eine generelle Frage bleibt noch: bringt es nun etwas einzelne Werte mit der DMA auszulesen? Gruß und danke für die Hilfe bisher
Ich habe gerade den Fehler gefunden.... ich hatte einen Zahlendreher in der DAC Adresse und anstelle der12Bit die 8 Bit Register angegeben, deswegen auch die merkwürdigen Sprünge. Entschuldigt die dumme Fragerei. Sollte trotzdem jemand an billigem Code interessiert sein kann ich ihn trotzdem noch einstellen, wäre aber eher peinlich als Gewinnbringend^^. Die Frage nach besseren Lösungen und der Effizienz der DMAsteht trotzdem noch.
>Ich möchte vorerst ein Sinussignal bis 3KHz abtasten, es aufzeichnen, >manipulieren und wieder ausgeben können und das so schnell wie möglich, >am besten wäre also wenn das aufgenommene Sample beim nächsten Sample >schon wieder ausgegeben wird. Gut, das schließt DMA eigentlich aus. Was meinst du mit manipulieren? >dachte ich mir ich taste das Signal so oft wie möglich ab und >gebe es real wieder aus anstelle einer Lookup table was zum Teufel hat der look-up table mit deinem Signal zu tun? >Was mich außerdem wundert ist dass sich die ADC Variable scheinbar viel >zu oft ändert ??? >Eine generelle Frage bleibt noch: bringt es nun etwas einzelne Werte mit >der DMA auszulesen? Nein, es sollten doch so mindestens 5 Werte sein, sonst ist die DMA-initialisierung aufwändiger. Ich schick dir mal ein Beispiel für 12 Werte mit Wechselbuffer. Grüsse
>Gut, das schließt DMA eigentlich aus. Was meinst du mit manipulieren? Manipulieren heißt in dem Fall für mich z.B. die Amplitude zu ändern. >was zum Teufel hat der look-up table mit deinem Signal zu tun? Die look-up table hat in so fern etwas mit meinem Signal zu tun, dass ich momentan nur ein reines Sinussignal ausmessen möchte und für die Rekonstruktion theoretisch nur die Amplitude und die Frequenz nötig wären. Die Signalform würde man sich in diesem Fall aus einer look-up table holen. >??? Ich hatte am Anfang das Gefühl, dass sich die Variable schneller ändert, als ich es dem ADC durch den Timer vorgegeben habe. >Nein, es sollten doch so mindestens 5 Werte sein, sonst ist die >DMA-initialisierung aufwändiger. >Ich schick dir mal ein Beispiel für 12 Werte mit Wechselbuffer. Gut dann nehme ich die DMA wieder raus. Mit welcher Methode kann man eigentlich testen wieviele Zyklen man noch zur Verfügung hat, ich dachte ich lasse einfach mal eine Variable hochzählen vom ADC Start bis ADC Ende, das scheint nicht gerade von Erfolg gekrönt zu sein. Danke für den Hinweis und das Beispiel, ich schau es mir gleich mal an. Gruß Marcus
Im übrigen weiß ich, dass ich die DAC und ADC aus dem Timer IRQ heraus starten kann, aber wie kann ich sie direkt durch das "ADC_ExternalTrigConv_T3_TRGO" starten? Ohne DMA scheint diese Funktion nicht mehr zu greifen.
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.