Grüß euch
Ich bräuchte kurz Hilfe bei der Initialisierung des Triple ADC Modus des
STM32F4 inklusive DMA. Die drei ADC sollen im "regular simultaneous
mode" laufen und gleichzeitig zu einer bestimmten Zeit an drei Kanälen
messen. Das funktioniert nach der Initialisierung auch bereits, leider
jedoch nur ein einziges mal.
Führe ich die lib-Funktion "HAL_ADCEx_MultiModeStart_DMA" erneut aus, so
messen die ADCs zwar brav die Werte und füllen das zugehörige ADC_CDR
Register, doch die DMA schläft aus irgendeinem Grund und überträgt die
Werte nicht in meinen Buffer.
Seltsam ist auch, dass ich in unregelmäßigen Abständen einen overrun
interrupt seitens des ADC bekomme. Laut Datenblatt blockiert dieser
künftige DMA Übertragungen, sofern nicht neu initialisiert wird:
>To recover the ADC from OVR state when the DMA is used, follow the steps below:>1. Reinitialize the DMA (adjust destination address and NDTR counter)>2. Clear the ADC OVR bit in ADC_SR register>3. Trigger the ADC to start the conversion.
Ich vermute mal, dass dies mit der nicht-funktionierenden DMA
Übertragung zusammenhängt und der Controller schlichtweg irgendwann das
OVR-Flag setzt, sofern der ADC zwar öfter gestartet wird, das
Ergebnisregister aber nie gelesen? Leider ist die Doku im reference
manual etwas dürftig und ich blick hier noch nicht wirklich durch...
Auf Grund der Länge hab ich den gesamten Initialisierungs-Code als
c-file angehängt. Im main file passiert bezüglich ADC/DMA nur noch
folgendes:
Also ich kenn mich jetzt mit diesem Multimode nicht aus, aber wenn du
1
hadc2.Init.ContinuousConvMode=DISABLE;
setzt, werden dann nicht nur jeweils 1 Messung gemacht, und dann musst
du diesen neu starten?
Und beim DMA muss man noch Buffer size angeben, das fehlt irgendwie
auch.
Ich starte die Messung ja neu (while1) und das Datenregister wird auch
neu befüllt.
Nur die DMA weigert sich die Daten aus dem CDR ab dem zweiten Durchlauf
in meinen Buffer zu schieben.
Die Buffer-Größe wird indirekt durch den 3.Übergabewert der
"HAL_ADCEx_MultiModeStart_DMA" Funktion angegeben. Diese ist Teil der
neuen HAL Libraries...
Das ist mitunter auch das Problem. So gut wie alle Beispiele, die unter
DMA und Co Tutorials im Netz kursieren basieren auf den alten Libs!
Ok, nach einiger Einarbeitungszeit in den DMA Controller konnte ich das
Problem lösen. Es fehlte eine einzige Zeile bei der Initialisierung von
ADC1:
hadc1.Init.DMAContinuousRequests = ENABLE;
Wird diese Definition in der ADC_HandleTypeDef Struktur eingefügt, so
setzt die Lib-Funktion HAL_ADCEx_MultiModeStart_DMA bei jedem Aufruf das
DDS Bit im ADC_CCR Register. Erst jenes feuert den DMA Controller bei
jeder erneuten Konversion.
Eine wesentliche Hürde war für mich die Definition von "Continuous" und
"Discontinuous" die STM auch bei den Libs verwendet. Verwirrend vor
allem deswegen, weil sowohl ersterer als auch zweiterer Modus bei der
Initialisierung ausgeschaltet werden...
Beachten sollte man deshalb:
ADC - continuous: ADC läuft ohne Pause durch
ADC - discontinuous: ADC wird nach einer gewissen Anzahl an Messungen
abgedreht
ADC - weder noch: ADC muss jedes mal erneut getriggert werden, wird
jedoch nicht abgedreht...
DMA - continuous: DMA läuft "ohne Pause" (je nach Trigger halt) durch,
wird jedoch NICHT(!) nach einer gewissen Anzahl an Messungen abgedreht
Ich dachte Anfangs, DMA continuous habe irgendwas mit ADC continuous zu
tun...
Vielen Dank für den Hinweis. War jetzt schon zwei Tage dran, bevor ich
einen Post entdeckt habe. Das Reference Manual zu verstehen ist ja schon
eine Sache. Aber in Kombination mit der neuen, meiner Ansicht nach nicht
optimal dokumentierten, HAL Bib ist das Ganze echt ein bischen
anstrengend.
Danke nochmal das du dich gemeldet hast als das Problem gelöst war!
Hallo,
ich habe eine sehr ähnliche Konfiguration und es funktioniert bei mir
nicht. Einmalig wird ein Wert vom ADC1 übertragen, danach ist Schluß.
Ich habe eine 20kHz-PWM und beim Overflow INT sollen die drei ADCs
simultan einmalig messen. Danach erst wieder beim nächsten INT.
Mit ADC1 getriggert vom Timer2 Overflow INT im Triple Mode funktionierts
wunderbar.
Mit DMA bisher nicht im Geringsten. Mein Board ist ein STM32f429 Disco.
Bitte um Hilfe...und gebe dem vorletzten Satz meines Vorredners absolut
recht ;)
Es funktioniert jetzt :)
Scheinbar gibt es da einen Konflikt mit dem Display im DMAC.
Ohne Display funktioniert es mit Stream 0, oder man benutzt den Stream 4
für den DMA Transfer! Dann geht es auch mit Display :) Wunderbar!
Übrigens reicht es die ADCs vorab einmalig einzuschalten und danach nur
noch die Funktion für den Multimode zyklisch auszuführen.
1
2
//HAL_ADC_Start(&hadc2); //Braucht man nicht zyklisch auszuführen
3
//HAL_ADC_Start(&hadc3); //Braucht man nicht zyklisch auszuführen
Es dauert ca 280 PWM-Takte bis der DMA IRQ-Handler aufgerufen wird.
Dagegen dauert es ohne DMA ca 180 Takte bis der ADC IRQ-Handler
aufgerufen wird.
Verstehe ich etwas falsch, oder ist es ohne DMA wirklich schneller?
Eine eigene Frage?
Dieser Thread ist über 11 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.