Forum: Mikrocontroller und Digitale Elektronik STM32F4 - triple ADC mit DMA funktioniert nur 1x


von Vincent H. (vinci)


Angehängte Dateien:

Lesenswert?

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:
1
uint16_t buffer[3] = {0};
2
3
adc_init();
4
5
while(1)
6
{
7
    HAL_ADC_Start(&hadc2);
8
    HAL_ADC_Start(&hadc3);
9
    HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t*)buffer, 3);
10
    HAL_Delay(100);
11
}


tia

von Patrick B. (p51d)


Lesenswert?

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.

von Vincent H. (vinci)


Lesenswert?

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!

von Vincent H. (vinci)


Angehängte Dateien:

Lesenswert?

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...

von Epi (Gast)


Lesenswert?

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!

von Christof K. (ckris)


Angehängte Dateien:

Lesenswert?

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 ;)

: Bearbeitet durch User
von Christof K. (ckris)


Lesenswert?

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
4
HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t*)buffer, 3);

Etwas befremdlich ist, TCIE und HTIE werden von der Funktion selbst 
gesetzt und gelöscht. Dennoch wird der Interrupt scheinbar nur einmalig 
ausgelöst.

: Bearbeitet durch User
von Christof K. (ckris)


Lesenswert?

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?

: Bearbeitet durch User
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.