Forum: Mikrocontroller und Digitale Elektronik STM32F4 - analoge Messung mit DAC und DMA


von Martin (Gast)


Lesenswert?

Hallo,

ich bin noch ziemlich unerfahren in der Mikrocontrollerprogrammierung 
und wollte zur Übung einen analogen Spannungswert über PC13 einlesen. 
Damit die CPU entlastet wird möchte ich DMA benutzen. Folgender 
Quellcode kam mit Hilfe eines Tutorials zu stande:

http://nopaste.info/1af854aa14.html

Ich benutze das STM32F4 Board von ST und die Software Keil.

Ziel des Programms soll es sein, je nach angelegter Spannung entweder 
eine rote oder blaue zum Leuchten zu bringen. Dies klappt leider noch 
nicht, es leuchtet unabhängig vom Poti nur die blaue. Die Variable 
"ADC3ConvertedValue" scheint nicht korrekt beschrieben zu werden.

Falls mein Problem trivial sein sollte, bitte ich um Nachsicht. Ich 
freue mich über jede Hilfestellung.

von Bitte das JPG-Format nur für Fotos und Scans verwe (Gast)


Lesenswert?

>ich bin noch ziemlich unerfahren in der Mikrocontrollerprogrammierung

>Damit die CPU entlastet wird

Die arme CPU!

> möchte ich DMA benutzen
Das widerspricht sich mit der obigen Aussage.

Probier´s mal ohne DMA. Wenn das geht, kommt der nächste
Schritt.

Nicht alles auf einmal wollen!

von Bitte das JPG-Format nur für Fotos und Scans verwe (Gast)


Lesenswert?

>Ich benutze das STM32F4 Board

Vermutlich das Discovery?

Das hat einen eingebauten Debugger.
Warum nicht den benutzen?

von Bitte das JPG-Format nur für Fotos und Scans verwe (Gast)


Lesenswert?

Sehe gerade

> ADC_SoftwareStartConv(ADC3);

Wenn das tatsächlich tut, was der Name suggeriert, muss
das natürlich in die while (1) - Schleife. Sonst rechnet
Deine Schleife immer nur endlos den allerersten Wert um...

DMA_InitStructure.DMA_BufferSize = 1;
dürfte falsch sein, da es sich bei ADC3ConvertedValue um eine 32-Bit 
Variable handelt,

Übrigens: Von wegen DMA und CPU entlasten -
mit einer CPU, die in einer Schleife sinnlos auf das Ergebnis
eines DMA-Transfers wartet, hast Du kein Mitleid?

Wenn Du´s "richtig" machen willst, müsstest
Du die CPU nach StartConv () in den Schlaf schicken (WFE oder WFI)
und Du brauchst Du einen DMA-Interrupt-Handler, der sie
daraus wieder aufweckt, wenn der Wert da ist, dann Ausgabe,
neue Umwandlung starten und wieder schalfen...

(und vielleicht noch andere Dinge).

Aber wie gesagt. Erst die einfachen Sachen probieren...

von Moritz M. (moritz_m72)


Lesenswert?

Hallo,

was du meinst ist ein ADC (Analog Digital Converter) zu messen analoger 
Spannungen. Mit einem DAC (Digital Analog Converter) kann man analoge 
Spannungen erzeugen.

Moritz

von frame (Gast)


Lesenswert?

Ich kann im ersten Moment keinen Fehler entdecken.
Dein Code ist von einem Beispielprojekt aus der Std_Periph_Driver 
Library für den STM32F4 abgeleitet. Bei mir läuft ein ähnliches Beispiel 
ohne Probleme.

>> ADC_SoftwareStartConv(ADC3);
>
> Wenn das tatsächlich tut, was der Name suggeriert, muss
> das natürlich in die while (1) - Schleife. Sonst rechnet
> Deine Schleife immer nur endlos den allerersten Wert um...

