Forum: Mikrocontroller und Digitale Elektronik STM32L452RET6P: ADC Scanmode mit DMA nicht OK


von Martin R. (mme)


Lesenswert?

Ich habe ein NUCLEO-L452RE, mit dem ich gerade Versuche mache, bevor ich 
die reale Platine fertige.

Ich möchte 16 Analogwerte dauerhaft im Scanmode wandeln. Die 
ADC-Ergebnisse sollen in ein Array geschrieben werden (DMA). Geht aber 
irgendwie nicht richtig...

Mit der Abfrage eines einzelnen ADC-Kanals ohne DMA gehen die ADC-Kanäle 
(zumindest bei den ersten 4 Kanälen habe ich es getestet) und es kommen 
auch plausible Werte raus, wenn ich eine Spannung 0..3,3V einspeise. 
Quellcode ist wie folgt:
1
HAL_ADC_Start(&hadc1);
2
HAL_ADC_PollForConversion(&hadc1, 100);
3
uiAdcResult = HAL_ADC_GetValue(&hadc1);
4
HAL_ADC_Stop(&hadc1);

PS: Den jeweiligen Kanal des ADC habe ich beim Testen jeweils im Cube 
umgeschaltet.


Den ADC starte ich wie folgt beim Scannen der 16 Kanäle mittels DMA:
1
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ro.uiAdcResults, 16);

Der vom Cube erzeugte Quellcode sieht wie folgt aus:
1
hadc1.Instance = ADC1;
2
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV16;
3
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
4
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
5
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
6
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
7
hadc1.Init.LowPowerAutoWait = DISABLE;
8
hadc1.Init.ContinuousConvMode = ENABLE;
9
hadc1.Init.NbrOfConversion = 16;
10
hadc1.Init.DiscontinuousConvMode = DISABLE;
11
hadc1.Init.NbrOfDiscConversion = 1;
12
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
13
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
14
hadc1.Init.DMAContinuousRequests = ENABLE;
15
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
16
hadc1.Init.OversamplingMode = DISABLE;
17
18
sConfig.Channel = ADC_CHANNEL_1;
19
sConfig.Rank = 1;
20
sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
21
sConfig.SingleDiff = ADC_SINGLE_ENDED;
22
sConfig.OffsetNumber = ADC_OFFSET_NONE;
23
sConfig.Offset = 0;
24
25
sConfig.Channel = ADC_CHANNEL_2;
26
sConfig.Rank = 2;
27
28
sConfig.Channel = ADC_CHANNEL_3;
29
sConfig.Rank = 3;
30
...
31
sConfig.Channel = ADC_CHANNEL_16;
32
sConfig.Rank = 16;

und DMA:
1
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
2
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);

Leider kommen die Daten nicht so wie erwartet in dem Array an.
Arrayfeld 0 und 1 ändern sich nahezu identisch, werden von IN3 was 
kommt.
Arrayfeld 2 und 3 ändern sich nahezu identisch, werden von IN4 was 
kommt.
Arrayfeld 4 ändert sich, werden von IN5 was kommt.
Die restlichen Kanäle sind trotz Pull-Down-Widerstand immer ca. auf Wert 
480.

Sehr kurios das Ganze. Ich komme leider nicht dahinter, woran es liegt. 
Hat jemand eine Idee, was ich falsch mache?

: Bearbeitet durch User
von Martin R. (mme)


Angehängte Dateien:

Lesenswert?

im Anhang die DMA- und ADC-Einstellungen vom Cube...

: Bearbeitet durch User
von Christian K. (the_kirsch)


Lesenswert?

(ist jetzt für den STM32 F1 03 aka "Bluepill")

Ich benutze die HAL nicht, aber wenn ich den ADC im Scanmodus verwende, 
gehe ich wie Folgt vor:

* Die ADC1->SQR Register konfigurieren: Gibt an in welcher Reihenfolge 
die einzelnen ADC-Chanels eingelesen werden sollen.

* Die ADC1->SMPR Register konfigurieren: Wenn nötig wird hier 
eingestellt wie schnell die einzelne ADC-Wandlung dauern soll

* ADC1->CR1 Bit setzen: SCAN

* ADC1->CR2 Bits setzen: CONT und DMA

* DMA Konfigurieren:
    DMA1_Channel1->CPAR = &(ADC1->DR)
    DMA1_Channel1->CMAR = Pointer auf das Array
    DMA1_Channel1->CNDTR = Anzahl, muss mit der SQR Konfiguration 
übereinstimmen, und das Array sollte lang genug sein
    DMA1_Channel1->CCR: MEM2MEM=0, PL=LOW, MSIZE=16, PSIZE=16, MINC=1, 
PINC=0, CIRC=1, DIR=0, TEIE=0, HTIE=0, TCIE=0, EN=0

* DMA starten: DMA1_Channel1->CCR Bit setzen: EN

: Bearbeitet durch User
von Martin R. (mme)


Lesenswert?

Das kuriose ist, daß ich ein anderes Projekt mit dem NUCLEO-F767ZI 
(deutlich größerer Mikrocontroller) habe, bei dem es funktioniert. 
Anzahl der Kanäle ist bei dem aber nicht 16, sondern geringer, aber 
daran sollte es ja nicht liegen.

Cube für den F767ZI sieht beim ADC geringfügig anders aus, aber die 
meisten Parameter sind identisch. Hab gedacht, ich kann das bei dem 
L452REgenau so machen.

von Martin R. (mme)


Angehängte Dateien:

Lesenswert?

Jetzt habe ich das Ganze mal genauer untersucht. Ich habe die Anzahl der 
ADC-Kanäle variiert (siehe Anhang). Bis 5 Kanäle ist es OK. Ab 6 Kanäle 
kommt irgend etwas durcheinander. Ob das ein Fehler des Mikrocontrollers 
ist?

Im Cube ist der STM32L452RETx eingestellt. Auf dem NUCLEO-L452RE ist ein 
STM32L452RET6U bestückt. Das sollte ja eigentlich passen.

Hat jemand eine Erklärung für diesen Effekt?

Habe die Cube-Datei beigefügt. Eventuell sieht jemand eine falsche 
Einstellung. Ich verwende bislang den alten Cube Version 4.23.0. Ich 
denke aber nicht, daß es daran liegt. Den neuen Cube finde ich etwas 
unübersichtlicher.

: Bearbeitet durch User
von Martin R. (mme)


Angehängte Dateien:

Lesenswert?

Ich habe nun mal ein neues Projekt gemacht und das Nucleo-Board im Cube 
ausgewählt. Läßt dauerhaft eine LED blinken und startet den ADC mit DMA 
(7 Kanäle). Im Anhang das komplette Testprojekt.

Das selbe Problem. Kanal 2...5 geht, die anderen zeigen unsinnige Werte 
an. Sollten eigentlich Null sein, da Pull down. Und ca. 4096, wenn ich 
3,3V testweise anlege. Im beigefügten Watch wurde Kanal 2 mit 3,3V 
gespeist und im Array 1 wird der entsprechende Wert angezeigt. Array 0, 
5 und 6 zeigen Müll an.

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