STM32F4 - analoge Messung mit DAC und DMA

Gast #2796858
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.
Gast #2796884
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!
Gast #2796913
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...
Gast #2797583
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.
Gast #2797701
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?
Gast #2797789
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.
Gast #2797838
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);

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren