Forum: Mikrocontroller und Digitale Elektronik stm32 Werteübergabe: ADC => DMA =>Speicher => Speicher => DMA => DAC


von Marcus P. (spell)


Lesenswert?

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

von Gebhard R. (Firma: Raich Gerätebau & Entwicklung) (geb)


Lesenswert?

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

von Marcus P. (spell)


Lesenswert?

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

von Gebhard R. (Firma: Raich Gerätebau & Entwicklung) (geb)


Lesenswert?

>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

von Marcus P. (spell)


Lesenswert?

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

von Marcus P. (spell)


Lesenswert?

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.

von Gebhard R. (Firma: Raich Gerätebau & Entwicklung) (geb)


Angehängte Dateien:

Lesenswert?

>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

von Marcus P. (spell)


Lesenswert?

>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

von Marcus P. (spell)


Lesenswert?

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