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.
>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!
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...
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
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.
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?
> 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.
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);
> 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);