Forum: Mikrocontroller und Digitale Elektronik ADC / DMA Problem beim STM32F030


von Tobi (Gast)


Lesenswert?

Hallo zusammen,

ich möchte gerne mit einem STM32F030 zwei externe ADC Signale und den 
internen TMP Sensor kontinuierlich abtasten lassen. Die Werte sollen 
gleich mit Hilfe des DMAs in ein Array geschrieben werden.
Leider komme ich nicht weiter. Als Programmierumgebung verwende ich 
CooCox. Wenn ich nach ein paar Sekunde im Debug Modus anhalte und mir 
das Array "online" ansehe, steht im ersten Feld 62 und die beiden 
weiteren auf 0.

Anbei meine Init Routine. Bei dieser habe ich mich an dem Beispiel von 
CooCox orientiert. Habe ich etwas vergessen zu initialisieren?

Vielen Dank für eure Hilfe.

Gruß
Tobi
1
#define ADC1_DR_Address    0x40012440
2
uint16_t ADC_Werte[3];
3
4
void initADC(void)
5
{
6
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
7
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE);
8
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
9
10
  DMA_DeInit(DMA1_Channel1);
11
  ADC_DeInit(ADC1);
12
13
  GPIO_InitTypeDef GPIO_InitDef;
14
  GPIO_InitDef.GPIO_Mode = GPIO_Mode_AN;
15
  GPIO_InitDef.GPIO_PuPd = GPIO_PuPd_NOPULL ;
16
  GPIO_InitDef.GPIO_Pin = GPIO_Pin_0  |  // ADC Versorgungsspannung
17
              GPIO_Pin_1  ;  // ADC Motorstrom
18
  GPIO_Init(GPIOA, &GPIO_InitDef);
19
20
  DMA_InitTypeDef DMA_InitStructure;
21
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;
22
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_Werte;
23
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
24
  DMA_InitStructure.DMA_BufferSize = 3;
25
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
26
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
27
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
28
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
29
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
30
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
31
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
32
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);
33
  DMA_Cmd(DMA1_Channel1, ENABLE);
34
  ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);
35
  ADC_DMACmd(ADC1, ENABLE);
36
37
  ADC_InitTypeDef ADC_InitStructure;
38
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
39
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
40
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
41
  //ADC_InitStructure.ADC_ExternalTrigConv = ;
42
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
43
  ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;
44
  ADC_Init(ADC1, &ADC_InitStructure);
45
46
  ADC_ChannelConfig(ADC1, ADC_Channel_0, ADC_SampleTime_55_5Cycles);       // ADC Versorgungsspannung
47
  ADC_ChannelConfig(ADC1, ADC_Channel_1, ADC_SampleTime_55_5Cycles);       // ADC Motorstrom
48
  ADC_ChannelConfig(ADC1, ADC_Channel_TempSensor, ADC_SampleTime_55_5Cycles); // interner Temperatursensor
49
  ADC_TempSensorCmd(ENABLE);
50
51
  ADC_GetCalibrationFactor(ADC1);
52
  ADC_Cmd(ADC1, ENABLE);
53
  while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN));
54
  ADC_StartOfConversion(ADC1);
55
}

von jzjjf (Gast)


Lesenswert?

wenn ich mich recht erinnere:
du hast nur einen ADC ( dein ADC1 )
der soll aber 3 eingänge abtasten...
Wo schaltest du zwischen den eingängen um?
der DMA macht das leider nicht von alleine...
du musst nach erfolgem samplen den eingang umschalten ( MUX )

Es gab eine automatik .. aber das kenne ich nicht aus dem kopf.
vlt jemand hier?

ansonst timerintrrupt und ein signal geben im haupttask.
immer wenn der timer abläuft umschalten und wert samplen

von Tobi (Gast)


Lesenswert?

Bei meinem STM32F103 übernimmt diese Aufgabe der DMA und die Channel 
Konfiguration. Funktioniert dies beim STM32F030 nicht?!

von Haas (Gast)


Lesenswert?

Hi,

startest du den ADC auch im DMA Mode?

z.B. HAL_ADC_Start_DMA(...

von Tobi (Gast)


Lesenswert?

Das sollte meiner Meinung nach über die folgenden Befehle angewiesen 
werden:
1
  ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);
2
  ADC_DMACmd(ADC1, ENABLE);

von Stefan S. (chiefeinherjar)


Lesenswert?

Also beim F103 kann man die Reihenfolge und Anzahl der Kanäle angeben, 
die dann automatisch umgeschaltet werden.
Bei deinem weiß ich das aus dem Kopf gerade nicht...