Muß es nicht.
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
Das bedeutet, das der Kanal nach dem ersten Start permanent sampelt, bis 
er explizit gestoppt wird.

Ich mache das folgendermaßen:
Ein Potentiometer von 10k (1k ... 50k) zwischen 3.3V und GND 
anschließen, Schleifer auf den Analogeingang.
Am Schleifer drehen und im Debugger den Code an einer passenden Stelle 
anhalten, zum Beispiel hier:
ADC3ConvertedVoltage = ADC3ConvertedValue *3300/0xFFF;
Dann sollte der ADC-Wert dem Schleifer folgen.
Außerdem kannst du im Debugger in ADC3->DR nachschauen. Dort sollte der 
letzte Wandlerwert stehen.

von Martin (Gast)


Lesenswert?

Schon mal vielen Dank für eure Rückmeldungen.

frame schrieb:
> Außerdem kannst du im Debugger in ADC3->DR nachschauen. Dort sollte der
> letzte Wandlerwert stehen.

Wo finde ich diese Möglichkeit?

Ich habe das Watchwindow eingeschaltet und beobachte die Variablen bei 
einem Haltepunkt in der while-Schleife.
Sowohl bei ADC3ConvertedValue als auch ADC3ConvertedVoltage werden Werte 
angezeigt (zwischen 50-150). Sie ändern sich bei Neustart des 
Controllers obwohl ich an der Spannung nichts geändert habe, reagieren 
jedoch nicht auf die eine andere Poti-Stellung. Ich habe ja einen 12 bit 
ADC konfiguriert und habe eigentlich Werte zwischen 0 und 4096 erwartet. 
Habe ich irgendwo einen Denkfehler?

von frame (Gast)


Lesenswert?

> Wo finde ich diese Möglichkeit?

Habe gerade die 'Evaluierungsversion' von Keil hervorgekramt - da gibt 
es wirklich kein Debugfenster, um die Peripherieregister anzuzeigen. Das 
geht wahrscheinlich erst in der Bezahlversion.
Notfalls müßtest du im Datenblatt/Referenzmanual nachschauen, auf 
welcher Adresse das Register landet, um die ADC-Register in einem 
'Memory Window' beobachten zu können.
Normalerweise benutze ich Crossworks, da geht das recht komfortabel.


> Habe ich irgendwo einen Denkfehler?

Theoretisch nicht.
Nach dem Aufruf von ADC_SoftwareStartConv(ADC3) sollte der ADC permanent 
sampeln, und die DMA mit EOC den Wert dauernd in deine Variable 
übertragen.


Bist du dir sicher, den richtigen ADC-Eingang zu benutzen ?
Ich habe, wie gesagt, mein Projekt anscheinend vom gleichen Beispiel aus 
der Periph_Driver Library abgeleitet. Allerdings war das Beispiel für 
das STM3240G-Evaluationboard, nicht für das STM32F4-Discovery.
Deswegen habe ich auf PC0 (AIN_10) umgestellt, und außerdem die 
DMA-Konfiguration geändert, weil ich 1024 sukzessive Werte brauche.
Ich bin mir nicht ganz schlüssig, welches Board du verwendest - prüfe 
lieber nach, daß der Pin nicht anderweitig verbaut ist.

von Martin (Gast)


Lesenswert?

Ich habe das STM32F407VGT6 Board. Den Pin habe ich ja abgeändert auf 
PC13. Dort liegt auch die Spannung vom Poti an. Laut Manual ist der Pin 
Free I/O.

> GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
> GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
> GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
> GPIO_Init(GPIOC, &GPIO_InitStructure);
>
>RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);

von frame (Gast)


Lesenswert?

> Den Pin habe ich ja abgeändert auf  PC13.
> ...
> GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;


Und das auch ?
ADC_RegularChannelConfig (ADC3, ADC_Channel_X, 1, 
ADC_SampleTime_5Cycles);

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.