von Tobi (Gast)


Lesenswert?

Stefan S. schrieb:
> Also beim F103 kann man die Reihenfolge und Anzahl der Kanäle angeben,
> die dann automatisch umgeschaltet werden.
> Bei deinem weiß ich das aus dem Kopf gerade nicht...

Ja, das stimmt. Beim F103 gibt es in der Zeile
1
ADC_ChannelConfig(ADC1, ADC_Channel_0, ADC_SampleTime_55_5Cycles);
einen Übergabeparameter mehr. Da konnte man die Reihenfolge festlegen, 
in welchen die ADCs Eingänge abgearbeitet werden. Beim F030 kann man da 
nichts übergeben oder einstellen. Ich vermute, dass die Reihenfolge der 
Funktion ADC_ChannelConfig dies übernimmt ... ?!

von Stefan S. (chiefeinherjar)


Lesenswert?

Also beim F103 kann man die Reihenfolge und Anzahl der Kanäle angeben, 
die dann automatisch umgeschaltet werden.
Bei deinem weiß ich das aus dem Kopf gerade nicht...

Tobi schrieb:
> Ich vermute, dass die Reihenfolge der Funktion ADC_ChannelConfig dies
> übernimmt ... ?!

Wie wäre es damit, daß Reference-Manual zu konsultieren? - da steht 
alles drin, was man wissen muss... Wahlweise natürlich passende 
App-Notes.

von Tobi (Gast)


Lesenswert?

Stefan S. schrieb:
> Wie wäre es damit, daß Reference-Manual zu konsultieren? - da steht
> alles drin, was man wissen muss... Wahlweise natürlich passende
> App-Notes.

Auch nach längerem Probieren und Lesen komme ich leider nicht weiter. 
Mittlerweile habe ich gelesen, dass die Abarbeitung beim F030 der Reihe 
nach erfolgt, entweder von ADC Channel 0 - 18 oder eben von 18 - 0, bei 
den Kanälen die eingestellt wurden. In meinem Fall über die Funktion
1
ADC_ChannelConfig(ADC1, ADC_Channel_0, ADC_SampleTime_55_5Cycles)
Auch bezüglich der Abfolge der Init habe ich keine anderen Erkenntnisse 
in den Application Notes herausgefunden.
Mittlerweile habe ich diverse Möglichkeiten probiert. Getriggert über 
Timer15 oder manuell über Software alle 100 ms, nur einen ADC Kanal. 
Jedoch liefert alles immer nur den Wert 0. Als wenn ich einen Clock 
vergessen hätte zu aktiveren.
Das einzige was zu funktionieren scheint, ist die Kalibrierung. Diese 
liefert den Wert 62 zurück.
Habe auch mal die Systemclocks ausgelesen, ob ADC zu schnell läuft 
(größer 14MHz).
Das Ergebnis:
SYSCLK    48.000.000
HCLK      48.000.000
PCLK      48.000.000
ADCCLK    14.000.000
CECCLK        32.786
I2C1CLK    8.000.000
USART1CLK 48.000.000

Mikrocontroller wurde auch schon mal getauscht.
Versorgungsspannung am VDDA Pin liegt ebenfalls an. Im Application Note 
steht noch 1µF + 10nF. Momentan ist dieser lediglich über einen 100nF 
versorgt. Aber kann das zum Totalausfall führen?!
Spannung am Oszi sieht gut aus mit 3,3V.
Bei meinem anderen Projekten mit STM32F407 oder STM32F103 gab es da nie 
Probleme? Ist beim STM32F030 irgendwas besonderes noch zu beachten?!


Andere Programmteile funktionieren wunderbar. Taster ein/ auslesen, zwei 
7-Segment Anzeigen ansteuern, UART RX & TX.

Vielleicht hat ja noch jemand einen Rat?!

von Christopher J. (christopher_j23)


Lesenswert?

Tobi schrieb:
> Vielleicht hat ja noch jemand einen Rat?!

Reference Manual lesen statt Copy-Paste-Programmierung. Btw: Coocox ist 
absolut veraltet. Nimm besser SW4STM32 oder TrueStudio

von mts (Gast)


Lesenswert?

Tobi schrieb:

> Vielleicht hat ja noch jemand einen Rat?!

Was steht den in ADC_CHSELR?

von Tobi (Gast)


Angehängte Dateien:

Lesenswert?

mts schrieb:
> Was steht den in ADC_CHSELR?

Anbei im Debug Modus nach ca. 3 Sekunden pausiert und ausgelesen.

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.